Merge change 9510

* changes:
  Untangle MediaPlayer, MediaRecorder, MediaScanner and MediaMetadataRetriever JNI code, so that creating one of those doesn't initialize all the others. Shaves a hundred milliseconds or so off music app startup time.
This commit is contained in:
Android (Google) Code Review
2009-08-03 11:34:25 -07:00
10 changed files with 167 additions and 135 deletions

View File

@@ -35,6 +35,7 @@ public class MediaMetadataRetriever
{
static {
System.loadLibrary("media_jni");
native_init();
}
// The field below is accessed by native methods
@@ -211,7 +212,8 @@ public class MediaMetadataRetriever
* allocated internally.
*/
public native void release();
private native void native_setup();
private native void native_setup();
private static native void native_init();
private native final void native_finalize();

View File

@@ -466,6 +466,7 @@ public class MediaPlayer
static {
System.loadLibrary("media_jni");
native_init();
}
private final static String TAG = "MediaPlayer";
@@ -1109,6 +1110,7 @@ public class MediaPlayer
*/
private native final int native_setMetadataFilter(Parcel request);
private static native final void native_init();
private native final void native_setup(Object mediaplayer_this);
private native final void native_finalize();

View File

@@ -57,6 +57,7 @@ public class MediaRecorder
{
static {
System.loadLibrary("media_jni");
native_init();
}
private final static String TAG = "MediaRecorder";
@@ -655,6 +656,8 @@ public class MediaRecorder
*/
public native void release();
private static native final void native_init();
private native final void native_setup(Object mediarecorder_this) throws IllegalStateException;
private native final void native_finalize();

View File

@@ -99,6 +99,7 @@ public class MediaScanner
{
static {
System.loadLibrary("media_jni");
native_init();
}
private final static String TAG = "MediaScanner";
@@ -1404,6 +1405,7 @@ public class MediaScanner
public native byte[] extractAlbumArt(FileDescriptor fd);
private static native final void native_init();
private native final void native_setup();
private native final void native_finalize();
@Override

View File

@@ -169,13 +169,6 @@ static JNINativeMethod gMethods[] = {
int register_android_media_AmrInputStream(JNIEnv *env)
{
const char* const kClassPathName = "android/media/AmrInputStream";
jclass clazz;
clazz = env->FindClass(kClassPathName);
if (clazz == NULL) {
LOGE("Can't find %s", kClassPathName);
return -1;
}
return AndroidRuntime::registerNativeMethods(env,
kClassPathName, gMethods, NELEM(gMethods));

View File

@@ -40,6 +40,7 @@ struct fields_t {
static fields_t fields;
static Mutex sLock;
static const char* const kClassPathName = "android/media/MediaMetadataRetriever";
static void process_media_retriever_call(JNIEnv *env, status_t opStatus, const char* exception, const char *message)
{
@@ -269,6 +270,36 @@ static void android_media_MediaMetadataRetriever_native_finalize(JNIEnv *env, jo
android_media_MediaMetadataRetriever_release(env, thiz);
}
// This function gets a field ID, which in turn causes class initialization.
// It is called from a static block in MediaMetadataRetriever, which won't run until the
// first time an instance of this class is used.
static void android_media_MediaMetadataRetriever_native_init(JNIEnv *env)
{
jclass clazz = env->FindClass(kClassPathName);
if (clazz == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaMetadataRetriever");
return;
}
fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
if (fields.context == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaMetadataRetriever.mNativeContext");
return;
}
fields.bitmapClazz = env->FindClass("android/graphics/Bitmap");
if (fields.bitmapClazz == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find android/graphics/Bitmap");
return;
}
fields.bitmapConstructor = env->GetMethodID(fields.bitmapClazz, "<init>", "(IZ[B)V");
if (fields.bitmapConstructor == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find Bitmap constructor");
return;
}
}
static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz)
{
LOGV("native_setup");
@@ -292,36 +323,13 @@ static JNINativeMethod nativeMethods[] = {
{"release", "()V", (void *)android_media_MediaMetadataRetriever_release},
{"native_finalize", "()V", (void *)android_media_MediaMetadataRetriever_native_finalize},
{"native_setup", "()V", (void *)android_media_MediaMetadataRetriever_native_setup},
{"native_init", "()V", (void *)android_media_MediaMetadataRetriever_native_init},
};
// Register native mehtods with Android runtime environment
// This function only registers the native methods, and is called from
// JNI_OnLoad in android_media_MediaPlayer.cpp
int register_android_media_MediaMetadataRetriever(JNIEnv *env)
{
static const char* const kClassPathName = "android/media/MediaMetadataRetriever";
jclass clazz = env->FindClass(kClassPathName);
if (clazz == NULL) {
LOGE("Can't find class: %s", kClassPathName);
return -1;
}
fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
if (fields.context == NULL) {
LOGE("Can't find MediaMetadataRetriever.mNativeContext");
return -1;
}
fields.bitmapClazz = env->FindClass("android/graphics/Bitmap");
if (fields.bitmapClazz == NULL) {
LOGE("Bitmap class is not found");
return -1;
}
fields.bitmapConstructor = env->GetMethodID(fields.bitmapClazz, "<init>", "(IZ[B)V");
if (fields.bitmapConstructor == NULL) {
LOGE("Bitmap constructor is not found");
return -1;
}
return AndroidRuntime::registerNativeMethods
(env, kClassPathName, nativeMethods, NELEM(nativeMethods));
(env, kClassPathName, nativeMethods, NELEM(nativeMethods));
}

View File

@@ -511,6 +511,51 @@ android_media_MediaPlayer_getMetadata(JNIEnv *env, jobject thiz, jboolean update
return media_player->getMetadata(update_only, apply_filter, metadata) == OK;
}
// This function gets some field IDs, which in turn causes class initialization.
// It is called from a static block in MediaPlayer, which won't run until the
// first time an instance of this class is used.
static void
android_media_MediaPlayer_native_init(JNIEnv *env)
{
jclass clazz;
clazz = env->FindClass("android/media/MediaPlayer");
if (clazz == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaPlayer");
return;
}
fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
if (fields.context == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaPlayer.mNativeContext");
return;
}
fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
if (fields.post_event == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaPlayer.postEventFromNative");
return;
}
fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;");
if (fields.surface == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaPlayer.mSurface");
return;
}
jclass surface = env->FindClass("android/view/Surface");
if (surface == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find android/view/Surface");
return;
}
fields.surface_native = env->GetFieldID(surface, "mSurface", "I");
if (fields.surface_native == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find Surface.mSurface");
return;
}
}
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
@@ -576,53 +621,16 @@ static JNINativeMethod gMethods[] = {
{"native_invoke", "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke},
{"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
{"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
{"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
};
static const char* const kClassPathName = "android/media/MediaPlayer";
// This function only registers the native methods
static int register_android_media_MediaPlayer(JNIEnv *env)
{
jclass clazz;
clazz = env->FindClass("android/media/MediaPlayer");
if (clazz == NULL) {
LOGE("Can't find android/media/MediaPlayer");
return -1;
}
fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
if (fields.context == NULL) {
LOGE("Can't find MediaPlayer.mNativeContext");
return -1;
}
fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
if (fields.post_event == NULL) {
LOGE("Can't find MediaPlayer.postEventFromNative");
return -1;
}
fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;");
if (fields.surface == NULL) {
LOGE("Can't find MediaPlayer.mSurface");
return -1;
}
jclass surface = env->FindClass("android/view/Surface");
if (surface == NULL) {
LOGE("Can't find android/view/Surface");
return -1;
}
fields.surface_native = env->GetFieldID(surface, "mSurface", "I");
if (fields.surface_native == NULL) {
LOGE("Can't find Surface fields");
return -1;
}
return AndroidRuntime::registerNativeMethods(env,
"android/media/MediaPlayer", gMethods, NELEM(gMethods));
}

View File

@@ -371,6 +371,53 @@ android_media_MediaRecorder_release(JNIEnv *env, jobject thiz)
}
}
// This function gets some field IDs, which in turn causes class initialization.
// It is called from a static block in MediaRecorder, which won't run until the
// first time an instance of this class is used.
static void
android_media_MediaRecorder_native_init(JNIEnv *env)
{
jclass clazz;
clazz = env->FindClass("android/media/MediaRecorder");
if (clazz == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaRecorder");
return;
}
fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
if (fields.context == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaRecorder.mNativeContext");
return;
}
fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;");
if (fields.surface == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaRecorder.mSurface");
return;
}
jclass surface = env->FindClass("android/view/Surface");
if (surface == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find android/view/Surface");
return;
}
fields.surface_native = env->GetFieldID(surface, "mSurface", "I");
if (fields.surface_native == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find Surface.mSurface");
return;
}
fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
if (fields.post_event == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "MediaRecorder.postEventFromNative");
return;
}
}
static void
android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
{
@@ -418,55 +465,19 @@ static JNINativeMethod gMethods[] = {
{"getMaxAmplitude", "()I", (void *)android_media_MediaRecorder_native_getMaxAmplitude},
{"start", "()V", (void *)android_media_MediaRecorder_start},
{"stop", "()V", (void *)android_media_MediaRecorder_stop},
{"native_reset", "()V", (void *)android_media_MediaRecorder_native_reset},
{"native_reset", "()V", (void *)android_media_MediaRecorder_native_reset},
{"release", "()V", (void *)android_media_MediaRecorder_release},
{"native_init", "()V", (void *)android_media_MediaRecorder_native_init},
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaRecorder_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize},
};
static const char* const kClassPathName = "android/media/MediaRecorder";
// This function only registers the native methods, and is called from
// JNI_OnLoad in android_media_MediaPlayer.cpp
int register_android_media_MediaRecorder(JNIEnv *env)
{
jclass clazz;
clazz = env->FindClass("android/media/MediaRecorder");
if (clazz == NULL) {
LOGE("Can't find android/media/MediaRecorder");
return -1;
}
fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
if (fields.context == NULL) {
LOGE("Can't find MediaRecorder.mNativeContext");
return -1;
}
fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;");
if (fields.surface == NULL) {
LOGE("Can't find MediaRecorder.mSurface");
return -1;
}
jclass surface = env->FindClass("android/view/Surface");
if (surface == NULL) {
LOGE("Can't find android/view/Surface");
return -1;
}
fields.surface_native = env->GetFieldID(surface, "mSurface", "I");
if (fields.surface_native == NULL) {
LOGE("Can't find Surface fields");
return -1;
}
fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
if (fields.post_event == NULL) {
LOGE("Can't find MediaRecorder.postEventFromNative");
return -1;
}
return AndroidRuntime::registerNativeMethods(env,
"android/media/MediaRecorder", gMethods, NELEM(gMethods));
}

View File

@@ -241,6 +241,27 @@ done:
return array;
}
// This function gets a field ID, which in turn causes class initialization.
// It is called from a static block in MediaScanner, which won't run until the
// first time an instance of this class is used.
static void
android_media_MediaScanner_native_init(JNIEnv *env)
{
jclass clazz;
clazz = env->FindClass("android/media/MediaScanner");
if (clazz == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaScanner");
return;
}
fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
if (fields.context == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaScanner.mNativeContext");
return;
}
}
static void
android_media_MediaScanner_native_setup(JNIEnv *env, jobject thiz)
{
@@ -275,28 +296,17 @@ static JNINativeMethod gMethods[] = {
(void *)android_media_MediaScanner_processFile},
{"setLocale", "(Ljava/lang/String;)V", (void *)android_media_MediaScanner_setLocale},
{"extractAlbumArt", "(Ljava/io/FileDescriptor;)[B", (void *)android_media_MediaScanner_extractAlbumArt},
{"native_init", "()V", (void *)android_media_MediaScanner_native_init},
{"native_setup", "()V", (void *)android_media_MediaScanner_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaScanner_native_finalize},
};
static const char* const kClassPathName = "android/media/MediaScanner";
// This function only registers the native methods, and is called from
// JNI_OnLoad in android_media_MediaPlayer.cpp
int register_android_media_MediaScanner(JNIEnv *env)
{
jclass clazz;
clazz = env->FindClass("android/media/MediaScanner");
if (clazz == NULL) {
LOGE("Can't find android/media/MediaScanner");
return -1;
}
fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
if (fields.context == NULL) {
LOGE("Can't find MediaScanner.mNativeContext");
return -1;
}
return AndroidRuntime::registerNativeMethods(env,
"android/media/MediaScanner", gMethods, NELEM(gMethods));
}

View File

@@ -128,13 +128,6 @@ static JNINativeMethod gMethods[] = {
int register_android_media_ResampleInputStream(JNIEnv *env)
{
const char* const kClassPathName = "android/media/ResampleInputStream";
jclass clazz;
clazz = env->FindClass(kClassPathName);
if (clazz == NULL) {
LOGE("Can't find %s", kClassPathName);
return -1;
}
return AndroidRuntime::registerNativeMethods(env,
kClassPathName, gMethods, NELEM(gMethods));