Bug 1250387 - Kill GckoConnectivityReceiver.java and improve GeckoNetworkManager.java r=grisha
authorShatur<tushar.saini1285@gmail.com>
Tue, 19 Apr 2016 06:31:17 +0530
changeset 293785 f2187390d83f57f18c70c643a36dc80ebfe08631
parent 293784 2a71ec431c13459a79d7c4ab222c8ef2cdacb9be
child 293786 9a55bb9bae73342d88a57ba0720a3711992db273
push id18810
push usercbook@mozilla.com
push dateWed, 20 Apr 2016 04:03:08 +0000
treeherderfx-team@f2187390d83f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgrisha
bugs1250387
milestone48.0a1
Bug 1250387 - Kill GckoConnectivityReceiver.java and improve GeckoNetworkManager.java r=grisha
mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
mobile/android/base/java/org/mozilla/gecko/GeckoConnectivityReceiver.java
mobile/android/base/java/org/mozilla/gecko/GeckoEvent.java
mobile/android/base/java/org/mozilla/gecko/GeckoNetworkManager.java
mobile/android/base/moz.build
widget/android/nsAppShell.cpp
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
@@ -117,29 +117,27 @@ public class GeckoApplication extends Ap
             final BrowserDB db = GeckoProfile.get(this).getDB();
             ThreadUtils.postToBackgroundThread(new Runnable() {
                 @Override
                 public void run() {
                     db.expireHistory(getContentResolver(), BrowserContract.ExpirePriority.NORMAL);
                 }
             });
         }
-        GeckoConnectivityReceiver.getInstance().stop();
         GeckoNetworkManager.getInstance().stop();
     }
 
     public void onActivityResume(GeckoActivityStatus activity) {
         if (mPausedGecko) {
             GeckoThread.onResume();
             mPausedGecko = false;
         }
 
         final Context applicationContext = getApplicationContext();
         GeckoBatteryManager.getInstance().start(applicationContext);
-        GeckoConnectivityReceiver.getInstance().start(applicationContext);
         GeckoNetworkManager.getInstance().start(applicationContext);
 
         mInBackground = false;
     }
 
     @Override
     public void onCreate() {
         Log.i(LOG_TAG, "zerdatime " + SystemClock.uptimeMillis() + " - Fennec application start");
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoConnectivityReceiver.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- Mode: Java; 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/. */
-
-package org.mozilla.gecko;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.util.Log;
-
-public class GeckoConnectivityReceiver extends BroadcastReceiver {
-    /*
-     * Keep the below constants in sync with
-     * http://mxr.mozilla.org/mozilla-central/source/netwerk/base/nsINetworkLinkService.idl
-     */
-    private static final String LINK_DATA_UP = "up";
-    private static final String LINK_DATA_DOWN = "down";
-    private static final String LINK_DATA_CHANGED = "changed";
-    private static final String LINK_DATA_UNKNOWN = "unknown";
-
-    private static final String LOGTAG = "GeckoConnectivityReceiver";
-
-    private static final GeckoConnectivityReceiver sInstance = new GeckoConnectivityReceiver();
-
-    private final IntentFilter mFilter;
-    private Context mApplicationContext;
-    private boolean mIsEnabled;
-
-    public static GeckoConnectivityReceiver getInstance() {
-        return sInstance;
-    }
-
-    private GeckoConnectivityReceiver() {
-        mFilter = new IntentFilter();
-        mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
-    }
-
-    public synchronized void start(Context context) {
-        if (mIsEnabled) {
-            Log.w(LOGTAG, "Already started!");
-            return;
-        }
-
-        mApplicationContext = context.getApplicationContext();
-
-        // registerReceiver will return null if registering fails.
-        if (mApplicationContext.registerReceiver(this, mFilter) == null) {
-            Log.e(LOGTAG, "Registering receiver failed");
-        } else {
-            mIsEnabled = true;
-        }
-    }
-
-    public synchronized void stop() {
-        if (!mIsEnabled) {
-            Log.w(LOGTAG, "Already stopped!");
-            return;
-        }
-
-        mApplicationContext.unregisterReceiver(this);
-        mApplicationContext = null;
-        mIsEnabled = false;
-    }
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
-        NetworkInfo info = cm.getActiveNetworkInfo();
-
-        final String status;
-        if (info == null) {
-            status = LINK_DATA_UNKNOWN;
-        } else if (!info.isConnected()) {
-            status = LINK_DATA_DOWN;
-        } else {
-            status = LINK_DATA_UP;
-        }
-
-        if (GeckoThread.isRunning()) {
-            GeckoAppShell.sendEventToGecko(GeckoEvent.createNetworkLinkChangeEvent(status));
-            GeckoAppShell.sendEventToGecko(GeckoEvent.createNetworkLinkChangeEvent(LINK_DATA_CHANGED));
-        }
-    }
-}
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoEvent.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoEvent.java
@@ -480,21 +480,22 @@ public class GeckoEvent {
     }
 
     public static GeckoEvent createVisitedEvent(String data) {
         GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.VISITED);
         event.mCharacters = data;
         return event;
     }
 
