Annotation.cpp revision 889344df4bb5cace0b8efbc1e3114406df95ceea
1/*
2 * Copyright (C) 2008 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 * Annotations.
18 *
19 * We're not expecting to make much use of runtime annotations, so speed vs.
20 * space choices are weighted heavily toward small size.
21 *
22 * It would have been nice to treat "system" annotations in the same way
23 * we do "real" annotations, but that doesn't work.  The chief difficulty
24 * is that some of them have member types that are not legal in annotations,
25 * such as Method and Annotation.  Another source of pain comes from the
26 * AnnotationDefault annotation, which by virtue of being an annotation
27 * could itself have default values, requiring some additional checks to
28 * prevent recursion.
29 *
30 * It's simpler, and more efficient, to handle the system annotations
31 * entirely inside the VM.  There are empty classes defined for the system
32 * annotation types, but their only purpose is to allow the system
33 * annotations to share name space with standard annotations.
34 */
35#include "Dalvik.h"
36
37// fwd
38static Object* processEncodedAnnotation(const ClassObject* clazz,\
39    const u1** pPtr);
40static bool skipEncodedAnnotation(const ClassObject* clazz, const u1** pPtr);
41
42/*
43 * System annotation descriptors.
44 */
45static const char* kDescrAnnotationDefault
46                                    = "Ldalvik/annotation/AnnotationDefault;";
47static const char* kDescrEnclosingClass
48                                    = "Ldalvik/annotation/EnclosingClass;";
49static const char* kDescrEnclosingMethod
50                                    = "Ldalvik/annotation/EnclosingMethod;";
51static const char* kDescrInnerClass = "Ldalvik/annotation/InnerClass;";
52static const char* kDescrMemberClasses
53                                    = "Ldalvik/annotation/MemberClasses;";
54static const char* kDescrSignature  = "Ldalvik/annotation/Signature;";
55static const char* kDescrThrows     = "Ldalvik/annotation/Throws;";
56
57/*
58 * Read an unsigned LEB128 value from a buffer.  Advances "pBuf".
59 */
60static u4 readUleb128(const u1** pBuf)
61{
62    u4 result = 0;
63    int shift = 0;
64    const u1* buf = *pBuf;
65    u1 val;
66
67    do {
68        /*
69         * Worst-case on bad data is we read too much data and return a bogus
70         * result.  Safe to assume that we will encounter a byte with its
71         * high bit clear before the end of the mapped file.
72         */
73        assert(shift < 32);
74
75        val = *buf++;
76        result |= (val & 0x7f) << shift;
77        shift += 7;
78    } while ((val & 0x80) != 0);
79
80    *pBuf = buf;
81    return result;
82}
83
84/*
85 * Get the annotations directory item.
86 */
87static const DexAnnotationsDirectoryItem* getAnnoDirectory(DexFile* pDexFile,
88    const ClassObject* clazz)
89{
90    const DexClassDef* pClassDef;
91
92    /*
93     * Find the class def in the DEX file.  For better performance we should
94     * stash this in the ClassObject.
95     */
96    pClassDef = dexFindClass(pDexFile, clazz->descriptor);
97    assert(pClassDef != NULL);
98    return dexGetAnnotationsDirectoryItem(pDexFile, pClassDef);
99}
100
101/*
102 * Return a zero-length array of Annotation objects.
103 *
104 * TODO: this currently allocates a new array each time, but I think we
105 * can get away with returning a canonical copy.
106 *
107 * Caller must call dvmReleaseTrackedAlloc().
108 */
109static ArrayObject* emptyAnnoArray()
110{
111    return dvmAllocArrayByClass(
112        gDvm.classJavaLangAnnotationAnnotationArray, 0, ALLOC_DEFAULT);
113}
114
115/*
116 * Return an array of empty arrays of Annotation objects.
117 *
118 * Caller must call dvmReleaseTrackedAlloc().
119 */
120static ArrayObject* emptyAnnoArrayArray(int numElements)
121{
122    Thread* self = dvmThreadSelf();
123    ArrayObject* arr;
124    int i;
125
126    arr = dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArrayArray,
127            numElements, ALLOC_DEFAULT);
128    if (arr != NULL) {
129        ArrayObject** elems = (ArrayObject**)(void*)arr->contents;
130        for (i = 0; i < numElements; i++) {
131            elems[i] = emptyAnnoArray();
132            dvmReleaseTrackedAlloc((Object*)elems[i], self);
133        }
134    }
135
136    return arr;
137}
138
139/*
140 * Read a signed integer.  "zwidth" is the zero-based byte count.
141 */
142static s4 readSignedInt(const u1* ptr, int zwidth)
143{
144    s4 val = 0;
145    int i;
146
147    for (i = zwidth; i >= 0; --i)
148        val = ((u4)val >> 8) | (((s4)*ptr++) << 24);
149    val >>= (3 - zwidth) * 8;
150
151    return val;
152}
153
154/*
155 * Read an unsigned integer.  "zwidth" is the zero-based byte count,
156 * "fillOnRight" indicates which side we want to zero-fill from.
157 */
158static u4 readUnsignedInt(const u1* ptr, int zwidth, bool fillOnRight)
159{
160    u4 val = 0;
161    int i;
162
163    if (!fillOnRight) {
164        for (i = zwidth; i >= 0; --i)
165            val = (val >> 8) | (((u4)*ptr++) << 24);
166        val >>= (3 - zwidth) * 8;
167    } else {
168        for (i = zwidth; i >= 0; --i)
169            val = (val >> 8) | (((u4)*ptr++) << 24);
170    }
171    return val;
172}
173
174/*
175 * Read a signed long.  "zwidth" is the zero-based byte count.
176 */
177static s8 readSignedLong(const u1* ptr, int zwidth)
178{
179    s8 val = 0;
180    int i;
181
182    for (i = zwidth; i >= 0; --i)
183        val = ((u8)val >> 8) | (((s8)*ptr++) << 56);
184    val >>= (7 - zwidth) * 8;
185
186    return val;
187}
188
189/*
190 * Read an unsigned long.  "zwidth" is the zero-based byte count,
191 * "fillOnRight" indicates which side we want to zero-fill from.
192 */
193static u8 readUnsignedLong(const u1* ptr, int zwidth, bool fillOnRight)
194{
195    u8 val = 0;
196    int i;
197
198    if (!fillOnRight) {
199        for (i = zwidth; i >= 0; --i)
200            val = (val >> 8) | (((u8)*ptr++) << 56);
201        val >>= (7 - zwidth) * 8;
202    } else {
203        for (i = zwidth; i >= 0; --i)
204            val = (val >> 8) | (((u8)*ptr++) << 56);
205    }
206    return val;
207}
208
209
210/*
211 * ===========================================================================
212 *      Element extraction
213 * ===========================================================================
214 */
215
216/*
217 * An annotation in "clazz" refers to a method by index.  This just gives
218 * us the name of the class and the name and signature of the method.  We
219 * need to find the method's class, and then find the method within that
220 * class.  If the method has been resolved before, we can just use the
221 * results of the previous lookup.
222 *
223 * Normally we do this as part of method invocation in the interpreter, which
224 * provides us with a bit of context: is it virtual or direct, do we need
225 * to initialize the class because it's a static method, etc.  We don't have
226 * that information here, so we have to do a bit of searching.
227 *
228 * Returns NULL if the method was not found (exception may be pending).
229 */
230static Method* resolveAmbiguousMethod(const ClassObject* referrer, u4 methodIdx)
231{
232    DexFile* pDexFile;
233    ClassObject* resClass;
234    Method* resMethod;
235    const DexMethodId* pMethodId;
236    const char* name;
237
238    /* if we've already resolved this method, return it */
239    resMethod = dvmDexGetResolvedMethod(referrer->pDvmDex, methodIdx);
240    if (resMethod != NULL)
241        return resMethod;
242
243    pDexFile = referrer->pDvmDex->pDexFile;
244    pMethodId = dexGetMethodId(pDexFile, methodIdx);
245    resClass = dvmResolveClass(referrer, pMethodId->classIdx, true);
246    if (resClass == NULL) {
247        /* note exception will be pending */
248        ALOGD("resolveAmbiguousMethod: unable to find class %d", methodIdx);
249        return NULL;
250    }
251    if (dvmIsInterfaceClass(resClass)) {
252        /* method is part of an interface -- not expecting that */
253        ALOGD("resolveAmbiguousMethod: method in interface?");
254        return NULL;
255    }
256
257    // TODO - consider a method access flag that indicates direct vs. virtual
258    name = dexStringById(pDexFile, pMethodId->nameIdx);
259
260    DexProto proto;
261    dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
262
263    if (name[0] == '<') {
264        /*
265         * Constructor or class initializer.  Only need to examine the
266         * "direct" list, and don't need to look up the class hierarchy.
267         */
268        resMethod = dvmFindDirectMethod(resClass, name, &proto);
269    } else {
270        /*
271         * Do a hierarchical scan for direct and virtual methods.
272         *
273         * This uses the search order from the VM spec (v2 5.4.3.3), which
274         * seems appropriate here.
275         */
276        resMethod = dvmFindMethodHier(resClass, name, &proto);
277    }
278
279    return resMethod;
280}
281
282/*
283 * constants for processAnnotationValue indicating what style of
284 * result is wanted
285 */
286enum AnnotationResultStyle {
287    kAllObjects,         /* return everything as an object */
288    kAllRaw,             /* return everything as a raw value or index */
289    kPrimitivesOrObjects /* return primitives as-is but the rest as objects */
290};
291
292/*
293 * Recursively process an annotation value.
294 *
295 * "clazz" is the class on which the annotations are defined.  It may be
296 * NULL when "resultStyle" is "kAllRaw".
297 *
298 * If "resultStyle" is "kAllObjects", the result will always be an Object of an
299 * appropriate type (in pValue->value.l).  For primitive types, the usual
300 * wrapper objects will be created.
301 *
302 * If "resultStyle" is "kAllRaw", numeric constants are stored directly into
303 * "pValue", and indexed values like String and Method are returned as
304 * indexes.  Complex values like annotations and arrays are not handled.
305 *
306 * If "resultStyle" is "kPrimitivesOrObjects", numeric constants are stored
307 * directly into "pValue", and everything else is constructed as an Object
308 * of appropriate type (in pValue->value.l).
309 *
310 * The caller must call dvmReleaseTrackedAlloc on returned objects, when
311 * using "kAllObjects" or "kPrimitivesOrObjects".
312 *
313 * Returns "true" on success, "false" if the value could not be processed
314 * or an object could not be allocated.  On allocation failure an exception
315 * will be raised.
316 */
317static bool processAnnotationValue(const ClassObject* clazz,
318    const u1** pPtr, AnnotationValue* pValue,
319    AnnotationResultStyle resultStyle)
320{
321    Thread* self = dvmThreadSelf();
322    Object* elemObj = NULL;
323    bool setObject = false;
324    const u1* ptr = *pPtr;
325    u1 valueType, valueArg;
326    int width;
327    u4 idx;
328
329    valueType = *ptr++;
330    valueArg = valueType >> kDexAnnotationValueArgShift;
331    width = valueArg + 1;       /* assume, correct later */
332
333    ALOGV("----- type is 0x%02x %d, ptr=%p [0x%06x]",
334        valueType & kDexAnnotationValueTypeMask, valueArg, ptr-1,
335        (ptr-1) - (u1*)clazz->pDvmDex->pDexFile->baseAddr);
336
337    pValue->type = valueType & kDexAnnotationValueTypeMask;
338
339    switch (valueType & kDexAnnotationValueTypeMask) {
340    case kDexAnnotationByte:
341        pValue->value.i = (s1) readSignedInt(ptr, valueArg);
342        if (resultStyle == kAllObjects) {
343            elemObj = (Object*) dvmBoxPrimitive(pValue->value,
344                        dvmFindPrimitiveClass('B'));
345            setObject = true;
346        }
347        break;
348    case kDexAnnotationShort:
349        pValue->value.i = (s2) readSignedInt(ptr, valueArg);
350        if (resultStyle == kAllObjects) {
351            elemObj = (Object*) dvmBoxPrimitive(pValue->value,
352                        dvmFindPrimitiveClass('S'));
353            setObject = true;
354        }
355        break;
356    case kDexAnnotationChar:
357        pValue->value.i = (u2) readUnsignedInt(ptr, valueArg, false);
358        if (resultStyle == kAllObjects) {
359            elemObj = (Object*) dvmBoxPrimitive(pValue->value,
360                        dvmFindPrimitiveClass('C'));
361            setObject = true;
362        }
363        break;
364    case kDexAnnotationInt:
365        pValue->value.i = readSignedInt(ptr, valueArg);
366        if (resultStyle == kAllObjects) {
367            elemObj = (Object*) dvmBoxPrimitive(pValue->value,
368                        dvmFindPrimitiveClass('I'));
369            setObject = true;
370        }
371        break;
372    case kDexAnnotationLong:
373        pValue->value.j = readSignedLong(ptr, valueArg);
374        if (resultStyle == kAllObjects) {
375            elemObj = (Object*) dvmBoxPrimitive(pValue->value,
376                        dvmFindPrimitiveClass('J'));
377            setObject = true;
378        }
379        break;
380    case kDexAnnotationFloat:
381        pValue->value.i = readUnsignedInt(ptr, valueArg, true);
382        if (resultStyle == kAllObjects) {
383            elemObj = (Object*) dvmBoxPrimitive(pValue->value,
384                        dvmFindPrimitiveClass('F'));
385            setObject = true;
386        }
387        break;
388    case kDexAnnotationDouble:
389        pValue->value.j = readUnsignedLong(ptr, valueArg, true);
390        if (resultStyle == kAllObjects) {
391            elemObj = (Object*) dvmBoxPrimitive(pValue->value,
392                        dvmFindPrimitiveClass('D'));
393            setObject = true;
394        }
395        break;
396    case kDexAnnotationBoolean:
397        pValue->value.i = (valueArg != 0);
398        if (resultStyle == kAllObjects) {
399            elemObj = (Object*) dvmBoxPrimitive(pValue->value,
400                        dvmFindPrimitiveClass('Z'));
401            setObject = true;
402        }
403        width = 0;
404        break;
405
406    case kDexAnnotationString:
407        idx = readUnsignedInt(ptr, valueArg, false);
408        if (resultStyle == kAllRaw) {
409            pValue->value.i = idx;
410        } else {
411            elemObj = (Object*) dvmResolveString(clazz, idx);
412            setObject = true;
413            if (elemObj == NULL)
414                return false;
415            dvmAddTrackedAlloc(elemObj, self);      // balance the Release
416        }
417        break;
418    case kDexAnnotationType:
419        idx = readUnsignedInt(ptr, valueArg, false);
420        if (resultStyle == kAllRaw) {
421            pValue->value.i = idx;
422        } else {
423            elemObj = (Object*) dvmResolveClass(clazz, idx, true);
424            setObject = true;
425            if (elemObj == NULL) {
426                /* we're expected to throw a TypeNotPresentException here */
427                DexFile* pDexFile = clazz->pDvmDex->pDexFile;
428                const char* desc = dexStringByTypeIdx(pDexFile, idx);
429                dvmClearException(self);
430                dvmThrowTypeNotPresentException(desc);
431                return false;
432            } else {
433                dvmAddTrackedAlloc(elemObj, self);      // balance the Release
434            }
435        }
436        break;
437    case kDexAnnotationMethod:
438        idx = readUnsignedInt(ptr, valueArg, false);
439        if (resultStyle == kAllRaw) {
440            pValue->value.i = idx;
441        } else {
442            Method* meth = resolveAmbiguousMethod(clazz, idx);
443            if (meth == NULL)
444                return false;
445            elemObj = dvmCreateReflectObjForMethod(clazz, meth);
446            setObject = true;
447            if (elemObj == NULL)
448                return false;
449        }
450        break;
451    case kDexAnnotationField:
452        idx = readUnsignedInt(ptr, valueArg, false);
453        assert(false);      // TODO
454        break;
455    case kDexAnnotationEnum:
456        /* enum values are the contents of a static field */
457        idx = readUnsignedInt(ptr, valueArg, false);
458        if (resultStyle == kAllRaw) {
459            pValue->value.i = idx;
460        } else {
461            StaticField* sfield;
462
463            sfield = dvmResolveStaticField(clazz, idx);
464            if (sfield == NULL) {
465                return false;
466            } else {
467                assert(sfield->clazz->descriptor[0] == 'L');
468                elemObj = sfield->value.l;
469                setObject = true;
470                dvmAddTrackedAlloc(elemObj, self);      // balance the Release
471            }
472        }
473        break;
474    case kDexAnnotationArray:
475        /*
476         * encoded_array format, which is a size followed by a stream
477         * of annotation_value.
478         *
479         * We create an array of Object, populate it, and return it.
480         */
481        if (resultStyle == kAllRaw) {
482            return false;
483        } else {
484            ArrayObject* newArray;
485            u4 size, count;
486
487            size = readUleb128(&ptr);
488            LOGVV("--- annotation array, size is %u at %p", size, ptr);
489            newArray = dvmAllocArrayByClass(gDvm.classJavaLangObjectArray,
490                size, ALLOC_DEFAULT);
491            if (newArray == NULL) {
492                ALOGE("annotation element array alloc failed (%d)", size);
493                return false;
494            }
495
496            AnnotationValue avalue;
497            for (count = 0; count < size; count++) {
498                if (!processAnnotationValue(clazz, &ptr, &avalue,
499                                kAllObjects)) {
500                    dvmReleaseTrackedAlloc((Object*)newArray, self);
501                    return false;
502                }
503                Object* obj = (Object*)avalue.value.l;
504                dvmSetObjectArrayElement(newArray, count, obj);
505                dvmReleaseTrackedAlloc(obj, self);
506            }
507
508            elemObj = (Object*) newArray;
509            setObject = true;
510        }
511        width = 0;
512        break;
513    case kDexAnnotationAnnotation:
514        /* encoded_annotation format */
515        if (resultStyle == kAllRaw)
516            return false;
517        elemObj = processEncodedAnnotation(clazz, &ptr);
518        setObject = true;
519        if (elemObj == NULL)
520            return false;
521        dvmAddTrackedAlloc(elemObj, self);      // balance the Release
522        width = 0;
523        break;
524    case kDexAnnotationNull:
525        if (resultStyle == kAllRaw) {
526            pValue->value.i = 0;
527        } else {
528            assert(elemObj == NULL);
529            setObject = true;
530        }
531        width = 0;
532        break;
533    default:
534        ALOGE("Bad annotation element value byte 0x%02x (0x%02x)",
535            valueType, valueType & kDexAnnotationValueTypeMask);
536        assert(false);
537        return false;
538    }
539
540    ptr += width;
541
542    *pPtr = ptr;
543    if (setObject)
544        pValue->value.l = elemObj;
545    return true;
546}
547
548
549/*
550 * For most object types, we have nothing to do here, and we just return
551 * "valueObj".
552 *
553 * For an array annotation, the type of the extracted object will always
554 * be java.lang.Object[], but we want it to match the type that the
555 * annotation member is expected to return.  In some cases this may
556 * involve un-boxing primitive values.
557 *
558 * We allocate a second array with the correct type, then copy the data
559 * over.  This releases the tracked allocation on "valueObj" and returns
560 * a new, tracked object.
561 *
562 * On failure, this releases the tracking on "valueObj" and returns NULL
563 * (allowing the call to say "foo = convertReturnType(foo, ..)").
564 */
565static Object* convertReturnType(Object* valueObj, ClassObject* methodReturn)
566{
567    if (valueObj == NULL ||
568        !dvmIsArray((ArrayObject*)valueObj) || !dvmIsArrayClass(methodReturn))
569    {
570        return valueObj;
571    }
572
573    Thread* self = dvmThreadSelf();
574    ClassObject* srcElemClass;
575    ClassObject* dstElemClass;
576
577    /*
578     * We always extract kDexAnnotationArray into Object[], so we expect to
579     * find that here.  This means we can skip the FindClass on
580     * (valueObj->clazz->descriptor+1, valueObj->clazz->classLoader).
581     */
582    if (strcmp(valueObj->clazz->descriptor, "[Ljava/lang/Object;") != 0) {
583        ALOGE("Unexpected src type class (%s)", valueObj->clazz->descriptor);
584        return NULL;
585    }
586    srcElemClass = gDvm.classJavaLangObject;
587
588    /*
589     * Skip past the '[' to get element class name.  Note this is not always
590     * the same as methodReturn->elementClass.
591     */
592    char firstChar = methodReturn->descriptor[1];
593    if (firstChar == 'L' || firstChar == '[') {
594        dstElemClass = dvmFindClass(methodReturn->descriptor+1,
595            methodReturn->classLoader);
596    } else {
597        dstElemClass = dvmFindPrimitiveClass(firstChar);
598    }
599    ALOGV("HEY: converting valueObj from [%s to [%s",
600        srcElemClass->descriptor, dstElemClass->descriptor);
601
602    ArrayObject* srcArray = (ArrayObject*) valueObj;
603    u4 length = srcArray->length;
604    ArrayObject* newArray;
605
606    newArray = dvmAllocArrayByClass(methodReturn, length, ALLOC_DEFAULT);
607    if (newArray == NULL) {
608        ALOGE("Failed creating duplicate annotation class (%s %d)",
609            methodReturn->descriptor, length);
610        goto bail;
611    }
612
613    bool success;
614    if (dstElemClass->primitiveType == PRIM_NOT) {
615        success = dvmCopyObjectArray(newArray, srcArray, dstElemClass);
616    } else {
617        success = dvmUnboxObjectArray(newArray, srcArray, dstElemClass);
618    }
619    if (!success) {
620        ALOGE("Annotation array copy failed");
621        dvmReleaseTrackedAlloc((Object*)newArray, self);
622        newArray = NULL;
623        goto bail;
624    }
625
626bail:
627    /* replace old, return new */
628    dvmReleaseTrackedAlloc(valueObj, self);
629    return (Object*) newArray;
630}
631
632/*
633 * Create a new AnnotationMember.
634 *
635 * "clazz" is the class on which the annotations are defined.  "pPtr"
636 * points to a pointer into the annotation data.  "annoClass" is the
637 * annotation's class.
638 *
639 * We extract the annotation's value, create a new AnnotationMember object,
640 * and construct it.
641 *
642 * Returns NULL on failure; an exception may or may not be raised.
643 */
644static Object* createAnnotationMember(const ClassObject* clazz,
645    const ClassObject* annoClass, const u1** pPtr)
646{
647    Thread* self = dvmThreadSelf();
648    const DexFile* pDexFile = clazz->pDvmDex->pDexFile;
649    StringObject* nameObj = NULL;
650    Object* valueObj = NULL;
651    Object* newMember = NULL;
652    Object* methodObj = NULL;
653    ClassObject* methodReturn = NULL;
654    u4 elementNameIdx;
655    const char* name;
656    AnnotationValue avalue;
657    JValue unused;
658    bool failed = true;
659
660    elementNameIdx = readUleb128(pPtr);
661
662    if (!processAnnotationValue(clazz, pPtr, &avalue, kAllObjects)) {
663        ALOGW("Failed processing annotation value");
664        goto bail;
665    }
666    valueObj = (Object*)avalue.value.l;
667
668    /* new member to hold the element */
669    newMember =
670        dvmAllocObject(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember,
671        ALLOC_DEFAULT);
672    name = dexStringById(pDexFile, elementNameIdx);
673    nameObj = dvmCreateStringFromCstr(name);
674
675    /* find the method in the annotation class, given only the name */
676    if (name != NULL) {
677        Method* annoMeth = dvmFindVirtualMethodByName(annoClass, name);
678        if (annoMeth == NULL) {
679            ALOGW("WARNING: could not find annotation member %s in %s",
680                name, annoClass->descriptor);
681        } else {
682            methodObj = dvmCreateReflectObjForMethod(annoClass, annoMeth);
683            methodReturn = dvmGetBoxedReturnType(annoMeth);
684        }
685    }
686    if (newMember == NULL || nameObj == NULL || methodObj == NULL ||
687        methodReturn == NULL)
688    {
689        ALOGE("Failed creating annotation element (m=%p n=%p a=%p r=%p)",
690            newMember, nameObj, methodObj, methodReturn);
691        goto bail;
692    }
693
694    /* convert the return type, if necessary */
695    valueObj = convertReturnType(valueObj, methodReturn);
696    if (valueObj == NULL)
697        goto bail;
698
699    /* call 4-argument constructor */
700    dvmCallMethod(self, gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init,
701        newMember, &unused, nameObj, valueObj, methodReturn, methodObj);
702    if (dvmCheckException(self)) {
703        ALOGD("Failed constructing annotation element");
704        goto bail;
705    }
706
707    failed = false;
708
709bail:
710    /* release tracked allocations */
711    dvmReleaseTrackedAlloc(newMember, self);
712    dvmReleaseTrackedAlloc((Object*)nameObj, self);
713    dvmReleaseTrackedAlloc(valueObj, self);
714    dvmReleaseTrackedAlloc(methodObj, self);
715    if (failed)
716        return NULL;
717    else
718        return newMember;
719}
720
721/*
722 * Create a new Annotation object from what we find in the annotation item.
723 *
724 * "clazz" is the class on which the annotations are defined.  "pPtr"
725 * points to a pointer into the annotation data.
726 *
727 * We use the AnnotationFactory class to create the annotation for us.  The
728 * method we call is:
729 *
730 *  public static Annotation createAnnotation(
731 *      Class<? extends Annotation> annotationType,
732 *      AnnotationMember[] elements)
733 *
734 * Returns a new Annotation, which will NOT be in the local ref table and
735 * not referenced elsewhere, so store it away soon.  On failure, returns NULL
736 * with an exception raised.
737 */
738static Object* processEncodedAnnotation(const ClassObject* clazz,
739    const u1** pPtr)
740{
741    Thread* self = dvmThreadSelf();
742    Object* newAnno = NULL;
743    ArrayObject* elementArray = NULL;
744    const ClassObject* annoClass;
745    const u1* ptr;
746    u4 typeIdx, size, count;
747
748    ptr = *pPtr;
749    typeIdx = readUleb128(&ptr);
750    size = readUleb128(&ptr);
751
752    LOGVV("----- processEnc ptr=%p type=%d size=%d", ptr, typeIdx, size);
753
754    annoClass = dvmDexGetResolvedClass(clazz->pDvmDex, typeIdx);
755    if (annoClass == NULL) {
756        annoClass = dvmResolveClass(clazz, typeIdx, true);
757        if (annoClass == NULL) {
758            ALOGE("Unable to resolve %s annotation class %d",
759                clazz->descriptor, typeIdx);
760            assert(dvmCheckException(self));
761            dvmClearException(self);
762            return NULL;
763        }
764    }
765
766    ALOGV("----- processEnc ptr=%p [0x%06x]  typeIdx=%d size=%d class=%s",
767        *pPtr, *pPtr - (u1*) clazz->pDvmDex->pDexFile->baseAddr,
768        typeIdx, size, annoClass->descriptor);
769
770    /*
771     * Elements are parsed out and stored in an array.  The Harmony
772     * constructor wants an array with just the declared elements --
773     * default values get merged in later.
774     */
775    JValue result;
776
777    if (size > 0) {
778        elementArray = dvmAllocArrayByClass(
779            gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray,
780            size, ALLOC_DEFAULT);
781        if (elementArray == NULL) {
782            ALOGE("failed to allocate annotation member array (%d elements)",
783                size);
784            goto bail;
785        }
786    }
787
788    /*
789     * "ptr" points to a byte stream with "size" occurrences of
790     * annotation_element.
791     */
792    for (count = 0; count < size; count++) {
793        Object* newMember = createAnnotationMember(clazz, annoClass, &ptr);
794        if (newMember == NULL)
795            goto bail;
796
797        /* add it to the array */
798        dvmSetObjectArrayElement(elementArray, count, newMember);
799    }
800
801    dvmCallMethod(self,
802        gDvm.methOrgApacheHarmonyLangAnnotationAnnotationFactory_createAnnotation,
803        NULL, &result, annoClass, elementArray);
804    if (dvmCheckException(self)) {
805        ALOGD("Failed creating an annotation");
806        //dvmLogExceptionStackTrace();
807        goto bail;
808    }
809
810    newAnno = (Object*)result.l;
811
812bail:
813    dvmReleaseTrackedAlloc((Object*) elementArray, NULL);
814    *pPtr = ptr;
815    if (newAnno == NULL && !dvmCheckException(self)) {
816        /* make sure an exception is raised */
817        dvmThrowRuntimeException("failure in processEncodedAnnotation");
818    }
819    return newAnno;
820}
821
822/*
823 * Run through an annotation set and convert each entry into an Annotation
824 * object.
825 *
826 * Returns an array of Annotation objects, or NULL with an exception raised
827 * on alloc failure.
828 */
829static ArrayObject* processAnnotationSet(const ClassObject* clazz,
830    const DexAnnotationSetItem* pAnnoSet, int visibility)
831{
832    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
833    const DexAnnotationItem* pAnnoItem;
834
835    /* we need these later; make sure they're initialized */
836    if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory))
837        dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory);
838    if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember))
839        dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember);
840
841    /* count up the number of visible elements */
842    size_t count = 0;
843    for (size_t i = 0; i < pAnnoSet->size; ++i) {
844        pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
845        if (pAnnoItem->visibility == visibility) {
846            count++;
847        }
848    }
849
850    ArrayObject* annoArray = dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArray,
851                                                  count, ALLOC_DEFAULT);
852    if (annoArray == NULL) {
853        return NULL;
854    }
855
856    /*
857     * Generate Annotation objects.  We must put them into the array
858     * immediately (or add them to the tracked ref table).
859     * We may not be able to resolve all annotations, and should just
860     * ignore those we can't.
861     */
862    u4 dstIndex = 0;
863    for (int i = 0; i < (int) pAnnoSet->size; i++) {
864        pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
865        if (pAnnoItem->visibility != visibility)
866            continue;
867        const u1* ptr = pAnnoItem->annotation;
868        Object *anno = processEncodedAnnotation(clazz, &ptr);
869        if (anno != NULL) {
870            dvmSetObjectArrayElement(annoArray, dstIndex, anno);
871            ++dstIndex;
872        }
873    }
874
875    // If we got as many as we expected, we're done...
876    if (dstIndex == count) {
877        return annoArray;
878    }
879
880    // ...otherwise we need to trim the trailing nulls.
881    ArrayObject* trimmedArray = dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArray,
882                                                     dstIndex, ALLOC_DEFAULT);
883    if (trimmedArray == NULL) {
884        return NULL;
885    }
886    for (size_t i = 0; i < dstIndex; ++i) {
887        Object** src = (Object**)(void*) annoArray->contents;
888        dvmSetObjectArrayElement(trimmedArray, i, src[i]);
889    }
890    dvmReleaseTrackedAlloc((Object*) annoArray, NULL);
891    return trimmedArray;
892}
893
894/*
895 * Return the annotation item of the specified type in the annotation set, or
896 * NULL if the set contains no annotation of that type.
897 */
898static const DexAnnotationItem* getAnnotationItemFromAnnotationSet(
899        const ClassObject* clazz, const DexAnnotationSetItem* pAnnoSet,
900        int visibility, const ClassObject* annotationClazz)
901{
902    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
903    const DexAnnotationItem* pAnnoItem;
904    int i;
905    const ClassObject* annoClass;
906    const u1* ptr;
907    u4 typeIdx;
908
909    /* we need these later; make sure they're initialized */
910    if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory))
911        dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory);
912    if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember))
913        dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember);
914
915    for (i = 0; i < (int) pAnnoSet->size; i++) {
916        pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
917        if (pAnnoItem->visibility != visibility)
918            continue;
919
920        ptr = pAnnoItem->annotation;
921        typeIdx = readUleb128(&ptr);
922
923        annoClass = dvmDexGetResolvedClass(clazz->pDvmDex, typeIdx);
924        if (annoClass == NULL) {
925            annoClass = dvmResolveClass(clazz, typeIdx, true);
926            if (annoClass == NULL) {
927                ALOGE("Unable to resolve %s annotation class %d",
928                      clazz->descriptor, typeIdx);
929                Thread* self = dvmThreadSelf();
930                assert(dvmCheckException(self));
931                dvmClearException(self);
932                continue;
933            }
934        }
935
936        if (annoClass == annotationClazz) {
937            return pAnnoItem;
938        }
939    }
940
941    return NULL;
942}
943
944/*
945 * Return the Annotation object of the specified type in the annotation set, or
946 * NULL if the set contains no annotation of that type.
947 */
948static Object* getAnnotationObjectFromAnnotationSet(const ClassObject* clazz,
949        const DexAnnotationSetItem* pAnnoSet, int visibility,
950        const ClassObject* annotationClazz)
951{
952    const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet(
953            clazz, pAnnoSet, visibility, annotationClazz);
954    if (pAnnoItem == NULL) {
955        return NULL;
956    }
957    const u1* ptr = pAnnoItem->annotation;
958    return processEncodedAnnotation(clazz, &ptr);
959}
960
961/*
962 * ===========================================================================
963 *      Skipping and scanning
964 * ===========================================================================
965 */
966
967/*
968 * Skip past an annotation value.
969 *
970 * "clazz" is the class on which the annotations are defined.
971 *
972 * Returns "true" on success, "false" on parsing failure.
973 */
974static bool skipAnnotationValue(const ClassObject* clazz, const u1** pPtr)
975{
976    const u1* ptr = *pPtr;
977    u1 valueType, valueArg;
978    int width;
979
980    valueType = *ptr++;
981    valueArg = valueType >> kDexAnnotationValueArgShift;
982    width = valueArg + 1;       /* assume */
983
984    ALOGV("----- type is 0x%02x %d, ptr=%p [0x%06x]",
985        valueType & kDexAnnotationValueTypeMask, valueArg, ptr-1,
986        (ptr-1) - (u1*)clazz->pDvmDex->pDexFile->baseAddr);
987
988    switch (valueType & kDexAnnotationValueTypeMask) {
989    case kDexAnnotationByte:        break;
990    case kDexAnnotationShort:       break;
991    case kDexAnnotationChar:        break;
992    case kDexAnnotationInt:         break;
993    case kDexAnnotationLong:        break;
994    case kDexAnnotationFloat:       break;
995    case kDexAnnotationDouble:      break;
996    case kDexAnnotationString:      break;
997    case kDexAnnotationType:        break;
998    case kDexAnnotationMethod:      break;
999    case kDexAnnotationField:       break;
1000    case kDexAnnotationEnum:        break;
1001
1002    case kDexAnnotationArray:
1003        /* encoded_array format */
1004        {
1005            u4 size = readUleb128(&ptr);
1006            while (size--) {
1007                if (!skipAnnotationValue(clazz, &ptr))
1008                    return false;
1009            }
1010        }
1011        width = 0;
1012        break;
1013    case kDexAnnotationAnnotation:
1014        /* encoded_annotation format */
1015        if (!skipEncodedAnnotation(clazz, &ptr))
1016            return false;
1017        width = 0;
1018        break;
1019    case kDexAnnotationBoolean:
1020    case kDexAnnotationNull:
1021        width = 0;
1022        break;
1023    default:
1024        ALOGE("Bad annotation element value byte 0x%02x", valueType);
1025        assert(false);
1026        return false;
1027    }
1028
1029    ptr += width;
1030
1031    *pPtr = ptr;
1032    return true;
1033}
1034
1035/*
1036 * Skip past an encoded annotation.  Mainly useful for annotations embedded
1037 * in other annotations.
1038 */
1039static bool skipEncodedAnnotation(const ClassObject* clazz, const u1** pPtr)
1040{
1041    const u1* ptr;
1042    u4 size;
1043
1044    ptr = *pPtr;
1045    (void) readUleb128(&ptr);
1046    size = readUleb128(&ptr);
1047
1048    /*
1049     * "ptr" points to a byte stream with "size" occurrences of
1050     * annotation_element.
1051     */
1052    while (size--) {
1053        (void) readUleb128(&ptr);
1054
1055        if (!skipAnnotationValue(clazz, &ptr))
1056            return false;
1057    }
1058
1059    *pPtr = ptr;
1060    return true;
1061}
1062
1063
1064/*
1065 * Compare the name of the class in the DEX file to the supplied descriptor.
1066 * Return value is equivalent to strcmp.
1067 */
1068static int compareClassDescriptor(DexFile* pDexFile, u4 typeIdx,
1069    const char* descriptor)
1070{
1071    const char* str = dexStringByTypeIdx(pDexFile, typeIdx);
1072
1073    return strcmp(str, descriptor);
1074}
1075
1076/*
1077 * Search through the annotation set for an annotation with a matching
1078 * descriptor.
1079 *
1080 * Comparing the string descriptor is slower than comparing an integer class
1081 * index.  If annotation lists are expected to be long, we could look up
1082 * the class' index by name from the DEX file, rather than doing a class
1083 * lookup and string compare on each entry.  (Note the index will be
1084 * different for each DEX file, so we can't cache annotation class indices
1085 * globally.)
1086 */
1087static const DexAnnotationItem* searchAnnotationSet(const ClassObject* clazz,
1088    const DexAnnotationSetItem* pAnnoSet, const char* descriptor,
1089    int visibility)
1090{
1091    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1092    const DexAnnotationItem* result = NULL;
1093    u4 typeIdx;
1094    int i;
1095
1096    //printf("##### searchAnnotationSet %s %d\n", descriptor, visibility);
1097
1098    for (i = 0; i < (int) pAnnoSet->size; i++) {
1099        const DexAnnotationItem* pAnnoItem;
1100
1101        pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i);
1102        if (pAnnoItem->visibility != visibility)
1103            continue;
1104        const u1* ptr = pAnnoItem->annotation;
1105        typeIdx = readUleb128(&ptr);
1106
1107        if (compareClassDescriptor(pDexFile, typeIdx, descriptor) == 0) {
1108            //printf("#####  match on %x/%p at %d\n", typeIdx, pDexFile, i);
1109            result = pAnnoItem;
1110            break;
1111        }
1112    }
1113
1114    return result;
1115}
1116
1117/*
1118 * Find an annotation value in the annotation_item whose name matches "name".
1119 * A pointer to the annotation_value is returned, or NULL if it's not found.
1120 */
1121static const u1* searchEncodedAnnotation(const ClassObject* clazz,
1122    const u1* ptr, const char* name)
1123{
1124    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1125    u4 typeIdx, size;
1126
1127    typeIdx = readUleb128(&ptr);
1128    size = readUleb128(&ptr);
1129    //printf("#####   searching ptr=%p type=%u size=%u\n", ptr, typeIdx, size);
1130
1131    while (size--) {
1132        u4 elementNameIdx;
1133        const char* elemName;
1134
1135        elementNameIdx = readUleb128(&ptr);
1136        elemName = dexStringById(pDexFile, elementNameIdx);
1137        if (strcmp(name, elemName) == 0) {
1138            //printf("#####   item match on %s\n", name);
1139            return ptr;     /* points to start of value */
1140        }
1141
1142        skipAnnotationValue(clazz, &ptr);
1143    }
1144
1145    //printf("#####   no item match on %s\n", name);
1146    return NULL;
1147}
1148
1149#define GAV_FAILED  ((Object*) 0x10000001)
1150
1151/*
1152 * Extract an encoded annotation value from the field specified by "annoName".
1153 *
1154 * "expectedType" is an annotation value type, e.g. kDexAnnotationString.
1155 * "debugAnnoName" is only used in debug messages.
1156 *
1157 * Returns GAV_FAILED on failure.  If an allocation failed, an exception
1158 * will be raised.
1159 */
1160static Object* getAnnotationValue(const ClassObject* clazz,
1161    const DexAnnotationItem* pAnnoItem, const char* annoName,
1162    int expectedType, const char* debugAnnoName)
1163{
1164    const u1* ptr;
1165    AnnotationValue avalue;
1166
1167    /* find the annotation */
1168    ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, annoName);
1169    if (ptr == NULL) {
1170        ALOGW("%s annotation lacks '%s' member", debugAnnoName, annoName);
1171        return GAV_FAILED;
1172    }
1173
1174    if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects))
1175        return GAV_FAILED;
1176
1177    /* make sure it has the expected format */
1178    if (avalue.type != expectedType) {
1179        ALOGW("%s %s has wrong type (0x%02x, expected 0x%02x)",
1180            debugAnnoName, annoName, avalue.type, expectedType);
1181        return GAV_FAILED;
1182    }
1183
1184    return (Object*)avalue.value.l;
1185}
1186
1187
1188/*
1189 * Find the Signature attribute and extract its value.  (Signatures can
1190 * be found in annotations on classes, constructors, methods, and fields.)
1191 *
1192 * Caller must call dvmReleaseTrackedAlloc().
1193 *
1194 * Returns NULL if not found.  On memory alloc failure, returns NULL with an
1195 * exception raised.
1196 */
1197static ArrayObject* getSignatureValue(const ClassObject* clazz,
1198    const DexAnnotationSetItem* pAnnoSet)
1199{
1200    const DexAnnotationItem* pAnnoItem;
1201    Object* obj;
1202
1203    pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrSignature,
1204        kDexVisibilitySystem);
1205    if (pAnnoItem == NULL)
1206        return NULL;
1207
1208    /*
1209     * The Signature annotation has one member, "String value".
1210     */
1211    obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationArray,
1212            "Signature");
1213    if (obj == GAV_FAILED)
1214        return NULL;
1215    assert(obj->clazz == gDvm.classJavaLangObjectArray);
1216
1217    return (ArrayObject*)obj;
1218}
1219
1220
1221/*
1222 * ===========================================================================
1223 *      Class
1224 * ===========================================================================
1225 */
1226
1227/*
1228 * Find the DexAnnotationSetItem for this class.
1229 */
1230static const DexAnnotationSetItem* findAnnotationSetForClass(
1231    const ClassObject* clazz)
1232{
1233    DexFile* pDexFile;
1234    const DexAnnotationsDirectoryItem* pAnnoDir;
1235
1236    if (clazz->pDvmDex == NULL)         /* generated class (Proxy, array) */
1237        return NULL;
1238
1239    pDexFile = clazz->pDvmDex->pDexFile;
1240    pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1241    if (pAnnoDir != NULL)
1242        return dexGetClassAnnotationSet(pDexFile, pAnnoDir);
1243    else
1244        return NULL;
1245}
1246
1247/*
1248 * Return an array of Annotation objects for the class.  Returns an empty
1249 * array if there are no annotations.
1250 *
1251 * Caller must call dvmReleaseTrackedAlloc().
1252 *
1253 * On allocation failure, this returns NULL with an exception raised.
1254 */
1255ArrayObject* dvmGetClassAnnotations(const ClassObject* clazz)
1256{
1257    ArrayObject* annoArray;
1258    const DexAnnotationSetItem* pAnnoSet = NULL;
1259
1260    pAnnoSet = findAnnotationSetForClass(clazz);
1261    if (pAnnoSet == NULL) {
1262        /* no annotations for anything in class, or no class annotations */
1263        annoArray = emptyAnnoArray();
1264    } else {
1265        annoArray = processAnnotationSet(clazz, pAnnoSet,
1266                        kDexVisibilityRuntime);
1267    }
1268
1269    return annoArray;
1270}
1271
1272/*
1273 * Returns the annotation or NULL if it doesn't exist.
1274 */
1275Object* dvmGetClassAnnotation(const ClassObject* clazz,
1276        const ClassObject* annotationClazz)
1277{
1278    const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForClass(clazz);
1279    if (pAnnoSet == NULL) {
1280        return NULL;
1281    }
1282    return getAnnotationObjectFromAnnotationSet(clazz, pAnnoSet,
1283            kDexVisibilityRuntime, annotationClazz);
1284}
1285
1286/*
1287 * Returns true if the annotation exists.
1288 */
1289bool dvmIsClassAnnotationPresent(const ClassObject* clazz,
1290        const ClassObject* annotationClazz)
1291{
1292    const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForClass(clazz);
1293    if (pAnnoSet == NULL) {
1294        return NULL;
1295    }
1296    const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet(
1297            clazz, pAnnoSet, kDexVisibilityRuntime, annotationClazz);
1298    return (pAnnoItem != NULL);
1299}
1300
1301/*
1302 * Retrieve the Signature annotation, if any.  Returns NULL if no signature
1303 * exists.
1304 *
1305 * Caller must call dvmReleaseTrackedAlloc().
1306 */
1307ArrayObject* dvmGetClassSignatureAnnotation(const ClassObject* clazz)
1308{
1309    ArrayObject* signature = NULL;
1310    const DexAnnotationSetItem* pAnnoSet;
1311
1312    pAnnoSet = findAnnotationSetForClass(clazz);
1313    if (pAnnoSet != NULL)
1314        signature = getSignatureValue(clazz, pAnnoSet);
1315
1316    return signature;
1317}
1318
1319/*
1320 * Get the EnclosingMethod attribute from an annotation.  Returns a Method
1321 * object, or NULL.
1322 *
1323 * Caller must call dvmReleaseTrackedAlloc().
1324 */
1325Object* dvmGetEnclosingMethod(const ClassObject* clazz)
1326{
1327    const DexAnnotationItem* pAnnoItem;
1328    const DexAnnotationSetItem* pAnnoSet;
1329    Object* obj;
1330
1331    pAnnoSet = findAnnotationSetForClass(clazz);
1332    if (pAnnoSet == NULL)
1333        return NULL;
1334
1335    pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingMethod,
1336        kDexVisibilitySystem);
1337    if (pAnnoItem == NULL)
1338        return NULL;
1339
1340    /*
1341     * The EnclosingMethod annotation has one member, "Method value".
1342     */
1343    obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationMethod,
1344            "EnclosingMethod");
1345    if (obj == GAV_FAILED)
1346        return NULL;
1347    assert(obj->clazz == gDvm.classJavaLangReflectConstructor ||
1348           obj->clazz == gDvm.classJavaLangReflectMethod);
1349
1350    return obj;
1351}
1352
1353/*
1354 * Find a class' enclosing class.  We return what we find in the
1355 * EnclosingClass attribute.
1356 *
1357 * Returns a Class object, or NULL.
1358 *
1359 * Caller must call dvmReleaseTrackedAlloc().
1360 */
1361ClassObject* dvmGetDeclaringClass(const ClassObject* clazz)
1362{
1363    const DexAnnotationItem* pAnnoItem;
1364    const DexAnnotationSetItem* pAnnoSet;
1365    Object* obj;
1366
1367    pAnnoSet = findAnnotationSetForClass(clazz);
1368    if (pAnnoSet == NULL)
1369        return NULL;
1370
1371    pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingClass,
1372        kDexVisibilitySystem);
1373    if (pAnnoItem == NULL)
1374        return NULL;
1375
1376    /*
1377     * The EnclosingClass annotation has one member, "Class value".
1378     */
1379    obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationType,
1380            "EnclosingClass");
1381    if (obj == GAV_FAILED)
1382        return NULL;
1383
1384    assert(dvmIsClassObject(obj));
1385    return (ClassObject*)obj;
1386}
1387
1388/*
1389 * Find a class' enclosing class.  We first search for an EnclosingClass
1390 * attribute, and if that's not found we look for an EnclosingMethod.
1391 *
1392 * Returns a Class object, or NULL.
1393 *
1394 * Caller must call dvmReleaseTrackedAlloc().
1395 */
1396ClassObject* dvmGetEnclosingClass(const ClassObject* clazz)
1397{
1398    const DexAnnotationItem* pAnnoItem;
1399    const DexAnnotationSetItem* pAnnoSet;
1400    Object* obj;
1401
1402    pAnnoSet = findAnnotationSetForClass(clazz);
1403    if (pAnnoSet == NULL)
1404        return NULL;
1405
1406    pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingClass,
1407        kDexVisibilitySystem);
1408    if (pAnnoItem != NULL) {
1409        /*
1410         * The EnclosingClass annotation has one member, "Class value".
1411         */
1412        obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationType,
1413                "EnclosingClass");
1414        if (obj != GAV_FAILED) {
1415            assert(dvmIsClassObject(obj));
1416            return (ClassObject*)obj;
1417        }
1418    }
1419
1420    /*
1421     * That didn't work.  Look for an EnclosingMethod.
1422     *
1423     * We could create a java.lang.reflect.Method object and extract the
1424     * declaringClass from it, but that's more work than we want to do.
1425     * Instead, we find the "value" item and parse the index out ourselves.
1426     */
1427    pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingMethod,
1428        kDexVisibilitySystem);
1429    if (pAnnoItem == NULL)
1430        return NULL;
1431
1432    /* find the value member */
1433    const u1* ptr;
1434    ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "value");
1435    if (ptr == NULL) {
1436        ALOGW("EnclosingMethod annotation lacks 'value' member");
1437        return NULL;
1438    }
1439
1440    /* parse it, verify the type */
1441    AnnotationValue avalue;
1442    if (!processAnnotationValue(clazz, &ptr, &avalue, kAllRaw)) {
1443        ALOGW("EnclosingMethod parse failed");
1444        return NULL;
1445    }
1446    if (avalue.type != kDexAnnotationMethod) {
1447        ALOGW("EnclosingMethod value has wrong type (0x%02x, expected 0x%02x)",
1448            avalue.type, kDexAnnotationMethod);
1449        return NULL;
1450    }
1451
1452    /* pull out the method index and resolve the method */
1453    Method* meth = resolveAmbiguousMethod(clazz, avalue.value.i);
1454    if (meth == NULL)
1455        return NULL;
1456
1457    ClassObject* methClazz = meth->clazz;
1458    dvmAddTrackedAlloc((Object*) methClazz, NULL);      // balance the Release
1459    return methClazz;
1460}
1461
1462/*
1463 * Get the EnclosingClass attribute from an annotation.  If found, returns
1464 * "true".  A String with the original name of the class and the original
1465 * access flags are returned through the arguments.  (The name will be NULL
1466 * for an anonymous inner class.)
1467 *
1468 * Caller must call dvmReleaseTrackedAlloc().
1469 */
1470bool dvmGetInnerClass(const ClassObject* clazz, StringObject** pName,
1471    int* pAccessFlags)
1472{
1473    const DexAnnotationItem* pAnnoItem;
1474    const DexAnnotationSetItem* pAnnoSet;
1475
1476    pAnnoSet = findAnnotationSetForClass(clazz);
1477    if (pAnnoSet == NULL)
1478        return false;
1479
1480    pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrInnerClass,
1481        kDexVisibilitySystem);
1482    if (pAnnoItem == NULL)
1483        return false;
1484
1485    /*
1486     * The InnerClass annotation has two members, "String name" and
1487     * "int accessFlags".  We don't want to get the access flags as an
1488     * Integer, so we process that as a simple value.
1489     */
1490    const u1* ptr;
1491    ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "name");
1492    if (ptr == NULL) {
1493        ALOGW("InnerClass annotation lacks 'name' member");
1494        return false;
1495    }
1496
1497    /* parse it into an Object */
1498    AnnotationValue avalue;
1499    if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects)) {
1500        ALOGD("processAnnotationValue failed on InnerClass member 'name'");
1501        return false;
1502    }
1503
1504    /* make sure it has the expected format */
1505    if (avalue.type != kDexAnnotationNull &&
1506        avalue.type != kDexAnnotationString)
1507    {
1508        ALOGW("InnerClass name has bad type (0x%02x, expected STRING or NULL)",
1509            avalue.type);
1510        return false;
1511    }
1512
1513    *pName = (StringObject*) avalue.value.l;
1514    assert(*pName == NULL || (*pName)->clazz == gDvm.classJavaLangString);
1515
1516    ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "accessFlags");
1517    if (ptr == NULL) {
1518        ALOGW("InnerClass annotation lacks 'accessFlags' member");
1519        return false;
1520    }
1521
1522    /* parse it, verify the type */
1523    if (!processAnnotationValue(clazz, &ptr, &avalue, kAllRaw)) {
1524        ALOGW("InnerClass accessFlags parse failed");
1525        return false;
1526    }
1527    if (avalue.type != kDexAnnotationInt) {
1528        ALOGW("InnerClass value has wrong type (0x%02x, expected 0x%02x)",
1529            avalue.type, kDexAnnotationInt);
1530        return false;
1531    }
1532
1533    *pAccessFlags = avalue.value.i;
1534
1535    return true;
1536}
1537
1538/*
1539 * Extract an array of Class objects from the MemberClasses annotation
1540 * for this class.
1541 *
1542 * Caller must call dvmReleaseTrackedAlloc().
1543 *
1544 * Returns NULL if we don't find any member classes.
1545 */
1546ArrayObject* dvmGetDeclaredClasses(const ClassObject* clazz)
1547{
1548    const DexAnnotationSetItem* pAnnoSet;
1549    const DexAnnotationItem* pAnnoItem;
1550    Object* obj;
1551
1552    pAnnoSet = findAnnotationSetForClass(clazz);
1553    if (pAnnoSet == NULL)
1554        return NULL;
1555
1556    pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrMemberClasses,
1557        kDexVisibilitySystem);
1558    if (pAnnoItem == NULL)
1559        return NULL;
1560
1561    /*
1562     * The MemberClasses annotation has one member, "Class[] value".
1563     */
1564    obj = getAnnotationValue(clazz, pAnnoItem, "value",
1565            kDexAnnotationArray, "MemberClasses");
1566    if (obj == GAV_FAILED)
1567        return NULL;
1568    assert(dvmIsArray((ArrayObject*)obj));
1569    obj = convertReturnType(obj, gDvm.classJavaLangClassArray);
1570    return (ArrayObject*)obj;
1571}
1572
1573
1574/*
1575 * ===========================================================================
1576 *      Method (and Constructor)
1577 * ===========================================================================
1578 */
1579
1580/*
1581 * Compare the attributes (class name, method name, method signature) of
1582 * the specified method to "method".
1583 */
1584static int compareMethodStr(DexFile* pDexFile, u4 methodIdx,
1585    const Method* method)
1586{
1587    const DexMethodId* pMethodId = dexGetMethodId(pDexFile, methodIdx);
1588    const char* str = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
1589    int result = strcmp(str, method->clazz->descriptor);
1590
1591    if (result == 0) {
1592        str = dexStringById(pDexFile, pMethodId->nameIdx);
1593        result = strcmp(str, method->name);
1594        if (result == 0) {
1595            DexProto proto;
1596            dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
1597            result = dexProtoCompare(&proto, &method->prototype);
1598        }
1599    }
1600
1601    return result;
1602}
1603
1604/*
1605 * Given a method, determine the method's index.
1606 *
1607 * We could simply store this in the Method*, but that would cost 4 bytes
1608 * per method.  Instead we plow through the DEX data.
1609 *
1610 * We have two choices: look through the class method data, or look through
1611 * the global method_ids table.  The former is awkward because the method
1612 * could have been defined in a superclass or interface.  The latter works
1613 * out reasonably well because it's in sorted order, though we're still left
1614 * doing a fair number of string comparisons.
1615 */
1616static u4 getMethodIdx(const Method* method)
1617{
1618    DexFile* pDexFile = method->clazz->pDvmDex->pDexFile;
1619    u4 hi = pDexFile->pHeader->methodIdsSize -1;
1620    u4 lo = 0;
1621    u4 cur;
1622
1623    while (hi >= lo) {
1624        int cmp;
1625        cur = (lo + hi) / 2;
1626
1627        cmp = compareMethodStr(pDexFile, cur, method);
1628        if (cmp < 0) {
1629            lo = cur + 1;
1630        } else if (cmp > 0) {
1631            hi = cur - 1;
1632        } else {
1633            break;
1634        }
1635    }
1636
1637    if (hi < lo) {
1638        /* this should be impossible -- the method came out of this DEX */
1639        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1640        ALOGE("Unable to find method %s.%s %s in DEX file!",
1641            method->clazz->descriptor, method->name, desc);
1642        free(desc);
1643        dvmAbort();
1644    }
1645
1646    return cur;
1647}
1648
1649/*
1650 * Find the DexAnnotationSetItem for this method.
1651 *
1652 * Returns NULL if none found.
1653 */
1654static const DexAnnotationSetItem* findAnnotationSetForMethod(
1655    const Method* method)
1656{
1657    ClassObject* clazz = method->clazz;
1658    DexFile* pDexFile;
1659    const DexAnnotationsDirectoryItem* pAnnoDir;
1660    const DexMethodAnnotationsItem* pMethodList;
1661    const DexAnnotationSetItem* pAnnoSet = NULL;
1662
1663    if (clazz->pDvmDex == NULL)         /* generated class (Proxy, array) */
1664        return NULL;
1665    pDexFile = clazz->pDvmDex->pDexFile;
1666
1667    pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1668    if (pAnnoDir != NULL) {
1669        pMethodList = dexGetMethodAnnotations(pDexFile, pAnnoDir);
1670        if (pMethodList != NULL) {
1671            /*
1672             * Run through the list and find a matching method.  We compare the
1673             * method ref indices in the annotation list with the method's DEX
1674             * method_idx value.
1675             *
1676             * TODO: use a binary search for long lists
1677             *
1678             * Alternate approach: for each entry in the annotations list,
1679             * find the method definition in the DEX file and perform string
1680             * comparisons on class name, method name, and signature.
1681             */
1682            u4 methodIdx = getMethodIdx(method);
1683            u4 count = dexGetMethodAnnotationsSize(pDexFile, pAnnoDir);
1684            u4 idx;
1685
1686            for (idx = 0; idx < count; idx++) {
1687                if (pMethodList[idx].methodIdx == methodIdx) {
1688                    /* found! */
1689                    pAnnoSet = dexGetMethodAnnotationSetItem(pDexFile,
1690                                    &pMethodList[idx]);
1691                    break;
1692                }
1693            }
1694        }
1695    }
1696
1697    return pAnnoSet;
1698}
1699
1700/*
1701 * Return an array of Annotation objects for the method.  Returns an empty
1702 * array if there are no annotations.
1703 *
1704 * Caller must call dvmReleaseTrackedAlloc().
1705 *
1706 * On allocation failure, this returns NULL with an exception raised.
1707 */
1708ArrayObject* dvmGetMethodAnnotations(const Method* method)
1709{
1710    ClassObject* clazz = method->clazz;
1711    const DexAnnotationSetItem* pAnnoSet;
1712    ArrayObject* annoArray = NULL;
1713
1714    pAnnoSet = findAnnotationSetForMethod(method);
1715    if (pAnnoSet == NULL) {
1716        /* no matching annotations found */
1717        annoArray = emptyAnnoArray();
1718    } else {
1719        annoArray = processAnnotationSet(clazz, pAnnoSet,kDexVisibilityRuntime);
1720    }
1721
1722    return annoArray;
1723}
1724
1725/*
1726 * Returns the annotation or NULL if it doesn't exist.
1727 */
1728Object* dvmGetMethodAnnotation(const ClassObject* clazz, const Method* method,
1729        const ClassObject* annotationClazz)
1730{
1731    const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForMethod(method);
1732    if (pAnnoSet == NULL) {
1733        return NULL;
1734    }
1735    return getAnnotationObjectFromAnnotationSet(clazz, pAnnoSet,
1736            kDexVisibilityRuntime, annotationClazz);
1737}
1738
1739/*
1740 * Returns true if the annotation exists.
1741 */
1742bool dvmIsMethodAnnotationPresent(const ClassObject* clazz,
1743        const Method* method, const ClassObject* annotationClazz)
1744{
1745    const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForMethod(method);
1746    if (pAnnoSet == NULL) {
1747        return NULL;
1748    }
1749    const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet(
1750            clazz, pAnnoSet, kDexVisibilityRuntime, annotationClazz);
1751    return (pAnnoItem != NULL);
1752}
1753
1754/*
1755 * Retrieve the Signature annotation, if any.  Returns NULL if no signature
1756 * exists.
1757 *
1758 * Caller must call dvmReleaseTrackedAlloc().
1759 */
1760ArrayObject* dvmGetMethodSignatureAnnotation(const Method* method)
1761{
1762    ClassObject* clazz = method->clazz;
1763    const DexAnnotationSetItem* pAnnoSet;
1764    ArrayObject* signature = NULL;
1765
1766    pAnnoSet = findAnnotationSetForMethod(method);
1767    if (pAnnoSet != NULL)
1768        signature = getSignatureValue(clazz, pAnnoSet);
1769
1770    return signature;
1771}
1772
1773/*
1774 * Extract an array of exception classes from the "system" annotation list
1775 * for this method.
1776 *
1777 * Caller must call dvmReleaseTrackedAlloc().
1778 *
1779 * Returns NULL if we don't find any exceptions for this method.
1780 */
1781ArrayObject* dvmGetMethodThrows(const Method* method)
1782{
1783    ClassObject* clazz = method->clazz;
1784    const DexAnnotationSetItem* pAnnoSet;
1785    const DexAnnotationItem* pAnnoItem;
1786
1787    /* find the set for this method */
1788    pAnnoSet = findAnnotationSetForMethod(method);
1789    if (pAnnoSet == NULL)
1790        return NULL;        /* nothing for this method */
1791
1792    /* find the "Throws" annotation, if any */
1793    pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrThrows,
1794        kDexVisibilitySystem);
1795    if (pAnnoItem == NULL)
1796        return NULL;        /* no Throws */
1797
1798    /*
1799     * The Throws annotation has one member, "Class[] value".
1800     */
1801    Object* obj = getAnnotationValue(clazz, pAnnoItem, "value",
1802        kDexAnnotationArray, "Throws");
1803    if (obj == GAV_FAILED)
1804        return NULL;
1805    assert(dvmIsArray((ArrayObject*)obj));
1806    obj = convertReturnType(obj, gDvm.classJavaLangClassArray);
1807    return (ArrayObject*)obj;
1808}
1809
1810/*
1811 * Given an Annotation's method, find the default value, if any.
1812 *
1813 * If this is a CLASS annotation, and we can't find a match for the
1814 * default class value, we need to throw a TypeNotPresentException.
1815 *
1816 * Caller must call dvmReleaseTrackedAlloc().
1817 */
1818Object* dvmGetAnnotationDefaultValue(const Method* method)
1819{
1820    const ClassObject* clazz = method->clazz;
1821    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1822    const DexAnnotationsDirectoryItem* pAnnoDir;
1823    const DexAnnotationSetItem* pAnnoSet = NULL;
1824
1825    /*
1826     * The method's declaring class (the annotation) will have an
1827     * AnnotationDefault "system" annotation associated with it if any
1828     * of its methods have default values.  Start by finding the
1829     * DexAnnotationItem associated with the class.
1830     */
1831    pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1832    if (pAnnoDir != NULL)
1833        pAnnoSet = dexGetClassAnnotationSet(pDexFile, pAnnoDir);
1834    if (pAnnoSet == NULL) {
1835        /* no annotations for anything in class, or no class annotations */
1836        return NULL;
1837    }
1838
1839    /* find the "AnnotationDefault" annotation, if any */
1840    const DexAnnotationItem* pAnnoItem;
1841    pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrAnnotationDefault,
1842        kDexVisibilitySystem);
1843    if (pAnnoItem == NULL) {
1844        /* no default values for any member in this annotation */
1845        //printf("##### no default annotations for %s.%s\n",
1846        //    method->clazz->descriptor, method->name);
1847        return NULL;
1848    }
1849
1850    /*
1851     * The AnnotationDefault annotation has one member, "Annotation value".
1852     * We need to pull that out.
1853     */
1854    const u1* ptr;
1855    ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "value");
1856    if (ptr == NULL) {
1857        ALOGW("AnnotationDefault annotation lacks 'value'");
1858        return NULL;
1859    }
1860    if ((*ptr & kDexAnnotationValueTypeMask) != kDexAnnotationAnnotation) {
1861        ALOGW("AnnotationDefault value has wrong type (0x%02x)",
1862            *ptr & kDexAnnotationValueTypeMask);
1863        return NULL;
1864    }
1865
1866    /*
1867     * The value_type byte for VALUE_ANNOTATION is followed by
1868     * encoded_annotation data.  We want to scan through it to find an
1869     * entry whose name matches our method name.
1870     */
1871    ptr++;
1872    ptr = searchEncodedAnnotation(clazz, ptr, method->name);
1873    if (ptr == NULL)
1874        return NULL;        /* no default annotation for this method */
1875
1876    /* got it, pull it out */
1877    AnnotationValue avalue;
1878    if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects)) {
1879        ALOGD("processAnnotationValue failed on default for '%s'",
1880            method->name);
1881        return NULL;
1882    }
1883
1884    /* convert the return type, if necessary */
1885    ClassObject* methodReturn = dvmGetBoxedReturnType(method);
1886    Object* obj = (Object*)avalue.value.l;
1887    obj = convertReturnType(obj, methodReturn);
1888
1889    return obj;
1890}
1891
1892
1893/*
1894 * ===========================================================================
1895 *      Field
1896 * ===========================================================================
1897 */
1898
1899/*
1900 * Compare the attributes (class name, field name, field signature) of
1901 * the specified field to "field".
1902 */
1903static int compareFieldStr(DexFile* pDexFile, u4 idx, const Field* field)
1904{
1905    const DexFieldId* pFieldId = dexGetFieldId(pDexFile, idx);
1906    const char* str = dexStringByTypeIdx(pDexFile, pFieldId->classIdx);
1907    int result = strcmp(str, field->clazz->descriptor);
1908
1909    if (result == 0) {
1910        str = dexStringById(pDexFile, pFieldId->nameIdx);
1911        result = strcmp(str, field->name);
1912        if (result == 0) {
1913            str = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
1914            result = strcmp(str, field->signature);
1915        }
1916    }
1917
1918    return result;
1919}
1920
1921/*
1922 * Given a field, determine the field's index.
1923 *
1924 * This has the same tradeoffs as getMethodIdx.
1925 */
1926static u4 getFieldIdx(const Field* field)
1927{
1928    DexFile* pDexFile = field->clazz->pDvmDex->pDexFile;
1929    u4 hi = pDexFile->pHeader->fieldIdsSize -1;
1930    u4 lo = 0;
1931    u4 cur;
1932
1933    while (hi >= lo) {
1934        int cmp;
1935        cur = (lo + hi) / 2;
1936
1937        cmp = compareFieldStr(pDexFile, cur, field);
1938        if (cmp < 0) {
1939            lo = cur + 1;
1940        } else if (cmp > 0) {
1941            hi = cur - 1;
1942        } else {
1943            break;
1944        }
1945    }
1946
1947    if (hi < lo) {
1948        /* this should be impossible -- the field came out of this DEX */
1949        ALOGE("Unable to find field %s.%s %s in DEX file!",
1950            field->clazz->descriptor, field->name, field->signature);
1951        dvmAbort();
1952    }
1953
1954    return cur;
1955}
1956
1957/*
1958 * Find the DexAnnotationSetItem for this field.
1959 *
1960 * Returns NULL if none found.
1961 */
1962static const DexAnnotationSetItem* findAnnotationSetForField(const Field* field)
1963{
1964    ClassObject* clazz = field->clazz;
1965    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
1966    const DexAnnotationsDirectoryItem* pAnnoDir;
1967    const DexFieldAnnotationsItem* pFieldList;
1968
1969    pAnnoDir = getAnnoDirectory(pDexFile, clazz);
1970    if (pAnnoDir == NULL)
1971        return NULL;
1972
1973    pFieldList = dexGetFieldAnnotations(pDexFile, pAnnoDir);
1974    if (pFieldList == NULL)
1975        return NULL;
1976
1977    /*
1978     * Run through the list and find a matching field.  We compare the
1979     * field ref indices in the annotation list with the field's DEX
1980     * field_idx value.
1981     *
1982     * TODO: use a binary search for long lists
1983     *
1984     * Alternate approach: for each entry in the annotations list,
1985     * find the field definition in the DEX file and perform string
1986     * comparisons on class name, field name, and signature.
1987     */
1988    u4 fieldIdx = getFieldIdx(field);
1989    u4 count = dexGetFieldAnnotationsSize(pDexFile, pAnnoDir);
1990    u4 idx;
1991
1992    for (idx = 0; idx < count; idx++) {
1993        if (pFieldList[idx].fieldIdx == fieldIdx) {
1994            /* found! */
1995            return dexGetFieldAnnotationSetItem(pDexFile, &pFieldList[idx]);
1996        }
1997    }
1998
1999    return NULL;
2000}
2001
2002/*
2003 * Return an array of Annotation objects for the field.  Returns an empty
2004 * array if there are no annotations.
2005 *
2006 * Caller must call dvmReleaseTrackedAlloc().
2007 *
2008 * On allocation failure, this returns NULL with an exception raised.
2009 */
2010ArrayObject* dvmGetFieldAnnotations(const Field* field)
2011{
2012    ClassObject* clazz = field->clazz;
2013    ArrayObject* annoArray = NULL;
2014    const DexAnnotationSetItem* pAnnoSet = NULL;
2015
2016    pAnnoSet = findAnnotationSetForField(field);
2017    if (pAnnoSet == NULL) {
2018        /* no matching annotations found */
2019        annoArray = emptyAnnoArray();
2020    } else {
2021        annoArray = processAnnotationSet(clazz, pAnnoSet,
2022                        kDexVisibilityRuntime);
2023    }
2024
2025    return annoArray;
2026}
2027
2028/*
2029 * Returns the annotation or NULL if it doesn't exist.
2030 */
2031Object* dvmGetFieldAnnotation(const ClassObject* clazz, const Field* field,
2032        const ClassObject* annotationClazz)
2033{
2034    const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForField(field);
2035    if (pAnnoSet == NULL) {
2036        return NULL;
2037    }
2038    return getAnnotationObjectFromAnnotationSet(clazz, pAnnoSet,
2039            kDexVisibilityRuntime, annotationClazz);
2040}
2041
2042/*
2043 * Returns true if the annotation exists.
2044 */
2045bool dvmIsFieldAnnotationPresent(const ClassObject* clazz,
2046        const Field* field, const ClassObject* annotationClazz)
2047{
2048    const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForField(field);
2049    if (pAnnoSet == NULL) {
2050        return NULL;
2051    }
2052    const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet(
2053            clazz, pAnnoSet, kDexVisibilityRuntime, annotationClazz);
2054    return (pAnnoItem != NULL);
2055}
2056
2057/*
2058 * Retrieve the Signature annotation, if any.  Returns NULL if no signature
2059 * exists.
2060 *
2061 * Caller must call dvmReleaseTrackedAlloc().
2062 */
2063ArrayObject* dvmGetFieldSignatureAnnotation(const Field* field)
2064{
2065    ClassObject* clazz = field->clazz;
2066    const DexAnnotationSetItem* pAnnoSet;
2067    ArrayObject* signature = NULL;
2068
2069    pAnnoSet = findAnnotationSetForField(field);
2070    if (pAnnoSet != NULL)
2071        signature = getSignatureValue(clazz, pAnnoSet);
2072
2073    return signature;
2074}
2075
2076
2077/*
2078 * ===========================================================================
2079 *      Parameter
2080 * ===========================================================================
2081 */
2082
2083/*
2084 * We have an annotation_set_ref_list, which is essentially a list of
2085 * entries that we pass to processAnnotationSet().
2086 *
2087 * The returned object must be released with dvmReleaseTrackedAlloc.
2088 */
2089static ArrayObject* processAnnotationSetRefList(const ClassObject* clazz,
2090    const DexAnnotationSetRefList* pAnnoSetList, u4 count)
2091{
2092    DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2093    ArrayObject* annoArrayArray = NULL;
2094    u4 idx;
2095
2096    /* allocate an array of Annotation arrays to hold results */
2097    annoArrayArray = dvmAllocArrayByClass(
2098        gDvm.classJavaLangAnnotationAnnotationArrayArray, count, ALLOC_DEFAULT);
2099    if (annoArrayArray == NULL) {
2100        ALOGW("annotation set ref array alloc failed");
2101        goto bail;
2102    }
2103
2104    for (idx = 0; idx < count; idx++) {
2105        Thread* self = dvmThreadSelf();
2106        const DexAnnotationSetRefItem* pItem;
2107        const DexAnnotationSetItem* pAnnoSet;
2108        Object *annoSet;
2109        DexAnnotationSetItem emptySet;
2110        emptySet.size = 0;
2111
2112        pItem = dexGetParameterAnnotationSetRef(pAnnoSetList, idx);
2113        pAnnoSet = dexGetSetRefItemItem(pDexFile, pItem);
2114        if (pAnnoSet == NULL) {
2115            pAnnoSet = &emptySet;
2116        }
2117
2118        annoSet = (Object *)processAnnotationSet(clazz,
2119                                                 pAnnoSet,
2120                                                 kDexVisibilityRuntime);
2121        if (annoSet == NULL) {
2122            ALOGW("processAnnotationSet failed");
2123            annoArrayArray = NULL;
2124            goto bail;
2125        }
2126        dvmSetObjectArrayElement(annoArrayArray, idx, annoSet);
2127        dvmReleaseTrackedAlloc((Object*) annoSet, self);
2128    }
2129
2130bail:
2131    return annoArrayArray;
2132}
2133
2134/*
2135 * Find the DexAnnotationSetItem for this parameter.
2136 *
2137 * Returns NULL if none found.
2138 */
2139static const DexParameterAnnotationsItem* findAnnotationsItemForMethod(
2140    const Method* method)
2141{
2142    ClassObject* clazz = method->clazz;
2143    DexFile* pDexFile;
2144    const DexAnnotationsDirectoryItem* pAnnoDir;
2145    const DexParameterAnnotationsItem* pParameterList;
2146
2147    if (clazz->pDvmDex == NULL)         /* generated class (Proxy, array) */
2148        return NULL;
2149
2150    pDexFile = clazz->pDvmDex->pDexFile;
2151    pAnnoDir = getAnnoDirectory(pDexFile, clazz);
2152    if (pAnnoDir == NULL)
2153        return NULL;
2154
2155    pParameterList = dexGetParameterAnnotations(pDexFile, pAnnoDir);
2156    if (pParameterList == NULL)
2157        return NULL;
2158
2159    /*
2160     * Run through the list and find a matching method.  We compare the
2161     * method ref indices in the annotation list with the method's DEX
2162     * method_idx value.
2163     *
2164     * TODO: use a binary search for long lists
2165     *
2166     * Alternate approach: for each entry in the annotations list,
2167     * find the method definition in the DEX file and perform string
2168     * comparisons on class name, method name, and signature.
2169     */
2170    u4 methodIdx = getMethodIdx(method);
2171    u4 count = dexGetParameterAnnotationsSize(pDexFile, pAnnoDir);
2172    u4 idx;
2173
2174    for (idx = 0; idx < count; idx++) {
2175        if (pParameterList[idx].methodIdx == methodIdx) {
2176            /* found! */
2177            return &pParameterList[idx];
2178        }
2179    }
2180
2181    return NULL;
2182}
2183
2184
2185/*
2186 * Count up the number of arguments the method takes.  The "this" pointer
2187 * doesn't count.
2188 */
2189static int countMethodArguments(const Method* method)
2190{
2191    /* method->shorty[0] is the return type */
2192    return strlen(method->shorty + 1);
2193}
2194
2195/*
2196 * Return an array of arrays of Annotation objects.  The outer array has
2197 * one entry per method parameter, the inner array has the list of annotations
2198 * associated with that parameter.
2199 *
2200 * If the method has no parameters, we return an array of length zero.  If
2201 * the method has one or more parameters, we return an array whose length
2202 * is equal to the number of parameters; if a given parameter does not have
2203 * an annotation, the corresponding entry will be null.
2204 *
2205 * Caller must call dvmReleaseTrackedAlloc().
2206 */
2207ArrayObject* dvmGetParameterAnnotations(const Method* method)
2208{
2209    ClassObject* clazz = method->clazz;
2210    const DexParameterAnnotationsItem* pItem;
2211    ArrayObject* annoArrayArray = NULL;
2212
2213    pItem = findAnnotationsItemForMethod(method);
2214    if (pItem != NULL) {
2215        DexFile* pDexFile = clazz->pDvmDex->pDexFile;
2216        const DexAnnotationSetRefList* pAnnoSetList;
2217        u4 size;
2218
2219        size = dexGetParameterAnnotationSetRefSize(pDexFile, pItem);
2220        pAnnoSetList = dexGetParameterAnnotationSetRefList(pDexFile, pItem);
2221        annoArrayArray = processAnnotationSetRefList(clazz, pAnnoSetList, size);
2222    } else {
2223        /* no matching annotations found */
2224        annoArrayArray = emptyAnnoArrayArray(countMethodArguments(method));
2225    }
2226
2227    return annoArrayArray;
2228}
2229
2230
2231/*
2232 * ===========================================================================
2233 *      DexEncodedArray interpretation
2234 * ===========================================================================
2235 */
2236
2237/**
2238 * Initializes an encoded array iterator.
2239 *
2240 * @param iterator iterator to initialize
2241 * @param encodedArray encoded array to iterate over
2242 * @param clazz class to use when resolving strings and types
2243 */
2244void dvmEncodedArrayIteratorInitialize(EncodedArrayIterator* iterator,
2245        const DexEncodedArray* encodedArray, const ClassObject* clazz) {
2246    iterator->encodedArray = encodedArray;
2247    iterator->cursor = encodedArray->array;
2248    iterator->size = readUleb128(&iterator->cursor);
2249    iterator->elementsLeft = iterator->size;
2250    iterator->clazz = clazz;
2251}
2252
2253/**
2254 * Returns whether there are more elements to be read.
2255 */
2256bool dvmEncodedArrayIteratorHasNext(const EncodedArrayIterator* iterator) {
2257    return (iterator->elementsLeft != 0);
2258}
2259
2260/**
2261 * Returns the next decoded value from the iterator, advancing its
2262 * cursor. This returns primitive values in their corresponding union
2263 * slots, and returns everything else (including nulls) as object
2264 * references in the "l" union slot.
2265 *
2266 * The caller must call dvmReleaseTrackedAlloc() on any returned reference.
2267 *
2268 * @param value pointer to store decoded value into
2269 * @returns true if a value was decoded and the cursor advanced; false if
2270 * the last value had already been decoded or if there was a problem decoding
2271 */
2272bool dvmEncodedArrayIteratorGetNext(EncodedArrayIterator* iterator,
2273        AnnotationValue* value) {
2274    bool processed;
2275
2276    if (iterator->elementsLeft == 0) {
2277        return false;
2278    }
2279
2280    processed = processAnnotationValue(iterator->clazz, &iterator->cursor,
2281            value, kPrimitivesOrObjects);
2282
2283    if (! processed) {
2284        ALOGE("Failed to process array element %d from %p",
2285                iterator->size - iterator->elementsLeft,
2286                iterator->encodedArray);
2287        iterator->elementsLeft = 0;
2288        return false;
2289    }
2290
2291    iterator->elementsLeft--;
2292    return true;
2293}
2294