Bug 1286662 - Add native methods for GeckoNetworkManager notifications; r=snorp
authorJim Chen <nchen@mozilla.com>
Wed, 20 Jul 2016 21:44:48 -0400
changeset 305982 7cca4a08498e54c471a69850dd24c833d5cbd9df
parent 305981 d65d3fd104a86998febc5f4498ed9353baec1765
child 305983 73754b53ea3bad45d7f2714292304c3ad6325e39
push id30474
push usercbook@mozilla.com
push dateThu, 21 Jul 2016 14:25:10 +0000
treeherdermozilla-central@6b180266ac16 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1286662
milestone50.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 1286662 - Add native methods for GeckoNetworkManager notifications; r=snorp Add and use onConnectionChanged and onStatusChanged native methods in GeckoNetworkManager in place of the network events in GeckoEvent.
mobile/android/base/java/org/mozilla/gecko/GeckoNetworkManager.java
widget/android/GeckoNetworkManager.h
widget/android/nsAppShell.cpp
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoNetworkManager.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoNetworkManager.java
@@ -1,16 +1,17 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.annotation.JNITarget;
+import org.mozilla.gecko.annotation.WrapForJNI;
 import org.mozilla.gecko.util.NativeEventListener;
 import org.mozilla.gecko.util.NativeJSObject;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.NetworkUtils;
 import org.mozilla.gecko.util.NetworkUtils.ConnectionSubType;
 import org.mozilla.gecko.util.NetworkUtils.ConnectionType;
 import org.mozilla.gecko.util.NetworkUtils.NetworkStatus;
 
@@ -67,18 +68,21 @@ public class GeckoNetworkManager extends
         stop,
         enableNotifications,
         disableNotifications,
         receivedUpdate
     }
 
     private ManagerState currentState = ManagerState.OffNoListeners;
     private ConnectionType currentConnectionType = ConnectionType.NONE;
+    private ConnectionType previousConnectionType = ConnectionType.NONE;
+    private ConnectionSubType currentConnectionSubtype = ConnectionSubType.UNKNOWN;
+    private ConnectionSubType previousConnectionSubtype = ConnectionSubType.UNKNOWN;
     private NetworkStatus currentNetworkStatus = NetworkStatus.UNKNOWN;
-    private ConnectionSubType currentConnectionSubtype = ConnectionSubType.UNKNOWN;
+    private NetworkStatus previousNetworkStatus = NetworkStatus.UNKNOWN;
 
     private enum InfoType {
         MCC,
         MNC
     }
 
     private GeckoNetworkManager() {
         EventDispatcher.getInstance().registerGeckoThreadListener(this,
@@ -278,37 +282,62 @@ public class GeckoNetworkManager extends
             Log.e(LOGTAG, "ConnectivityManager does not exist.");
         }
         currentConnectionType = NetworkUtils.getConnectionType(connectivityManager);
         currentNetworkStatus = NetworkUtils.getNetworkStatus(connectivityManager);
         currentConnectionSubtype = NetworkUtils.getConnectionSubType(connectivityManager);
         Log.d(LOGTAG, "New network state: " + currentNetworkStatus + ", " + currentConnectionType + ", " + currentConnectionSubtype);
     }
 
