Support reflective lookup of single fields.

Change-Id: Ie7058fa9de8212b0f52d5d9b0ec7d46242a851fc
http://b/4087759
diff --git a/vm/native/java_lang_Class.c b/vm/native/java_lang_Class.c
index 1a78e54..65fbbb7 100644
--- a/vm/native/java_lang_Class.c
+++ b/vm/native/java_lang_Class.c
@@ -242,7 +242,6 @@
 
 /*
  * static Field[] getDeclaredFields(Class klass, boolean publicOnly)
- *     throws SecurityException
  */
 static void Dalvik_java_lang_Class_getDeclaredFields(const u4* args,
     JValue* pResult)
@@ -258,6 +257,19 @@
 }
 
 /*
+ * static Field getDeclaredField(Class klass, String name)
+ */
+static void Dalvik_java_lang_Class_getDeclaredField(const u4* args,
+    JValue* pResult)
+{
+    ClassObject* clazz = (ClassObject*) args[0];
+    StringObject* nameObj = (StringObject*) args[1];
+    Object* fieldObj = dvmGetDeclaredField(clazz, nameObj);
+    dvmReleaseTrackedAlloc((Object*) fieldObj, NULL);
+    RETURN_PTR(fieldObj);
+}
+
+/*
  * static Method[] getDeclaredMethods(Class clazz, boolean publicOnly)
  *     throws SecurityException
  */
@@ -777,6 +789,8 @@
         Dalvik_java_lang_Class_getDeclaredFields },
     { "getDeclaredMethods",     "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;",
         Dalvik_java_lang_Class_getDeclaredMethods },
+    { "getDeclaredField",      "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;",
+        Dalvik_java_lang_Class_getDeclaredField },
     { "getDeclaredConstructorOrMethod", "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;",
         Dalvik_java_lang_Class_getDeclaredConstructorOrMethod },
     { "getInterfaces",          "()[Ljava/lang/Class;",
diff --git a/vm/reflect/Reflect.c b/vm/reflect/Reflect.c
index ae165dc..7a21ef3 100644
--- a/vm/reflect/Reflect.c
+++ b/vm/reflect/Reflect.c
@@ -801,6 +801,39 @@
 }
 
 /*
+ * Get the named field.
+ */
+Object* dvmGetDeclaredField(ClassObject* clazz, StringObject* nameObj)
+{
+    int i;
+    Object* fieldObj = NULL;
+    char* name = dvmCreateCstrFromString(nameObj);
+
+    if (!dvmIsClassInitialized(gDvm.classJavaLangReflectField))
+        dvmInitClass(gDvm.classJavaLangReflectField);
+
+    for (i = 0; i < clazz->sfieldCount; i++) {
+        Field* field = &clazz->sfields[i].field;
+        if (strcmp(name, field->name) == 0) {
+            fieldObj = createFieldObject(field, clazz);
+            break;
+        }
+    }
+    if (fieldObj == NULL) {
+        for (i = 0; i < clazz->ifieldCount; i++) {
+            Field* field = &clazz->ifields[i].field;
+            if (strcmp(name, field->name) == 0) {
+                fieldObj = createFieldObject(field, clazz);
+                break;
+            }
+        }
+    }
+
+    free(name);
+    return fieldObj;
+}
+
+/*
  * Get all interfaces a class implements. If this is unable to allocate
  * the result array, this raises an OutOfMemoryError and returns NULL.
  */
diff --git a/vm/reflect/Reflect.h b/vm/reflect/Reflect.h
index c1f2276..80e96fa 100644
--- a/vm/reflect/Reflect.h
+++ b/vm/reflect/Reflect.h
@@ -32,6 +32,11 @@
 ArrayObject* dvmGetDeclaredFields(ClassObject* clazz, bool publicOnly);
 
 /*
+ * Get the named field.
+ */
+Object* dvmGetDeclaredField(ClassObject* clazz, StringObject* nameObj);
+
+/*
  * Get all constructors declared by a class.
  */
 ArrayObject* dvmGetDeclaredConstructors(ClassObject* clazz, bool publicOnly);