Bug 918372 - Allocate a single GlobalRef for the Android Context. r=blassey a=lsblakk
authorGian-Carlo Pascutto <gpascutto@mozilla.com>
Wed, 25 Sep 2013 08:06:21 +0200
changeset 155556 c8abbbef2a6785e10bbba79f0a9e36b7f49734da
parent 155555 af8bc8ef89c49c8dd30b7360d2271757e7f37e35
child 155557 bc7b5e1c60a2543f79e415fb6a77eb108a69b8ce
push id4327
push usergpascutto@mozilla.com
push dateMon, 30 Sep 2013 12:10:44 +0000
treeherdermozilla-aurora@891eaf3a213e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey, lsblakk
bugs918372
milestone26.0a2
Bug 918372 - Allocate a single GlobalRef for the Android Context. r=blassey a=lsblakk
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())