Bug 713687 - Part 4 - Network API Android backend: use enable/disable notifications to prevent listening when not needed. r=dougt
authorMounir Lamouri <mounir.lamouri@gmail.com>
Mon, 16 Jan 2012 15:01:07 +0100
changeset 84746 9f68bafdd6852e727f4af1a303ca20a9bab0466a
parent 84745 9ee757bbbcd0031fe56d1cf394e0e7d9bff9bcee
child 84747 7087bb2ced148327594d06b2bd89a6994db8c086
push id21873
push usermlamouri@mozilla.com
push dateWed, 18 Jan 2012 10:29:07 +0000
treeherdermozilla-central@7538f4d4697c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdougt
bugs713687
milestone12.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 713687 - Part 4 - Network API Android backend: use enable/disable notifications to prevent listening when not needed. r=dougt
embedding/android/GeckoAppShell.java
embedding/android/GeckoNetworkManager.java
hal/android/AndroidHal.cpp
mobile/android/base/GeckoAppShell.java
mobile/android/base/GeckoNetworkManager.java
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -1775,9 +1775,17 @@ public class GeckoAppShell
             }
         }
         return false;
     }
 
     public static double[] getCurrentNetworkInformation() {
         return GeckoNetworkManager.getInstance().getCurrentInformation();
     }
+
+    public static void enableNetworkNotifications() {
+        GeckoNetworkManager.getInstance().enableNotifications();
+    }
+
+    public static void disableNetworkNotifications() {
+        GeckoNetworkManager.getInstance().disableNotifications();
+    }
 }
--- a/embedding/android/GeckoNetworkManager.java
+++ b/embedding/android/GeckoNetworkManager.java
@@ -127,16 +127,21 @@ public class GeckoNetworkManager
     NETWORK_3_5_G,  // 3.5G
     NETWORK_3_75_G, // 3.75G
     NETWORK_3_9_G,  // 3.9G
     NETWORK_UNKNOWN
   }
 
   private NetworkType  mNetworkType = NetworkType.NETWORK_NONE;
   private IntentFilter mNetworkFilter = new IntentFilter();
+  // Whether the manager should be listening to Network Information changes.
+  private boolean mShouldBeListening = false;
+  // Whether the manager should notify Gecko that a change in Network
+  // Information happened.
+  private boolean mShouldNotify      = false;
 
   public static GeckoNetworkManager getInstance() {
     return sInstance;
   }
 
   @Override
   public void onReceive(Context aContext, Intent aIntent) {
     updateNetworkType();
@@ -144,42 +149,76 @@ public class GeckoNetworkManager
 
   public void init() {
     mNetworkFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
 
     mNetworkType = getNetworkType();
   }
 
   public void start() {
+    mShouldBeListening = true;
     updateNetworkType();
 
+    if (mShouldNotify) {
+      startListening();
+    }
+  }
+
+  private void startListening() {
     GeckoApp.mAppContext.registerReceiver(sInstance, mNetworkFilter);
   }
 
   public void stop() {
+    mShouldBeListening = false;
+
+    if (mShouldNotify) {
+      stopListening();
+    }
+  }
+
+  private void stopListening() {
     GeckoApp.mAppContext.unregisterReceiver(sInstance);
   }
 
   private void updateNetworkType() {
     NetworkType previousNetworkType = mNetworkType;
     mNetworkType = getNetworkType();
 
-    if (mNetworkType == previousNetworkType) {
+    if (mNetworkType == previousNetworkType || !mShouldNotify) {
       return;
     }
 
     GeckoAppShell.sendEventToGecko(new GeckoEvent(getNetworkSpeed(mNetworkType),
                                                   isNetworkUsuallyMetered(mNetworkType)));
   }
 
   public double[] getCurrentInformation() {
     return new double[] { getNetworkSpeed(mNetworkType),
                           isNetworkUsuallyMetered(mNetworkType) ? 1.0 : 0.0 };
   }
 
+  public void enableNotifications() {
+    // We set mShouldNotify *after* calling updateNetworkType() to make sure we
+    // don't notify an eventual change in mNetworkType.
+    updateNetworkType();
+    mShouldNotify = true;
+
+    if (mShouldBeListening) {
+      startListening();
+    }
+  }
+
+  public void disableNotifications() {
+    mShouldNotify = false;
+
+    if (mShouldBeListening) {
+      stopListening();
+    }
+  }
+
   private static NetworkType getNetworkType() {
     ConnectivityManager cm =
       (ConnectivityManager)GeckoApp.mAppContext.getSystemService(Context.CONNECTIVITY_SERVICE);
 
     if (cm.getActiveNetworkInfo() == null) {
       return NetworkType.NETWORK_NONE;
     }
 
--- a/hal/android/AndroidHal.cpp
+++ b/hal/android/AndroidHal.cpp
@@ -137,21 +137,35 @@ GetScreenBrightness()
 }
 
 void
 SetScreenBrightness(double brightness)
 {}
 
 void
 EnableNetworkNotifications()
-{}
+{
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return;
+  }
+
+  bridge->EnableNetworkNotifications();
+}
 
 void
 DisableNetworkNotifications()
-{}
+{
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return;
+  }
+
+  bridge->DisableNetworkNotifications();
+}
 
 void
 GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo)
 {
   AndroidBridge* bridge = AndroidBridge::Bridge();
   if (!bridge) {
     return;
   }
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -1746,9 +1746,17 @@ public class GeckoAppShell
         if (mInputConnection != null && mInputConnection.isIMEEnabled()) {
             sendEventToGecko(new GeckoEvent("ScrollTo:FocusedInput", ""));
         }
     }
 
     public static double[] getCurrentNetworkInformation() {
         return GeckoNetworkManager.getInstance().getCurrentInformation();
     }