-    public static GeckoEvent createNetworkEvent(int connectionType, boolean isWifi, int DHCPGateway) {
+    public static GeckoEvent createNetworkEvent(int connectionType, boolean isWifi, int DHCPGateway, String status) {
         GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.NETWORK_CHANGED);
         event.mConnectionType = connectionType;
         event.mIsWifi = isWifi;
         event.mDHCPGateway = DHCPGateway;
+        event.mCharacters = status;
         return event;
     }
 
     public static GeckoEvent createThumbnailEvent(int tabId, int bufw, int bufh, ByteBuffer buffer) {
         GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.THUMBNAIL);
         event.mPoints = new Point[1];
         event.mPoints[0] = new Point(bufw, bufh);
         event.mMetaState = tabId;
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoNetworkManager.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoNetworkManager.java
@@ -32,16 +32,32 @@ import android.util.Log;
  * exact network type, especially the cellular network type.
  *
  * Current connection is firstly obtained from Android's ConnectivityManager,
  * which is represented by the constant, and then will be mapped into the
  * connection type defined in Network Information API version 3.
  */
 
 public class GeckoNetworkManager extends BroadcastReceiver implements NativeEventListener {
+    /*
+     * Keep the below constants in sync with
+     * http://mxr.mozilla.org/mozilla-central/source/netwerk/base/nsINetworkLinkService.idl
+     */
+    private static final String LINK_DATA_UP = "up";
+    private static final String LINK_DATA_DOWN = "down";
+    private static final String LINK_DATA_CHANGED = "changed";
+    private static final String LINK_DATA_UNKNOWN = "unknown";
+
+    private static final String LINK_TYPE_UNKONWN = "unknown";
+    private static final String LINK_TYPE_ETHERNET = "ethernet";
+    private static final String LINK_TYPE_WIFI = "wifi";
+    private static final String LINK_TYPE_WIMAX = "wimax";
+    private static final String LINK_TYPE_2G = "2g";
+    private static final String LINK_TYPE_3G = "3g";
+    private static final String LINK_TYPE_4G = "4g";
     private static final String LOGTAG = "GeckoNetworkManager";
 
     private static GeckoNetworkManager sInstance;
 
     public static void destroy() {
         if (sInstance != null) {
             sInstance.onDestroy();
             sInstance = null;
@@ -102,16 +118,17 @@ public class GeckoNetworkManager extends
         }
 
         return sInstance;
     }
 
     @Override
     public void onReceive(Context aContext, Intent aIntent) {
         updateConnectionType();
+        updateLinkStatus(aContext);
     }
 
     public void start(final Context context) {
         // Note that this initialization clause only runs once.
         mApplicationContext = context.getApplicationContext();
         if (mConnectionType == ConnectionType.NONE) {
             mConnectionType = getConnectionType();
         }
@@ -250,17 +267,37 @@ public class GeckoNetworkManager extends
 
         if (!mShouldNotify) {
             return;
         }
 
         GeckoAppShell.sendEventToGecko(GeckoEvent.createNetworkEvent(
                                        newConnectionType.value,
                                        newConnectionType == ConnectionType.WIFI,
-                                       wifiDhcpGatewayAddress()));
+                                       wifiDhcpGatewayAddress(),
+                                       getConnectionSubType()));
+    }
+
+    public void updateLinkStatus(Context context) {
+        ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkInfo info = cm.getActiveNetworkInfo();
+
+        final String status;
+        if (info == null) {
+            status = LINK_DATA_UNKNOWN;
+        } else if (!info.isConnected()) {
+            status = LINK_DATA_DOWN;
+        } else {
+            status = LINK_DATA_UP;
+        }
+
+        if (GeckoThread.isRunning()) {
+            GeckoAppShell.sendEventToGecko(GeckoEvent.createNetworkLinkChangeEvent(status));
+            GeckoAppShell.sendEventToGecko(GeckoEvent.createNetworkLinkChangeEvent(LINK_DATA_CHANGED));
+        }
     }
 
     public double[] getCurrentInformation() {
         final ConnectionType connectionType = mConnectionType;
         return new double[] { connectionType.value,
                               connectionType == ConnectionType.WIFI ? 1.0 : 0.0,
                               wifiDhcpGatewayAddress() };
     }
