Bug 918372 - Allocate a single GlobalRef for the Android Context. r=blassey
authorGian-Carlo Pascutto <gpascutto@mozilla.com>
Wed, 25 Sep 2013 08:06:21 +0200
changeset 148637 f1184809ec393e37aa896365d12f5e4967bf1980
parent 148636 cd7c48f51a2e9b05bf00500138ecf26ac14d3947
child 148638 ca438424df3a272ec3acca0b46f2927c06b3fe8d
push id25349
push userryanvm@gmail.com
push dateWed, 25 Sep 2013 18:52:12 +0000
treeherdermozilla-central@39f30376058c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey
bugs918372
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 918372 - Allocate a single GlobalRef for the Android Context. r=blassey
content/media/webrtc/MediaEngineWebRTC.cpp
media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
widget/android/AndroidBridge.cpp
--- a/content/media/webrtc/MediaEngineWebRTC.cpp
+++ b/content/media/webrtc/MediaEngineWebRTC.cpp
@@ -89,25 +89,20 @@ MediaEngineWebRTC::EnumerateVideoDevices
   MutexAutoLock lock(mMutex);
 
 #ifdef MOZ_WIDGET_ANDROID
   jobject context = mozilla::AndroidBridge::Bridge()->GetGlobalContextRef();
 
   // get the JVM
   JavaVM *jvm = mozilla::AndroidBridge::Bridge()->GetVM();
 
-  JNIEnv *env;
-  jint res = jvm->AttachCurrentThread(&env, NULL);
-
   if (webrtc::VideoEngine::SetAndroidObjects(jvm, (void*)context) != 0) {
     LOG(("VieCapture:SetAndroidObjects Failed"));
     return;
   }
-
-  env->DeleteGlobalRef(context);
 #endif
 
   if (!mVideoEngine) {
     if (!(mVideoEngine = webrtc::VideoEngine::Create())) {
       return;
     }
   }
 
--- a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
@@ -140,29 +140,20 @@ MediaConduitErrorCode WebrtcAudioConduit
     mVoiceEngine = other->mVoiceEngine;
   } else {
 #ifdef MOZ_WIDGET_ANDROID
       jobject context = jsjni_GetGlobalContextRef();
 
       // get the JVM
       JavaVM *jvm = jsjni_GetVM();
 
-      JNIEnv* env;
-      if (jvm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
-        CSFLogError(logTag,  "%s: could not get Java environment", __FUNCTION__);
-        return kMediaConduitSessionNotInited;
-      }
-      jvm->AttachCurrentThread(&env, NULL);
-
       if (webrtc::VoiceEngine::SetAndroidObjects(jvm, (void*)context) != 0) {
         CSFLogError(logTag, "%s Unable to set Android objects", __FUNCTION__);
         return kMediaConduitSessionNotInited;
       }
-
-      env->DeleteGlobalRef(context);
 #endif
 
     //Per WebRTC APIs below function calls return NULL on failure
     if(!(mVoiceEngine = webrtc::VoiceEngine::Create()))
     {
       CSFLogError(logTag, "%s Unable to create voice engine", __FUNCTION__);
       return kMediaConduitSessionNotInited;
     }
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -108,29 +108,20 @@ MediaConduitErrorCode WebrtcVideoConduit
   CSFLogDebug(logTag,  "%s ", __FUNCTION__);
 
 #ifdef MOZ_WIDGET_ANDROID
   jobject context = jsjni_GetGlobalContextRef();
 
   // get the JVM
   JavaVM *jvm = jsjni_GetVM();
 
-  JNIEnv* env;
-  if (jvm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
-      CSFLogError(logTag,  "%s: could not get Java environment", __FUNCTION__);
-      return kMediaConduitSessionNotInited;
-  }
-  jvm->AttachCurrentThread(&env, nullptr);
-
   if (webrtc::VideoEngine::SetAndroidObjects(jvm, (void*)context) != 0) {
     CSFLogError(logTag,  "%s: could not set Android objects", __FUNCTION__);
     return kMediaConduitSessionNotInited;
   }
-
-  env->DeleteGlobalRef(context);
 #endif
 
   if( !(mVideoEngine = webrtc::VideoEngine::Create()) )
   {
     CSFLogError(logTag, "%s Unable to create video engine ", __FUNCTION__);
      return kMediaConduitSessionNotInited;
   }
 
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -44,16 +44,17 @@
 #endif
 
 using namespace mozilla;
 
 NS_IMPL_ISUPPORTS0(nsFilePickerCallback)
 
 StaticRefPtr<AndroidBridge> AndroidBridge::sBridge;
 static unsigned sJavaEnvThreadIndex = 0;
+static jobject sGlobalContext = nullptr;
 static void JavaThreadDetachFunc(void *arg);
 
 // This is a dummy class that can be used in the template for android::sp
 class AndroidRefable {
     void incStrong(void* thing) { }
     void decStrong(void* thing) { }
 };
 
@@ -1429,28 +1430,50 @@ AndroidBridge::LockWindow(void *window, 
         *stride = info.s;
     } else return false;
 
     return true;
 }
 
 jobject
 AndroidBridge::GetGlobalContextRef() {
-    JNIEnv *env = GetJNIForThread();
-    if (!env)
-        return 0;
+    if (sGlobalContext == nullptr) {
+        JNIEnv *env = GetJNIForThread();
+        if (!env)
+            return 0;
 
-    AutoLocalJNIFrame jniFrame(env, 2);
+        AutoLocalJNIFrame jniFrame(env, 4);
 
-    jobject context = GetContext();
+        jobject context = GetContext();
+        if (!context) {
+            ALOG_BRIDGE("%s: Could not GetContext()", __FUNCTION__);
+            return 0;
+        }
+        jclass contextClass = env->FindClass("android/content/Context");
+        if (!contextClass) {
+            ALOG_BRIDGE("%s: Could not find Context class.", __FUNCTION__);
+            return 0;
+        }
+        jmethodID mid = env->GetMethodID(contextClass, "getApplicationContext",
+                                         "()Landroid/content/Context;");
+        if (!mid) {
+            ALOG_BRIDGE("%s: Could not find getApplicationContext.", __FUNCTION__);
+            return 0;
+        }
+        jobject appContext = env->CallObjectMethod(context, mid);
+        if (!appContext) {
+            ALOG_BRIDGE("%s: getApplicationContext failed.", __FUNCTION__);
+            return 0;
+        }
 
-    jobject globalRef = env->NewGlobalRef(context);
-    MOZ_ASSERT(globalRef);
+        sGlobalContext = env->NewGlobalRef(appContext);
+        MOZ_ASSERT(sGlobalContext);
+    }
 
-    return globalRef;
+    return sGlobalContext;
 }
 
 bool
 AndroidBridge::UnlockWindow(void* window)
 {
     int err;
 
     if (!HasNativeWindowAccess())