+
+    public static void enableNetworkNotifications() {
+        GeckoNetworkManager.getInstance().enableNotifications();
+    }
+
+    public static void disableNetworkNotifications() {
+        GeckoNetworkManager.getInstance().disableNotifications();
+    }
 }
--- a/mobile/android/base/GeckoNetworkManager.java
+++ b/mobile/android/base/GeckoNetworkManager.java
@@ -127,16 +127,21 @@ public class GeckoNetworkManager
     NETWORK_3_5_G,  // 3.5G
     NETWORK_3_75_G, // 3.75G
     NETWORK_3_9_G,  // 3.9G
     NETWORK_UNKNOWN
   }
 
   private NetworkType  mNetworkType = NetworkType.NETWORK_NONE;
   private IntentFilter mNetworkFilter = new IntentFilter();
+  // Whether the manager should be listening to Network Information changes.
+  private boolean mShouldBeListening = false;
+  // Whether the manager should notify Gecko that a change in Network
+  // Information happened.
+  private boolean mShouldNotify      = false;
 
   public static GeckoNetworkManager getInstance() {
     return sInstance;
   }
 
   @Override
   public void onReceive(Context aContext, Intent aIntent) {
     updateNetworkType();
@@ -144,42 +149,76 @@ public class GeckoNetworkManager
 
   public void init() {
     mNetworkFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
 
     mNetworkType = getNetworkType();
   }
 
   public void start() {
+    mShouldBeListening = true;
     updateNetworkType();
 
+    if (mShouldNotify) {
+      startListening();
+    }
+  }
+
+  private void startListening() {
     GeckoApp.mAppContext.registerReceiver(sInstance, mNetworkFilter);
   }
 
   public void stop() {
+    mShouldBeListening = false;
+
+    if (mShouldNotify) {
+      stopListening();
+    }
+  }
+
+  private void stopListening() {
     GeckoApp.mAppContext.unregisterReceiver(sInstance);
   }
 
   private void updateNetworkType() {
     NetworkType previousNetworkType = mNetworkType;
     mNetworkType = getNetworkType();
 
-    if (mNetworkType == previousNetworkType) {
+    if (mNetworkType == previousNetworkType || !mShouldNotify) {
       return;
     }
 
     GeckoAppShell.sendEventToGecko(new GeckoEvent(getNetworkSpeed(mNetworkType),
                                                   isNetworkUsuallyMetered(mNetworkType)));
   }
 
   public double[] getCurrentInformation() {
     return new double[] { getNetworkSpeed(mNetworkType),
                           isNetworkUsuallyMetered(mNetworkType) ? 1.0 : 0.0 };
   }
 
+  public void enableNotifications() {
+    // We set mShouldNotify *after* calling updateNetworkType() to make sure we
+    // don't notify an eventual change in mNetworkType.
+    updateNetworkType();
+    mShouldNotify = true;
+
+    if (mShouldBeListening) {
+      startListening();
+    }
+  }
+
+  public void disableNotifications() {
+    mShouldNotify = false;
+
+    if (mShouldBeListening) {
+      stopListening();
+    }
+  }
+
   private static NetworkType getNetworkType() {
     ConnectivityManager cm =
       (ConnectivityManager)GeckoApp.mAppContext.getSystemService(Context.CONNECTIVITY_SERVICE);
 
     if (cm.getActiveNetworkInfo() == null) {
       return NetworkType.NETWORK_NONE;
     }
 
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -172,16 +172,18 @@ AndroidBridge::Init(JNIEnv *jEnv,
     jSaveSentMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "saveSentMessage", "(Ljava/lang/String;Ljava/lang/String;J)I");
     jGetMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getMessage", "(IIJ)V");
     jDeleteMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "deleteMessage", "(IIJ)V");
     jCreateMessageList = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "createMessageList", "(JJ[Ljava/lang/String;IIZIJ)V");
     jGetNextMessageinList = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getNextMessageInList", "(IIJ)V");
     jClearMessageList = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "clearMessageList", "(I)V");
 
     jGetCurrentNetworkInformation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getCurrentNetworkInformation", "()[D");
+    jEnableNetworkNotifications = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableNetworkNotifications", "()V");
+    jDisableNetworkNotifications = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "disableNetworkNotifications", "()V");
 
     jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
     jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10"));
     jEGLSurfaceImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLSurfaceImpl"));
     jEGLContextImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLContextImpl"));
     jEGLConfigImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLConfigImpl"));
     jEGLDisplayImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLDisplayImpl"));
 
