1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package libcore.reflect; 18 19 import dalvik.annotation.Signature; 20 21 import libcore.util.EmptyArray; 22 23 import java.lang.annotation.Annotation; 24 25 /** 26 * Mirror of the data structure specified in {@link dalvik.annotation.Record}. But annotation type 27 * isn't allowed to have a 2D array element, but it's stored in the .dex format. This is regular 28 * class created to store the annotation elements consumed internally by libcore. 29 * 30 * Please see {@link dalvik.annotation.Record} for detailed javadoc for each element. 31 */ 32 public final class RecordComponents { 33 34 /** 35 * VISIBILITY_RUNTIME value. 36 * See https://source.android.com/docs/core/runtime/dex-format#visibility 37 */ 38 private static final byte DEX_ANNOTATION_VISIBILITY_RUNTIME = 1; 39 40 private final Class<?> declaringClass; 41 42 private final String[] componentNames; 43 private final Class<?>[] componentTypes; 44 private final Signature[] componentSignatures; 45 private byte[][] componentAnnotationVisibilities; 46 private Annotation[][] componentAnnotations; 47 48 /** 49 * Created an empty instance and the fields will be filled by the ART runtime. 50 */ RecordComponents(Class<?> declaringClass)51 public RecordComponents(Class<?> declaringClass) { 52 this.declaringClass = declaringClass; 53 componentNames = readElement("componentNames", String[].class); 54 componentTypes = readElement("componentTypes", Class[].class); 55 componentSignatures = readElement("componentSignatures", Signature[].class); 56 } 57 readElement(String name, Class<T[]> array_class)58 private <T> T[] readElement(String name, Class<T[]> array_class) { 59 return declaringClass.getRecordAnnotationElement(name, array_class); 60 } 61 getNames()62 public String[] getNames() { 63 return componentNames; 64 } 65 getTypes()66 public Class<?>[] getTypes() { 67 return componentTypes; 68 } 69 70 /** 71 * @return null if no signature is found. 72 */ getGenericSignature(int index)73 public String getGenericSignature(int index) { 74 Signature signature = null; 75 if (componentSignatures != null && index >= 0 && index < componentSignatures.length) { 76 signature = componentSignatures[index]; 77 } 78 if (signature == null) { 79 return null; 80 } 81 StringBuilder result = new StringBuilder(); 82 for (String s : signature.value()) { 83 result.append(s); 84 } 85 return result.toString(); 86 } 87 88 /** 89 * Return all annotations visible at runtime. 90 * 91 * @param index Component index 92 */ getVisibleAnnotations(int index)93 public Annotation[] getVisibleAnnotations(int index) { 94 synchronized (this) { 95 if (componentAnnotations == null) { 96 Annotation[][] allAnnotations = readElement("componentAnnotations", 97 Annotation[][].class); 98 byte[][] allVisibilities = readElement("componentAnnotationVisibilities", 99 byte[][].class); 100 if (allAnnotations == null) { 101 allAnnotations = new Annotation[0][]; 102 } 103 if (allVisibilities == null) { 104 allVisibilities = new byte[0][]; 105 } 106 componentAnnotationVisibilities = allVisibilities; 107 componentAnnotations = allAnnotations; 108 } 109 } 110 Annotation[][] allAnnotations = componentAnnotations; 111 byte[][] allVisibilities = componentAnnotationVisibilities; 112 113 if (index < 0 || index >= allAnnotations.length || allAnnotations[index] == null) { 114 return EmptyArray.ANNOTATION; 115 } 116 117 Annotation[] annotations = allAnnotations[index]; 118 int size = annotations.length; 119 if (size == 0) { 120 return annotations; 121 } 122 byte[] visibilities = index < allVisibilities.length ? allVisibilities[index] : null; 123 if (visibilities == null) { 124 return EmptyArray.ANNOTATION; 125 } 126 127 int minSize = Math.min(visibilities.length, size); 128 int visibleAnnotationsSize = 0; 129 for (int i = 0; i < minSize; i++) { 130 if (visibilities[i] == DEX_ANNOTATION_VISIBILITY_RUNTIME) { 131 visibleAnnotationsSize++; 132 } 133 } 134 135 // In most cases, component has no invisible annotations and return all annotations here. 136 if (visibleAnnotationsSize == size) { 137 return annotations; 138 } 139 140 // slow path 141 Annotation[] visibleAnnotations = new Annotation[visibleAnnotationsSize]; 142 int j = 0; 143 for (int i = 0; i < minSize; i++) { 144 if (visibilities[i] == DEX_ANNOTATION_VISIBILITY_RUNTIME) { 145 visibleAnnotations[j] = annotations[i]; 146 j++; 147 } 148 } 149 return visibleAnnotations; 150 } 151 } 152