+    @WrapForJNI
+    private static native void onConnectionChanged(int type, String subType,
+                                                   boolean isWifi, int DHCPGateway);
+
+    @WrapForJNI
+    private static native void onStatusChanged(String status);
+
     /**
      * Send current network state and connection type as a GeckoEvent, to whomever is listening.
      */
     private void sendNetworkStateToListeners() {
-        final Context applicationContext = GeckoAppShell.getApplicationContext();
-        final GeckoEvent networkEvent = GeckoEvent.createNetworkEvent(
-                currentConnectionType.value,
-                currentConnectionType == ConnectionType.WIFI,
-                wifiDhcpGatewayAddress(applicationContext),
-                currentConnectionSubtype.value
-        );
-        final GeckoEvent networkLinkChangeValueEvent = GeckoEvent.createNetworkLinkChangeEvent(
-                currentNetworkStatus.value
-        );
-        final GeckoEvent networkLinkChangeNotificationEvent = GeckoEvent.createNetworkLinkChangeEvent(
-                LINK_DATA_CHANGED
-        );
+        if (currentConnectionType != previousConnectionType ||
+                currentConnectionSubtype != previousConnectionSubtype) {
+            previousConnectionType = currentConnectionType;
+            previousConnectionSubtype = currentConnectionSubtype;
+
+            final boolean isWifi = currentConnectionType == ConnectionType.WIFI;
+            final int gateway = !isWifi ? 0 :
+                    wifiDhcpGatewayAddress(GeckoAppShell.getApplicationContext());
 
-        GeckoAppShell.sendEventToGecko(networkEvent);
-        GeckoAppShell.sendEventToGecko(networkLinkChangeValueEvent);
-        GeckoAppShell.sendEventToGecko(networkLinkChangeNotificationEvent);
+            if (GeckoThread.isRunning()) {
+                onConnectionChanged(currentConnectionType.value,
+                                    currentConnectionSubtype.value, isWifi, gateway);
+            } else {
+                GeckoThread.queueNativeCall(GeckoNetworkManager.class, "onConnectionChanged",
+                                            currentConnectionType.value,
+                                            String.class, currentConnectionSubtype.value,
+                                            isWifi, gateway);
+            }
+        }
+
+        final String status;
+
+        if (currentNetworkStatus != previousNetworkStatus) {
+            previousNetworkStatus = currentNetworkStatus;
+            status = currentNetworkStatus.value;
+        } else {
+            status = LINK_DATA_CHANGED;
+        }
+
+        if (GeckoThread.isRunning()) {
+            onStatusChanged(status);
+        } else {
+            GeckoThread.queueNativeCall(GeckoNetworkManager.class, "onStatusChanged",
+                                        String.class, status);
+        }
     }
 
     /**
      * Stop listening for network state updates.
      */
     private void unregisterBroadcastReceiver() {
         GeckoAppShell.getApplicationContext().unregisterReceiver(this);
     }
new file mode 100644
--- /dev/null
+++ b/widget/android/GeckoNetworkManager.h
@@ -0,0 +1,54 @@
+/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GeckoNetworkManager_h
+#define GeckoNetworkManager_h
+
+#include "GeneratedJNINatives.h"
+#include "nsAppShell.h"
+#include "nsCOMPtr.h"
+#include "nsINetworkLinkService.h"
+
+#include "mozilla/Services.h"
+
+namespace mozilla {
+
+class GeckoNetworkManager final
+    : public widget::GeckoNetworkManager::Natives<GeckoNetworkManager>
+    , public UsesGeckoThreadProxy
+{
+    GeckoNetworkManager() = delete;
+
+public:
+    static void
+    OnConnectionChanged(int32_t aType, jni::String::Param aSubType,
+                        bool aIsWifi, int32_t aGateway)
+    {
+        hal::NotifyNetworkChange(hal::NetworkInformation(
+                aType, aIsWifi, aGateway));
+
+        nsCOMPtr<nsIObserverService> os = services::GetObserverService();
+        if (os) {
+            os->NotifyObservers(nullptr,
+                                NS_NETWORK_LINK_TYPE_TOPIC,
+                                aSubType->ToString().get());
+        }
+    }
+
+    static void
+    OnStatusChanged(jni::String::Param aStatus)
+    {
+        nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+        if (os) {
+            os->NotifyObservers(nullptr,
+                                NS_NETWORK_LINK_TOPIC,
+                                aStatus->ToString().get());
+        }
+    }
+};
+
+} // namespace mozilla
+
+#endif // GeckoNetworkManager_h
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -56,16 +56,17 @@
 #include "IHistory.h"
 #endif
 
 #ifdef MOZ_LOGGING
 #include "mozilla/Logging.h"
 #endif
 
 #include "ANRReporter.h"
+#include "GeckoNetworkManager.h"
 #include "PrefsHelper.h"
 
 #ifdef DEBUG_ANDROID_EVENTS
 #define EVLOG(args...)  ALOG(args)
 #else
 #define EVLOG(args...) do { } while (0)
 #endif
 
@@ -380,16 +381,17 @@ nsAppShell::nsAppShell()
     }
 
     if (jni::IsAvailable()) {
         // Initialize JNI and Set the corresponding state in GeckoThread.
         AndroidBridge::ConstructBridge();
         GeckoAppShellSupport::Init();
         GeckoThreadSupport::Init();
         mozilla::ANRReporter::Init();
+        mozilla::GeckoNetworkManager::Init();
         mozilla::PrefsHelper::Init();
         nsWindow::InitNatives();
 
         widget::GeckoThread::SetState(widget::GeckoThread::State::JNI_READY());
     }
 
     sPowerManagerService = do_GetService(POWERMANAGERSERVICE_CONTRACTID);