@@ -1449,16 +1451,30 @@ AndroidBridge::GetCurrentNetworkInformat
     jdouble* info = mJNIEnv->GetDoubleArrayElements(arr, 0);
 
     aNetworkInfo->bandwidth() = info[0];
     aNetworkInfo->canBeMetered() = info[1] == 1.0f;
 
     mJNIEnv->ReleaseDoubleArrayElements(arr, info, 0);
 }
 
+void
+AndroidBridge::EnableNetworkNotifications()
+{
+    ALOG_BRIDGE("AndroidBridge::EnableNetworkNotifications");
+    mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jEnableNetworkNotifications);
+}
+
+void
+AndroidBridge::DisableNetworkNotifications()
+{
+    ALOG_BRIDGE("AndroidBridge::DisableNetworkNotifications");
+    mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jDisableNetworkNotifications);
+}
+
 void *
 AndroidBridge::LockBitmap(jobject bitmap)
 {
     int err;
     void *buf;
 
     if ((err = AndroidBitmap_lockPixels(JNI(), bitmap, &buf)) != 0) {
         ALOG_BRIDGE("AndroidBitmap_lockPixels failed! (error %d)", err);
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -348,16 +348,18 @@ public:
     void DeleteMessage(PRInt32 aMessageId, PRInt32 aRequestId, PRUint64 aProcessId);
     void CreateMessageList(const dom::sms::SmsFilterData& aFilter, bool aReverse, PRInt32 aRequestId, PRUint64 aProcessId);
     void GetNextMessageInList(PRInt32 aListId, PRInt32 aRequestId, PRUint64 aProcessId);
     void ClearMessageList(PRInt32 aListId);
 
     bool IsTablet();
 
     void GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo);
+    void EnableNetworkNotifications();
+    void DisableNetworkNotifications();
 
 protected:
     static AndroidBridge *sBridge;
 
     // the global JavaVM
     JavaVM *mJavaVM;
 
     // the JNIEnv for the main thread
@@ -444,16 +446,18 @@ protected:
     jmethodID jSaveSentMessage;
     jmethodID jGetMessage;
     jmethodID jDeleteMessage;
     jmethodID jCreateMessageList;
     jmethodID jGetNextMessageinList;
     jmethodID jClearMessageList;
 
     jmethodID jGetCurrentNetworkInformation;
+    jmethodID jEnableNetworkNotifications;
+    jmethodID jDisableNetworkNotifications;
 
     // stuff we need for CallEglCreateWindowSurface
     jclass jEGLSurfaceImplClass;
     jclass jEGLContextImplClass;
     jclass jEGLConfigImplClass;
     jclass jEGLDisplayImplClass;
     jclass jEGLContextClass;
     jclass jEGL10Class;