Merge "Revert "Revert "Move annotations to native."""
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java
index 7e5cfb7..0dc4bc4 100644
--- a/libart/src/main/java/java/lang/Class.java
+++ b/libart/src/main/java/java/lang/Class.java
@@ -37,6 +37,7 @@
 import java.io.InputStream;
 import java.io.Serializable;
 import java.lang.annotation.Annotation;
+import java.lang.annotation.Inherited;
 import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Constructor;
@@ -53,7 +54,9 @@
 import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import libcore.reflect.AnnotationAccess;
 import libcore.reflect.GenericSignatureParser;
@@ -354,7 +357,25 @@
     }
 
     @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
-        return AnnotationAccess.getAnnotation(this, annotationType);
+        if (annotationType == null) {
+            throw new NullPointerException("annotationType == null");
+        }
+
+        A annotation = getDeclaredAnnotation(annotationType);
+        if (annotation != null) {
+            return annotation;
+        }
+
+        if (annotationType.isDeclaredAnnotationPresent(Inherited.class)) {
+            for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+                annotation = sup.getDeclaredAnnotation(annotationType);
+                if (annotation != null) {
+                    return annotation;
+                }
+            }
+        }
+
+        return null;
     }
 
     /**
@@ -364,7 +385,33 @@
      * @see #getDeclaredAnnotations()
      */
     @Override public Annotation[] getAnnotations() {
-        return AnnotationAccess.getAnnotations(this);
+        /*
+         * We need to get the annotations declared on this class, plus the
+         * annotations from superclasses that have the "@Inherited" annotation
+         * set.  We create a temporary map to use while we accumulate the
+         * annotations and convert it to an array at the end.
+         *
+         * It's possible to have duplicates when annotations are inherited.
+         * We use a Map to filter those out.
+         *
+         * HashMap might be overkill here.
+         */
+        HashMap<Class<?>, Annotation> map = new HashMap<Class<?>, Annotation>();
+        for (Annotation declaredAnnotation : getDeclaredAnnotations()) {
+            map.put(declaredAnnotation.annotationType(), declaredAnnotation);
+        }
+        for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+            for (Annotation declaredAnnotation : sup.getDeclaredAnnotations()) {
+                Class<? extends Annotation> clazz = declaredAnnotation.annotationType();
+                if (!map.containsKey(clazz) && clazz.isDeclaredAnnotationPresent(Inherited.class)) {
+                    map.put(clazz, declaredAnnotation);
+                }
+            }
+        }
+
+        /* Convert annotation values from HashMap to array. */
+        Collection<Annotation> coll = map.values();
+        return coll.toArray(new Annotation[coll.size()]);
     }
 
     /**
@@ -737,10 +784,17 @@
      *
      * @see #getAnnotations()
      */
