Camera: Make CameraMetadataNative compile-time initializable

Ensure that all static initializer code can be executed in the
compiler. Move native field caching into the native method
registration function.

Saves up to 10ms on N6P zygote initialization.

Bug: 34956610
Test: m
Test: Device boots (N6P)
Test: Can take pictures and videos (N6P)
Change-Id: I481dfd3aa8dc3cc5a5c31eedad31390d8afda897
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 0e450d7..4d92ab1 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -1097,7 +1097,6 @@
             throws IllegalArgumentException;
     private static native int nativeGetTypeFromTag(int tag)
             throws IllegalArgumentException;
-    private static native void nativeClassInit();
 
     /**
      * <p>Perform a 0-copy swap of the internal metadata with another object.</p>
@@ -1289,10 +1288,6 @@
     }
 
     static {
-        /*
-         * We use a class initializer to allow the native code to cache some field offsets
-         */
-        nativeClassInit();
         registerAllMarshalers();
     }
 }
diff --git a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableString.java b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableString.java
index d2c3908..c81e18d 100644
--- a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableString.java
+++ b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableString.java
@@ -33,7 +33,9 @@
     private static final String TAG = MarshalQueryableString.class.getSimpleName();
     private static final boolean DEBUG = false;
 
-    private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
+    private static class PreloadHolder {
+        public static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
+    }
     private static final byte NUL = (byte)'\0'; // used as string terminator
 
     private class MarshalerString extends Marshaler<String> {
@@ -44,7 +46,7 @@
 
         @Override
         public void marshal(String value, ByteBuffer buffer) {
-            byte[] arr = value.getBytes(UTF8_CHARSET);
+            byte[] arr = value.getBytes(PreloadHolder.UTF8_CHARSET);
 
             buffer.put(arr);
             buffer.put(NUL); // metadata strings are NUL-terminated
@@ -52,7 +54,7 @@
 
         @Override
         public int calculateMarshalSize(String value) {
-            byte[] arr = value.getBytes(UTF8_CHARSET);
+            byte[] arr = value.getBytes(PreloadHolder.UTF8_CHARSET);
 
             return arr.length + 1; // metadata strings are NUL-terminated
         }
@@ -88,7 +90,7 @@
             buffer.get(strBytes, /*dstOffset*/0, stringLength + 1); // including null character
 
             // not including null character
-            return new String(strBytes, /*offset*/0, stringLength, UTF8_CHARSET);
+            return new String(strBytes, /*offset*/0, stringLength, PreloadHolder.UTF8_CHARSET);
         }
 
         @Override
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 518f99e..78a5735 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -161,7 +161,6 @@
 
 extern "C" {
 
-static void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
 static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType);
 static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName);
 static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag);
@@ -529,9 +528,6 @@
 
 static const JNINativeMethod gCameraMetadataMethods[] = {
 // static methods
-  { "nativeClassInit",
-    "()V",
-    (void *)CameraMetadata_classInit },
   { "nativeGetAllVendorKeys",
     "(Ljava/lang/Class;)Ljava/util/ArrayList;",
     (void *)CameraMetadata_getAllVendorKeys},
@@ -581,35 +577,6 @@
     (void *)CameraMetadata_writeToParcel },
 };
 
-struct field {
-    const char *class_name;
-    const char *field_name;
-    const char *field_type;
-    jfieldID   *jfield;
-};
-
-static int find_fields(JNIEnv *env, field *fields, int count)
-{
-    for (int i = 0; i < count; i++) {
-        field *f = &fields[i];
-        jclass clazz = env->FindClass(f->class_name);
-        if (clazz == NULL) {
-            ALOGE("Can't find %s", f->class_name);
-            return -1;
-        }
-
-        jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type);
-        if (field == NULL) {
-            ALOGE("Can't find %s.%s", f->class_name, f->field_name);
-            return -1;
-        }
-
-        *(f->jfield) = field;
-    }
-
-    return 0;
-}
-
 // Get all the required offsets in java class and register native functions
 int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
 {
@@ -651,6 +618,9 @@
     gMetadataOffsets.mArrayListAdd = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
             "add", "(Ljava/lang/Object;)Z");
 
+    jclass cameraMetadataClazz = FindClassOrDie(env, CAMERA_METADATA_CLASS_NAME);
+    fields.metadata_ptr = GetFieldIDOrDie(env, cameraMetadataClazz, "mMetadataPtr", "J");
+
     // Register native functions
     return RegisterMethodsOrDie(env,
             CAMERA_METADATA_CLASS_NAME,
@@ -660,22 +630,6 @@
 
 extern "C" {
 
-static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
-    // XX: Why do this separately instead of doing it in the register function?
-    ALOGV("%s", __FUNCTION__);
-
-    field fields_to_find[] = {
-        { CAMERA_METADATA_CLASS_NAME, "mMetadataPtr", "J", &fields.metadata_ptr },
-    };
-
-    // Do this here instead of in register_native_methods,
-    // since otherwise it will fail to find the fields.
-    if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
-        return;
-
-    env->FindClass(CAMERA_METADATA_CLASS_NAME);
-}
-
 static jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType) {
 
     // Get all vendor tags