Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 08e6c34c authored by Andreas Gampe's avatar Andreas Gampe
Browse files

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
parent 977e656e
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -1097,7 +1097,6 @@ public class CameraMetadataNative implements Parcelable {
            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 @@ public class CameraMetadataNative implements Parcelable {
    }

    static {
        /*
         * We use a class initializer to allow the native code to cache some field offsets
         */
        nativeClassInit();
        registerAllMarshalers();
    }
}
+6 −4
Original line number Diff line number Diff line
@@ -33,7 +33,9 @@ public class MarshalQueryableString implements MarshalQueryable<String> {
    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 @@ public class MarshalQueryableString implements MarshalQueryable<String> {

        @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 @@ public class MarshalQueryableString implements MarshalQueryable<String> {

        @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 @@ public class MarshalQueryableString implements MarshalQueryable<String> {
            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
+3 −49
Original line number Diff line number Diff line
@@ -161,7 +161,6 @@ struct Helpers {

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 void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parc

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 @@ static const JNINativeMethod gCameraMetadataMethods[] = {
    (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 @@ int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
    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 @@ int register_android_hardware_camera2_CameraMetadata(JNIEnv *env)

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