bool DexFile::ProcessAnnotationValue()

in runtime/dex_file.cc [1836:2097]


bool DexFile::ProcessAnnotationValue(Handle<mirror::Class> klass, const uint8_t** annotation_ptr,
    AnnotationValue* annotation_value, Handle<mirror::Class> array_class,
    DexFile::AnnotationResultStyle result_style) const {
  Thread* self = Thread::Current();
  mirror::Object* element_object = nullptr;
  bool set_object = false;
  Primitive::Type primitive_type = Primitive::kPrimVoid;
  const uint8_t* annotation = *annotation_ptr;
  uint8_t header_byte = *(annotation++);
  uint8_t value_type = header_byte & kDexAnnotationValueTypeMask;
  uint8_t value_arg = header_byte >> kDexAnnotationValueArgShift;
  int32_t width = value_arg + 1;
  annotation_value->type_ = value_type;

  switch (value_type) {
    case kDexAnnotationByte:
      annotation_value->value_.SetB(static_cast<int8_t>(ReadSignedInt(annotation, value_arg)));
      primitive_type = Primitive::kPrimByte;
      break;
    case kDexAnnotationShort:
      annotation_value->value_.SetS(static_cast<int16_t>(ReadSignedInt(annotation, value_arg)));
      primitive_type = Primitive::kPrimShort;
      break;
    case kDexAnnotationChar:
      annotation_value->value_.SetC(static_cast<uint16_t>(ReadUnsignedInt(annotation, value_arg,
                                                                          false)));
      primitive_type = Primitive::kPrimChar;
      break;
    case kDexAnnotationInt:
      annotation_value->value_.SetI(ReadSignedInt(annotation, value_arg));
      primitive_type = Primitive::kPrimInt;
      break;
    case kDexAnnotationLong:
      annotation_value->value_.SetJ(ReadSignedLong(annotation, value_arg));
      primitive_type = Primitive::kPrimLong;
      break;
    case kDexAnnotationFloat:
      annotation_value->value_.SetI(ReadUnsignedInt(annotation, value_arg, true));
      primitive_type = Primitive::kPrimFloat;
      break;
    case kDexAnnotationDouble:
      annotation_value->value_.SetJ(ReadUnsignedLong(annotation, value_arg, true));
      primitive_type = Primitive::kPrimDouble;
      break;
    case kDexAnnotationBoolean:
      annotation_value->value_.SetZ(value_arg != 0);
      primitive_type = Primitive::kPrimBoolean;
      width = 0;
      break;
    case kDexAnnotationString: {
      uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        StackHandleScope<1> hs(self);
        Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
        element_object = Runtime::Current()->GetClassLinker()->ResolveString(
            klass->GetDexFile(), index, dex_cache);
        set_object = true;
        if (element_object == nullptr) {
          return false;
        }
      }
      break;
    }
    case kDexAnnotationType: {
      uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        element_object = Runtime::Current()->GetClassLinker()->ResolveType(
            klass->GetDexFile(), index, klass.Get());
        set_object = true;
        if (element_object == nullptr) {
          CHECK(self->IsExceptionPending());
          if (result_style == kAllObjects) {
            const char* msg = StringByTypeIdx(index);
            self->ThrowNewWrappedException("Ljava/lang/TypeNotPresentException;", msg);
            element_object = self->GetException();
            self->ClearException();
          } else {
            return false;
          }
        }
      }
      break;
    }
    case kDexAnnotationMethod: {
      uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        StackHandleScope<2> hs(self);
        Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
        Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
        ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodWithoutInvokeType(
            klass->GetDexFile(), index, dex_cache, class_loader);
        if (method == nullptr) {
          return false;
        }
        set_object = true;
        if (method->IsConstructor()) {
          element_object = mirror::Constructor::CreateFromArtMethod(self, method);
        } else {
          element_object = mirror::Method::CreateFromArtMethod(self, method);
        }
        if (element_object == nullptr) {
          return false;
        }
      }
      break;
    }
    case kDexAnnotationField: {
      uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        StackHandleScope<2> hs(self);
        Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
        Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
        ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(
            klass->GetDexFile(), index, dex_cache, class_loader);
        if (field == nullptr) {
          return false;
        }
        set_object = true;
        element_object = mirror::Field::CreateFromArtField(self, field, true);
        if (element_object == nullptr) {
          return false;
        }
      }
      break;
    }
    case kDexAnnotationEnum: {
      uint32_t index = ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        StackHandleScope<3> hs(self);
        Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
        Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
        ArtField* enum_field = Runtime::Current()->GetClassLinker()->ResolveField(
            klass->GetDexFile(), index, dex_cache, class_loader, true);
        if (enum_field == nullptr) {
          return false;
        } else {
          Handle<mirror::Class> field_class(hs.NewHandle(enum_field->GetDeclaringClass()));
          Runtime::Current()->GetClassLinker()->EnsureInitialized(self, field_class, true, true);
          element_object = enum_field->GetObject(field_class.Get());
          set_object = true;
        }
      }
      break;
    }
    case kDexAnnotationArray:
      if (result_style == kAllRaw || array_class.Get() == nullptr) {
        return false;
      } else {
        ScopedObjectAccessUnchecked soa(self);
        StackHandleScope<2> hs(self);
        uint32_t size = DecodeUnsignedLeb128(&annotation);
        Handle<mirror::Class> component_type(hs.NewHandle(array_class->GetComponentType()));
        Handle<mirror::Array> new_array(hs.NewHandle(mirror::Array::Alloc<true>(
            self, array_class.Get(), size, array_class->GetComponentSizeShift(),
            Runtime::Current()->GetHeap()->GetCurrentAllocator())));
        if (new_array.Get() == nullptr) {
          LOG(ERROR) << "Annotation element array allocation failed with size " << size;
          return false;
        }
        AnnotationValue new_annotation_value;
        for (uint32_t i = 0; i < size; ++i) {
          if (!ProcessAnnotationValue(klass, &annotation, &new_annotation_value, component_type,
                                      kPrimitivesOrObjects)) {
            return false;
          }
          if (!component_type->IsPrimitive()) {
            mirror::Object* obj = new_annotation_value.value_.GetL();
            new_array->AsObjectArray<mirror::Object>()->SetWithoutChecks<false>(i, obj);
          } else {
            switch (new_annotation_value.type_) {
              case kDexAnnotationByte:
                new_array->AsByteArray()->SetWithoutChecks<false>(
                    i, new_annotation_value.value_.GetB());
                break;
              case kDexAnnotationShort:
                new_array->AsShortArray()->SetWithoutChecks<false>(
                    i, new_annotation_value.value_.GetS());
                break;
              case kDexAnnotationChar:
                new_array->AsCharArray()->SetWithoutChecks<false>(
                    i, new_annotation_value.value_.GetC());
                break;
              case kDexAnnotationInt:
                new_array->AsIntArray()->SetWithoutChecks<false>(
                    i, new_annotation_value.value_.GetI());
                break;
              case kDexAnnotationLong:
                new_array->AsLongArray()->SetWithoutChecks<false>(
                    i, new_annotation_value.value_.GetJ());
                break;
              case kDexAnnotationFloat:
                new_array->AsFloatArray()->SetWithoutChecks<false>(
                    i, new_annotation_value.value_.GetF());
                break;
              case kDexAnnotationDouble:
                new_array->AsDoubleArray()->SetWithoutChecks<false>(
                    i, new_annotation_value.value_.GetD());
                break;
              case kDexAnnotationBoolean:
                new_array->AsBooleanArray()->SetWithoutChecks<false>(
                    i, new_annotation_value.value_.GetZ());
                break;
              default:
                LOG(FATAL) << "Found invalid annotation value type while building annotation array";
                return false;
            }
          }
        }
        element_object = new_array.Get();
        set_object = true;
        width = 0;
      }
      break;
    case kDexAnnotationAnnotation:
      if (result_style == kAllRaw) {
        return false;
      }
      element_object = ProcessEncodedAnnotation(klass, &annotation);
      if (element_object == nullptr) {
        return false;
      }
      set_object = true;
      width = 0;
      break;
    case kDexAnnotationNull:
      if (result_style == kAllRaw) {
        annotation_value->value_.SetI(0);
      } else {
        CHECK(element_object == nullptr);
        set_object = true;
      }
      width = 0;
      break;
    default:
      LOG(ERROR) << StringPrintf("Bad annotation element value type 0x%02x", value_type);
      return false;
  }

  annotation += width;
  *annotation_ptr = annotation;

  if (result_style == kAllObjects && primitive_type != Primitive::kPrimVoid) {
    element_object = BoxPrimitive(primitive_type, annotation_value->value_);
    set_object = true;
  }

  if (set_object) {
    annotation_value->value_.SetL(element_object);
  }

  return true;
}