-    @Override public Annotation[] getDeclaredAnnotations() {
-        List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
-        return result.toArray(new Annotation[result.size()]);
-    }
+    @Override public native Annotation[] getDeclaredAnnotations();
+
+    /**
+     * Returns the annotation if it exists.
+     */
+    private native <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass);
+
+    /**
+     * Returns true if the annotation exists.
+     */
+    private native boolean isDeclaredAnnotationPresent(Class<? extends Annotation> annotationClass);
 
     /**
      * Returns an array containing {@code Class} objects for all classes,
@@ -796,7 +850,7 @@
      * method or constructor.
      */
     public Class<?> getDeclaringClass() {
-        if (AnnotationAccess.isAnonymousClass(this)) {
+        if (isAnonymousClass()) {
             return null;
         }
         return AnnotationAccess.getEnclosingClass(this);
@@ -1223,7 +1277,23 @@
     }
 
     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
-        return AnnotationAccess.isAnnotationPresent(this, annotationType);
+        if (annotationType == null) {
+            throw new NullPointerException("annotationType == null");
+        }
+
+        if (isDeclaredAnnotationPresent(annotationType)) {
+            return true;
+        }
+
+        if (annotationType.isDeclaredAnnotationPresent(Inherited.class)) {
+            for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+                if (sup.isDeclaredAnnotationPresent(annotationType)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
     }
 
     /**
diff --git a/libart/src/main/java/java/lang/reflect/Constructor.java b/libart/src/main/java/java/lang/reflect/Constructor.java
index 9711ef4..0dadd8d 100644
--- a/libart/src/main/java/java/lang/reflect/Constructor.java
+++ b/libart/src/main/java/java/lang/reflect/Constructor.java
@@ -36,7 +36,6 @@
 import java.lang.annotation.Annotation;
 import java.util.Comparator;
 import java.util.List;
-import libcore.reflect.AnnotationAccess;
 import libcore.reflect.Types;
 
 /**
@@ -97,10 +96,7 @@
      * this constructor has no declared exceptions, an empty array will be
      * returned.
      */
-    public Class<?>[] getExceptionTypes() {
-        // TODO: use dex cache to speed looking up class
-        return AnnotationAccess.getExceptions(this);
-    }
+    public native Class<?>[] getExceptionTypes();
 
     /**
      * Returns an array of the {@code Class} objects associated with the
@@ -181,24 +177,23 @@
         return super.getGenericExceptionTypes();
     }
 
-    @Override public Annotation[] getDeclaredAnnotations() {
-        List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
-        return result.toArray(new Annotation[result.size()]);
-    }
+    @Override public native Annotation[] getDeclaredAnnotations();
 
     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
         if (annotationType == null) {
             throw new NullPointerException("annotationType == null");
         }
-        return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+        return isAnnotationPresentNative(annotationType);
     }
+    private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
 
     @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
         if (annotationType == null) {
             throw new NullPointerException("annotationType == null");
         }
-        return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+        return getAnnotationNative(annotationType);
     }
+    private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType);
 
     /**
      * Returns an array of arrays that represent the annotations of the formal
@@ -209,9 +204,13 @@
      * @return an array of arrays of {@code Annotation} instances
      */
     public Annotation[][] getParameterAnnotations() {
-        return AnnotationAccess.getParameterAnnotations(
-            declaringClassOfOverriddenMethod, dexMethodIndex);
+        Annotation[][] parameterAnnotations = getParameterAnnotationsNative();
+        if (parameterAnnotations == null) {
+          parameterAnnotations = new Annotation[getParameterTypes().length][0];
+        }
+        return parameterAnnotations;
     }
+    private native Annotation[][] getParameterAnnotationsNative();
 
     /**
      * Returns the constructor's signature in non-printable form. This is called
diff --git a/libart/src/main/java/java/lang/reflect/Field.java b/libart/src/main/java/java/lang/reflect/Field.java
index 37f2ad0..06cc0b2 100644
--- a/libart/src/main/java/java/lang/reflect/Field.java
+++ b/libart/src/main/java/java/lang/reflect/Field.java
@@ -36,7 +36,6 @@
 import java.lang.annotation.Annotation;
 import java.util.Comparator;
 import java.util.List;
-import libcore.reflect.AnnotationAccess;
 import libcore.reflect.GenericSignatureParser;
 import libcore.reflect.Types;
 
@@ -218,7 +217,7 @@
      *             instantiated for some reason
      */
     public Type getGenericType() {
-        String signatureAttribute = AnnotationAccess.getSignature(this);
+        String signatureAttribute = getSignatureAttribute();
         Class<?> declaringClass = getDeclaringClass();
         ClassLoader cl = declaringClass.getClassLoader();
         GenericSignatureParser parser = new GenericSignatureParser(cl);
@@ -230,6 +229,19 @@
         return genericType;
     }
 
+    private String getSignatureAttribute() {
+        String[] annotation = getSignatureAnnotation();
+        if (annotation == null) {
+            return null;
+        }
+        StringBuilder result = new StringBuilder();
+        for (String s : annotation) {
+          result.append(s);
+        }
+        return result.toString();
+    }
+    private native String[] getSignatureAnnotation();
+
     /**
      * Returns the constructor's signature in non-printable form. This is called
      * (only) from IO native code and needed for deriving the serialVersionUID
@@ -240,24 +252,23 @@
         return Types.getSignature(getType());
     }
 
-    @Override public Annotation[] getDeclaredAnnotations() {
-        List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
-        return result.toArray(new Annotation[result.size()]);
-    }
+    @Override public native Annotation[] getDeclaredAnnotations();
 
     @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
         if (annotationType == null) {
             throw new NullPointerException("annotationType == null");
         }
-        return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+        return getAnnotationNative(annotationType);
     }
+    private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType);
 
     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
         if (annotationType == null) {
             throw new NullPointerException("annotationType == null");
         }
-        return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+        return isAnnotationPresentNative(annotationType);
     }
+    private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
 
     /**
      * Returns the value of the field in the specified object. This reproduces
diff --git a/libart/src/main/java/java/lang/reflect/Method.java b/libart/src/main/java/java/lang/reflect/Method.java
index a07ec6f..79287ba 100644
--- a/libart/src/main/java/java/lang/reflect/Method.java
+++ b/libart/src/main/java/java/lang/reflect/Method.java
@@ -36,7 +36,6 @@
 import java.lang.annotation.Annotation;
 import java.util.Comparator;
 import java.util.List;
-import libcore.reflect.AnnotationAccess;
 import libcore.reflect.Types;
 
 /**
@@ -148,16 +147,7 @@
      *
      * @return the declared exception classes
      */
-    public Class<?>[] getExceptionTypes() {
-        if (getDeclaringClass().isProxy()) {
-            return getExceptionTypesNative();
-        } else {
-            // TODO: use dex cache to speed looking up class
-            return AnnotationAccess.getExceptions(this);
-        }
-    }
-
-    private native Class<?>[] getExceptionTypesNative();
+    public native Class<?>[] getExceptionTypes();
 
     /**
      * Returns an array of {@code Class} objects associated with the parameter
@@ -250,8 +240,9 @@
         if (annotationType == null) {
             throw new NullPointerException("annotationType == null");
         }
-        return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+        return isAnnotationPresentNative(annotationType);
     }
+    private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
 
     /**
      * Returns the exception types as an array of {@code Type} instances. If
@@ -288,17 +279,15 @@
         return Types.getType(getMethodOrConstructorGenericInfo().genericReturnType);
     }
 
-    @Override public Annotation[] getDeclaredAnnotations() {
-        List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
-        return result.toArray(new Annotation[result.size()]);
-    }
+    @Override public native Annotation[] getDeclaredAnnotations();
 
     @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
         if (annotationType == null) {
             throw new NullPointerException("annotationType == null");
         }
-        return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+        return getAnnotationNative(annotationType);
     }
+    private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType);
 
     /**
      * Returns an array of arrays that represent the annotations of the formal
@@ -309,9 +298,13 @@
      * @return an array of arrays of {@code Annotation} instances
      */
     public Annotation[][] getParameterAnnotations() {
-        return AnnotationAccess.getParameterAnnotations(
-            declaringClassOfOverriddenMethod, dexMethodIndex);
+        Annotation[][] parameterAnnotations = getParameterAnnotationsNative();
+        if (parameterAnnotations == null) {
+          parameterAnnotations = new Annotation[getParameterTypes().length][0];
+        }
+        return parameterAnnotations;
     }
+    private native Annotation[][] getParameterAnnotationsNative();
 
     /**
      * Returns the default value for the annotation member represented by this
@@ -323,9 +316,7 @@
      *             if this annotation member is of type {@code Class} and no
      *             definition can be found
      */
-    public Object getDefaultValue() {
-        return AnnotationAccess.getDefaultValue(this);
-    }
+    public native Object getDefaultValue();
 
     /**
      * Returns the result of dynamically invoking this method. Equivalent to