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

Commit 2a822ea9 authored by Orion Hodson's avatar Orion Hodson
Browse files

Fix warning about recursive loading of libmedia_jni.so

JNI register methods were resolving classes to initialize fieldID's
and methodID's for native JNI use. Those classes may have static
initializers which call System.loadLibrary("libmedia_jni.so"), but the
library is already in the process of being loaded.

Bug: 180829511
Test: TH
Test: boot blueline observe no output from "adb logcat -d | grep recursive"
Change-Id: I47d40bc06457a9550bd5855f6f8d031ddc465b47
parent 25cc8e41
Loading
Loading
Loading
Loading
+25 −20
Original line number Diff line number Diff line
@@ -43,12 +43,34 @@ struct fields_t {
    jfieldID  nativePlayerInJavaObj; // stores in Java the native JetPlayer object
};

static fields_t javaJetPlayerFields;
static fields_t javaJetPlayerFields {};

#define JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME "mNativePlayerInJavaObj"
#define JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME "postEventFromNative"

static void initializeJavaIDs(JNIEnv* env) {
    static std::once_flag sJniInitialized;

    std::call_once(sJniInitialized, [](JNIEnv* env) {
        // Get the JetPlayer java class
        jclass jetPlayerClass = FindClassOrDie(env, kClassPathName);
        javaJetPlayerFields.jetClass = MakeGlobalRefOrDie(env, jetPlayerClass);

        // Get the mNativePlayerInJavaObj variable field
        javaJetPlayerFields.nativePlayerInJavaObj =
                GetFieldIDOrDie(env, jetPlayerClass, JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME, "J");

        // Get the callback to post events from this native code to Java
        javaJetPlayerFields.postNativeEventInJava = GetStaticMethodIDOrDie(env,
                javaJetPlayerFields.jetClass, JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME,
                "(Ljava/lang/Object;III)V");
    }, env);
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------


/*
 * This function is called from JetPlayer instance's render thread
 */
@@ -79,6 +101,8 @@ static jboolean
android_media_JetPlayer_setup(JNIEnv *env, jobject thiz, jobject weak_this,
    jint maxTracks, jint trackBufferSize)
{
    initializeJavaIDs(env);

    //ALOGV("android_media_JetPlayer_setup(): entering.");
    JetPlayer* lpJet = new JetPlayer(env->NewGlobalRef(weak_this), maxTracks, trackBufferSize);

@@ -511,28 +535,9 @@ static const JNINativeMethod gMethods[] = {
    {"native_clearQueue",  "()Z",                   (void *)android_media_JetPlayer_clearQueue},
};

#define JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME "mNativePlayerInJavaObj"
#define JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME "postEventFromNative"


int register_android_media_JetPlayer(JNIEnv *env)
{
    javaJetPlayerFields.jetClass = NULL;
    javaJetPlayerFields.postNativeEventInJava = NULL;
    javaJetPlayerFields.nativePlayerInJavaObj = NULL;

    // Get the JetPlayer java class
    jclass jetPlayerClass = FindClassOrDie(env, kClassPathName);
    javaJetPlayerFields.jetClass = MakeGlobalRefOrDie(env, jetPlayerClass);

    // Get the mNativePlayerInJavaObj variable field
    javaJetPlayerFields.nativePlayerInJavaObj = GetFieldIDOrDie(env,
            jetPlayerClass, JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME, "J");

    // Get the callback to post events from this native code to Java
    javaJetPlayerFields.postNativeEventInJava = GetStaticMethodIDOrDie(env,
            javaJetPlayerFields.jetClass, JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME,
            "(Ljava/lang/Object;III)V");

    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
+58 −61
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@

#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
#include "core_jni_helpers.h"
#include <jni.h>
#include <media/stagefright/NuMediaExtractor.h>
#include <nativehelper/JNIHelp.h>
@@ -48,6 +49,7 @@ using namespace android;

// ----------------------------------------------------------------------------

// MtpDatabase methods
static jmethodID method_beginSendObject;
static jmethodID method_endSendObject;
static jmethodID method_rescanFile;
@@ -75,6 +77,7 @@ static jmethodID method_endCopyObject;
static jmethodID method_getObjectReferences;
static jmethodID method_setObjectReferences;

// MtpDatabase fields.
static jfieldID field_context;

// MtpPropertyList methods
@@ -86,6 +89,59 @@ static jmethodID method_getDataTypes;
static jmethodID method_getLongValues;
static jmethodID method_getStringValues;

// Initializer for the jfieldIDs and jmethodIDs above. This method must be invoked
// before using these static fields and methods for JNI accesses.
static void initializeJavaIDs(JNIEnv* env) {
    static std::once_flag sJniInitialized;

#define GET_METHOD_ID(name, jclass, signature)                              \
    method_##name = GetMethodIDOrDie(env, jclass, #name, signature);

    std::call_once(sJniInitialized, [](JNIEnv* env) {
        const jclass mdb_class = FindClassOrDie(env, "android/mtp/MtpDatabase");
        GET_METHOD_ID(beginSendObject, mdb_class, "(Ljava/lang/String;III)I");
        GET_METHOD_ID(endSendObject, mdb_class, "(IZ)V");
        GET_METHOD_ID(rescanFile, mdb_class, "(Ljava/lang/String;II)V");
        GET_METHOD_ID(getObjectList, mdb_class, "(III)[I");
        GET_METHOD_ID(getNumObjects, mdb_class, "(III)I");
        GET_METHOD_ID(getSupportedPlaybackFormats, mdb_class, "()[I");
        GET_METHOD_ID(getSupportedCaptureFormats, mdb_class, "()[I");
        GET_METHOD_ID(getSupportedObjectProperties, mdb_class, "(I)[I");
        GET_METHOD_ID(getSupportedDeviceProperties, mdb_class, "()[I");
        GET_METHOD_ID(setObjectProperty, mdb_class, "(IIJLjava/lang/String;)I");
        GET_METHOD_ID(getDeviceProperty, mdb_class, "(I[J[C)I");
        GET_METHOD_ID(setDeviceProperty, mdb_class, "(IJLjava/lang/String;)I");
        GET_METHOD_ID(getObjectPropertyList, mdb_class, "(IIIII)Landroid/mtp/MtpPropertyList;");
        GET_METHOD_ID(getObjectInfo, mdb_class, "(I[I[C[J)Z");
        GET_METHOD_ID(getObjectFilePath, mdb_class, "(I[C[J)I");
        GET_METHOD_ID(openFilePath, mdb_class, "(Ljava/lang/String;Z)I");
        GET_METHOD_ID(getThumbnailInfo, mdb_class, "(I[J)Z");
        GET_METHOD_ID(getThumbnailData, mdb_class, "(I)[B");
        GET_METHOD_ID(beginDeleteObject, mdb_class, "(I)I");
        GET_METHOD_ID(endDeleteObject, mdb_class, "(IZ)V");
        GET_METHOD_ID(beginMoveObject, mdb_class, "(III)I");
        GET_METHOD_ID(endMoveObject, mdb_class, "(IIIIIZ)V");
        GET_METHOD_ID(beginCopyObject, mdb_class, "(III)I");
        GET_METHOD_ID(endCopyObject, mdb_class, "(IZ)V");
        GET_METHOD_ID(getObjectReferences, mdb_class, "(I)[I");
        GET_METHOD_ID(setObjectReferences, mdb_class, "(I[I)I");
        field_context = GetFieldIDOrDie(env, mdb_class, "mNativeContext", "J");

        const jclass mpl_class = FindClassOrDie(env, "android/mtp/MtpPropertyList");
        GET_METHOD_ID(getCode, mpl_class, "()I");
        GET_METHOD_ID(getCount, mpl_class, "()I");
        GET_METHOD_ID(getObjectHandles, mpl_class, "()[I");
        GET_METHOD_ID(getPropertyCodes, mpl_class, "()[I");
        GET_METHOD_ID(getDataTypes, mpl_class, "()[I");
        GET_METHOD_ID(getLongValues, mpl_class, "()[J");
        GET_METHOD_ID(getStringValues, mpl_class, "()[Ljava/lang/String;");

        return 0;
    }, env);

#undef GET_METHOD_ID
}


IMtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
    return (IMtpDatabase *)env->GetLongField(database, field_context);
@@ -1280,6 +1336,7 @@ MtpProperty* MtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
static void
android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
{
    initializeJavaIDs(env);
    MtpDatabase* database = new MtpDatabase(env, thiz);
    env->SetLongField(thiz, field_context, (jlong)database);
    checkAndClearExceptionFromCallback(env, __FUNCTION__);
@@ -1314,69 +1371,9 @@ static const JNINativeMethod gMtpPropertyGroupMethods[] = {
    {"format_date_time",        "(J)Ljava/lang/String;",
                                        (void *)android_mtp_MtpPropertyGroup_format_date_time},
};

#define GET_METHOD_ID(name, jclass, signature)                              \
    method_##name = env->GetMethodID(jclass, #name, signature);             \
    if (method_##name == NULL) {                                            \
        ALOGE("Can't find " #name);                                         \
        return -1;                                                          \
    }                                                                       \

                                                                   \
int register_android_mtp_MtpDatabase(JNIEnv *env)
{
    jclass clazz;

    clazz = env->FindClass("android/mtp/MtpDatabase");
    if (clazz == NULL) {
        ALOGE("Can't find android/mtp/MtpDatabase");
        return -1;
    }
    GET_METHOD_ID(beginSendObject, clazz, "(Ljava/lang/String;III)I");
    GET_METHOD_ID(endSendObject, clazz, "(IZ)V");
    GET_METHOD_ID(rescanFile, clazz, "(Ljava/lang/String;II)V");
    GET_METHOD_ID(getObjectList, clazz, "(III)[I");
    GET_METHOD_ID(getNumObjects, clazz, "(III)I");
    GET_METHOD_ID(getSupportedPlaybackFormats, clazz, "()[I");
    GET_METHOD_ID(getSupportedCaptureFormats, clazz, "()[I");
    GET_METHOD_ID(getSupportedObjectProperties, clazz, "(I)[I");
    GET_METHOD_ID(getSupportedDeviceProperties, clazz, "()[I");
    GET_METHOD_ID(setObjectProperty, clazz, "(IIJLjava/lang/String;)I");
    GET_METHOD_ID(getDeviceProperty, clazz, "(I[J[C)I");
    GET_METHOD_ID(setDeviceProperty, clazz, "(IJLjava/lang/String;)I");
    GET_METHOD_ID(getObjectPropertyList, clazz, "(IIIII)Landroid/mtp/MtpPropertyList;");
    GET_METHOD_ID(getObjectInfo, clazz, "(I[I[C[J)Z");
    GET_METHOD_ID(getObjectFilePath, clazz, "(I[C[J)I");
    GET_METHOD_ID(openFilePath, clazz, "(Ljava/lang/String;Z)I");
    GET_METHOD_ID(getThumbnailInfo, clazz, "(I[J)Z");
    GET_METHOD_ID(getThumbnailData, clazz, "(I)[B");
    GET_METHOD_ID(beginDeleteObject, clazz, "(I)I");
    GET_METHOD_ID(endDeleteObject, clazz, "(IZ)V");
    GET_METHOD_ID(beginMoveObject, clazz, "(III)I");
    GET_METHOD_ID(endMoveObject, clazz, "(IIIIIZ)V");
    GET_METHOD_ID(beginCopyObject, clazz, "(III)I");
    GET_METHOD_ID(endCopyObject, clazz, "(IZ)V");
    GET_METHOD_ID(getObjectReferences, clazz, "(I)[I");
    GET_METHOD_ID(setObjectReferences, clazz, "(I[I)I");

    field_context = env->GetFieldID(clazz, "mNativeContext", "J");
    if (field_context == NULL) {
        ALOGE("Can't find MtpDatabase.mNativeContext");
        return -1;
    }

    clazz = env->FindClass("android/mtp/MtpPropertyList");
    if (clazz == NULL) {
        ALOGE("Can't find android/mtp/MtpPropertyList");
        return -1;
    }
    GET_METHOD_ID(getCode, clazz, "()I");
    GET_METHOD_ID(getCount, clazz, "()I");
    GET_METHOD_ID(getObjectHandles, clazz, "()[I");
    GET_METHOD_ID(getPropertyCodes, clazz, "()[I");
    GET_METHOD_ID(getDataTypes, clazz, "()[I");
    GET_METHOD_ID(getLongValues, clazz, "()[J");
    GET_METHOD_ID(getStringValues, clazz, "()[Ljava/lang/String;");

    if (AndroidRuntime::registerNativeMethods(env,
                "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
        return -1;
+97 −249

File changed.

Preview size limit exceeded, changes collapsed.

+25 −45
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <fcntl.h>
#include <utils/threads.h>

#include "core_jni_helpers.h"
#include "jni.h"
#include <nativehelper/JNIPlatformHelp.h>
#include "android_runtime/AndroidRuntime.h"
@@ -34,6 +35,8 @@

using namespace android;

static Mutex sMutex;

// MtpServer fields
static jfieldID field_MtpServer_nativeContext;

@@ -44,7 +47,25 @@ static jfieldID field_MtpStorage_description;
static jfieldID field_MtpStorage_removable;
static jfieldID field_MtpStorage_maxFileSize;

static Mutex sMutex;
// Initializer for the jfieldIDs above. This method must be invoked before accessing MtpServer and
// MtpStorage fields.
static void initializeJavaIDs(JNIEnv* env) {
    static std::once_flag sJniInitialized;

    std::call_once(sJniInitialized, [](JNIEnv *env) {
        const jclass storage_clazz = FindClassOrDie(env, "android/mtp/MtpStorage");
        field_MtpStorage_storageId = GetFieldIDOrDie(env, storage_clazz, "mStorageId", "I");
        field_MtpStorage_path =
                GetFieldIDOrDie(env, storage_clazz, "mPath", "Ljava/lang/String;");
        field_MtpStorage_description =
                GetFieldIDOrDie(env, storage_clazz, "mDescription", "Ljava/lang/String;");
        field_MtpStorage_removable = GetFieldIDOrDie(env, storage_clazz, "mRemovable", "Z");
        field_MtpStorage_maxFileSize = GetFieldIDOrDie(env, storage_clazz, "mMaxFileSize", "J");

        const jclass server_clazz = FindClassOrDie(env, "android/mtp/MtpServer");
        field_MtpServer_nativeContext = GetFieldIDOrDie(env, server_clazz, "mNativeContext", "J");
    }, env);
}

// ----------------------------------------------------------------------------

@@ -52,6 +73,7 @@ static Mutex sMutex;
extern IMtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);

static inline MtpServer* getMtpServer(JNIEnv *env, jobject thiz) {
    initializeJavaIDs(env);
    return (MtpServer*)env->GetLongField(thiz, field_MtpServer_nativeContext);
}

@@ -60,6 +82,8 @@ android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, job
        jboolean usePtp, jstring deviceInfoManufacturer, jstring deviceInfoModel,
        jstring deviceInfoDeviceVersion, jstring deviceInfoSerialNumber)
{
    initializeJavaIDs(env);

    const char *deviceInfoManufacturerStr = env->GetStringUTFChars(deviceInfoManufacturer, NULL);
    const char *deviceInfoModelStr = env->GetStringUTFChars(deviceInfoModel, NULL);
    const char *deviceInfoDeviceVersionStr = env->GetStringUTFChars(deviceInfoDeviceVersion, NULL);
@@ -224,50 +248,6 @@ static const JNINativeMethod gMethods[] = {

int register_android_mtp_MtpServer(JNIEnv *env)
{
    jclass clazz;

    clazz = env->FindClass("android/mtp/MtpStorage");
    if (clazz == NULL) {
        ALOGE("Can't find android/mtp/MtpStorage");
        return -1;
    }
    field_MtpStorage_storageId = env->GetFieldID(clazz, "mStorageId", "I");
    if (field_MtpStorage_storageId == NULL) {
        ALOGE("Can't find MtpStorage.mStorageId");
        return -1;
    }
    field_MtpStorage_path = env->GetFieldID(clazz, "mPath", "Ljava/lang/String;");
    if (field_MtpStorage_path == NULL) {
        ALOGE("Can't find MtpStorage.mPath");
        return -1;
    }
    field_MtpStorage_description = env->GetFieldID(clazz, "mDescription", "Ljava/lang/String;");
    if (field_MtpStorage_description == NULL) {
        ALOGE("Can't find MtpStorage.mDescription");
        return -1;
    }
    field_MtpStorage_removable = env->GetFieldID(clazz, "mRemovable", "Z");
    if (field_MtpStorage_removable == NULL) {
        ALOGE("Can't find MtpStorage.mRemovable");
        return -1;
    }
    field_MtpStorage_maxFileSize = env->GetFieldID(clazz, "mMaxFileSize", "J");
    if (field_MtpStorage_maxFileSize == NULL) {
        ALOGE("Can't find MtpStorage.mMaxFileSize");
        return -1;
    }

    clazz = env->FindClass("android/mtp/MtpServer");
    if (clazz == NULL) {
        ALOGE("Can't find android/mtp/MtpServer");
        return -1;
    }
    field_MtpServer_nativeContext = env->GetFieldID(clazz, "mNativeContext", "J");
    if (field_MtpServer_nativeContext == NULL) {
        ALOGE("Can't find MtpServer.mNativeContext");
        return -1;
    }

    return AndroidRuntime::registerNativeMethods(env,
                "android/mtp/MtpServer", gMethods, NELEM(gMethods));
}