@@ -280,50 +317,103 @@ public class GeckoNetworkManager extends
     public void disableNotifications() {
         mShouldNotify = false;
 
         if (mShouldBeListening) {
             stopListening();
         }
     }
 
-    private ConnectionType getConnectionType() {
+    private NetworkInfo getConnectivityManager() {
         final Context appContext = mApplicationContext;
 
         if (null == appContext) {
-            return ConnectionType.NONE;
+          return null;
         }
 
         ConnectivityManager cm = (ConnectivityManager) appContext.getSystemService(Context.CONNECTIVITY_SERVICE);
         if (cm == null) {
-            Log.e(LOGTAG, "Connectivity service does not exist");
-            return ConnectionType.NONE;
+          Log.e(LOGTAG, "Connectivity service does not exist");
+          return null;
         }
 
         NetworkInfo ni = null;
         try {
             ni = cm.getActiveNetworkInfo();
-        } catch (SecurityException se) { /* if we don't have the permission, fall through to null check */ }
+        } catch (SecurityException se) {} // if we don't have the permission, fall through to null check
+
+        return ni;
+    }
+
+    private ConnectionType getConnectionType() {
+        NetworkInfo ni = getConnectivityManager();
+
         if (ni == null) {
             return ConnectionType.NONE;
         }
 
         switch (ni.getType()) {
-        case ConnectivityManager.TYPE_BLUETOOTH:
-            return ConnectionType.BLUETOOTH;
-        case ConnectivityManager.TYPE_ETHERNET:
-            return ConnectionType.ETHERNET;
-        case ConnectivityManager.TYPE_MOBILE:
-        case ConnectivityManager.TYPE_WIMAX:
-            return ConnectionType.CELLULAR;
-        case ConnectivityManager.TYPE_WIFI:
-            return ConnectionType.WIFI;
-        default:
-            Log.w(LOGTAG, "Ignoring the current network type.");
-            return ConnectionType.OTHER;
+            case ConnectivityManager.TYPE_BLUETOOTH:
+                return ConnectionType.BLUETOOTH;
+            case ConnectivityManager.TYPE_ETHERNET:
+                return ConnectionType.ETHERNET;
+            case ConnectivityManager.TYPE_MOBILE:
+            case ConnectivityManager.TYPE_WIMAX:
+                return ConnectionType.CELLULAR;
+            case ConnectivityManager.TYPE_WIFI:
+                return ConnectionType.WIFI;
+            default:
+                Log.w(LOGTAG, "Ignoring the current network type.");
+                return ConnectionType.OTHER;
+        }
+    }
+
+    private String getConnectionSubType() {
+        NetworkInfo ni = getConnectivityManager();
+
+        if (ni == null) {
+            return LINK_TYPE_UNKONWN;
+        }
+
+        switch (ni.getType()) {
+            case ConnectivityManager.TYPE_ETHERNET:
+                return LINK_TYPE_ETHERNET;
+            case ConnectivityManager.TYPE_MOBILE:
+                switch (ni.getSubtype()) {
+                    case TelephonyManager.NETWORK_TYPE_GPRS:
+                    case TelephonyManager.NETWORK_TYPE_EDGE:
+                    case TelephonyManager.NETWORK_TYPE_CDMA:
+                    case TelephonyManager.NETWORK_TYPE_1xRTT:
+                    case TelephonyManager.NETWORK_TYPE_IDEN:
+                        return LINK_TYPE_2G;
+                    case TelephonyManager.NETWORK_TYPE_UMTS:
+                    case TelephonyManager.NETWORK_TYPE_EVDO_0:
+                    case TelephonyManager.NETWORK_TYPE_EVDO_A:
+                    case TelephonyManager.NETWORK_TYPE_HSDPA:
+                    case TelephonyManager.NETWORK_TYPE_HSUPA:
+                    case TelephonyManager.NETWORK_TYPE_HSPA:
+                    case TelephonyManager.NETWORK_TYPE_EVDO_B:
+                    case TelephonyManager.NETWORK_TYPE_EHRPD:
+                    case TelephonyManager.NETWORK_TYPE_HSPAP:
+                        return LINK_TYPE_3G;
+                    case TelephonyManager.NETWORK_TYPE_LTE:
+                        return LINK_TYPE_4G;
+                    default:
+                        return LINK_TYPE_2G;
+                    /* We are not returning LINK_TYPE_UNKONOWN because we treat unknown
+                     * as "no connection" in code elsewhere, which is not the case.
+                     * TODO: Network change notification issue causes a caching problem (Bug 1236130).
+                     */
+                }
+            case ConnectivityManager.TYPE_WIMAX:
+                return LINK_TYPE_WIMAX;
+            case ConnectivityManager.TYPE_WIFI:
+                return LINK_TYPE_WIFI;
+            default:
+                return LINK_TYPE_UNKONWN;
         }
     }
 
     private static int getNetworkOperator(InfoType type, Context context) {
         if (null == context) {
             return -1;
         }
 
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -309,17 +309,16 @@ gbjar.sources += ['java/org/mozilla/geck
     'FormAssistPopup.java',
     'GeckoAccessibility.java',
     'GeckoActivity.java',
     'GeckoActivityStatus.java',
     'GeckoApp.java',
     'GeckoApplication.java',
     'GeckoAppShell.java',
     'GeckoBatteryManager.java',
-    'GeckoConnectivityReceiver.java',
     'GeckoEditable.java',
     'GeckoEditableClient.java',
     'GeckoEditableListener.java',
     'GeckoEvent.java',
     'GeckoHalDefines.java',
     'GeckoInputConnection.java',
     'GeckoJavaSampler.java',
     'GeckoMessageReceiver.java',
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -827,16 +827,22 @@ nsAppShell::LegacyGeckoEvent::Run()
 #endif
         break;
     }
 
     case AndroidGeckoEvent::NETWORK_CHANGED: {
         hal::NotifyNetworkChange(hal::NetworkInformation(curEvent->ConnectionType(),
                                                          curEvent->IsWifi(),
                                                          curEvent->DHCPGateway()));
+        nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+        if (os) {
+            os->NotifyObservers(nullptr,
+                                NS_NETWORK_LINK_TYPE_TOPIC,
+                                nsString(curEvent->Characters()).get());
+        }
         break;
     }
 
     case AndroidGeckoEvent::SCREENORIENTATION_CHANGED: {
         nsresult rv;
         nsCOMPtr<nsIScreenManager> screenMgr =
             do_GetService("@mozilla.org/gfx/screenmanager;1", &rv);
         if (NS_FAILED(rv)) {