Bug 1020412 - Proper handling of Context in GeckoNetworkManager. r=wesj, a=sledru
--- a/mobile/android/base/GeckoNetworkManager.java
+++ b/mobile/android/base/GeckoNetworkManager.java
@@ -18,20 +18,20 @@ import android.net.wifi.WifiManager;
import android.telephony.TelephonyManager;
import android.util.Log;
/*
* A part of the work of GeckoNetworkManager is to give an general connection
* type based on the current connection. According to spec of NetworkInformation
* API version 3, connection types include: bluetooth, cellular, ethernet, none,
* wifi and other. The objective of providing such general connection is due to
- * some securtiy concerns. In short, we don't want to expose the information of
+ * some security concerns. In short, we don't want to expose the information of
* exact network type, especially the cellular network type.
*
- * Currnet connection is firstly obtained from Android's ConnectivityManager,
+ * 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 {
private static final String LOGTAG = "GeckoNetworkManager";
static private final GeckoNetworkManager sInstance = new GeckoNetworkManager();
@@ -52,97 +52,103 @@ public class GeckoNetworkManager extends
}
}
private enum InfoType {
MCC,
MNC
}
- static private final ConnectionType kDefaultConnectionType = ConnectionType.NONE;
-
- private static Context getApplicationContext() {
- Context context = GeckoAppShell.getContext();
- if (null == context)
- return null;
- return context.getApplicationContext();
- }
private ConnectionType mConnectionType = ConnectionType.NONE;
private final IntentFilter mNetworkFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
// 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;
+ // The application context used for registering receivers, so
+ // we can unregister them again later.
+ private volatile Context mApplicationContext;
+
public static GeckoNetworkManager getInstance() {
return sInstance;
}
@Override
public void onReceive(Context aContext, Intent aIntent) {
updateConnectionType();
}
public void start(final Context context) {
// Note that this initialization clause only runs once.
+ mApplicationContext = context.getApplicationContext();
if (mConnectionType == ConnectionType.NONE) {
mConnectionType = getConnectionType();
}
mShouldBeListening = true;
updateConnectionType();
if (mShouldNotify) {
startListening();
}
}
private void startListening() {
- if (null !=getApplicationContext())
- getApplicationContext().registerReceiver(sInstance, mNetworkFilter);
+ final Context appContext = mApplicationContext;
+ if (appContext == null) {
+ Log.w(LOGTAG, "Not registering receiver: no context!");
+ return;
+ }
+
+ Log.v(LOGTAG, "Registering receiver.");
+ appContext.registerReceiver(this, mNetworkFilter);
}
public void stop() {
mShouldBeListening = false;
if (mShouldNotify) {
stopListening();
}
}
private void stopListening() {
- if (null != getApplicationContext())
- getApplicationContext().unregisterReceiver(sInstance);
+ if (null == mApplicationContext) {
+ return;
+ }
+
+ mApplicationContext.unregisterReceiver(this);
}
private int wifiDhcpGatewayAddress() {
if (mConnectionType != ConnectionType.WIFI) {
return 0;
}
- if (null == getApplicationContext()) {
+ if (null == mApplicationContext) {
return 0;
}
try {
- WifiManager mgr = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ WifiManager mgr = (WifiManager) mApplicationContext.getSystemService(Context.WIFI_SERVICE);
DhcpInfo d = mgr.getDhcpInfo();
if (d == null) {
return 0;
}
return d.gateway;
} catch (Exception ex) {
// getDhcpInfo() is not documented to require any permissions, but on some devices
- // requires android.permission.ACCESS_WIFI_STATE. Just catching the generic exeption
- // here and returning 0. Not logging because this could be noisy
+ // requires android.permission.ACCESS_WIFI_STATE. Just catch the generic exception
+ // here and returning 0. Not logging because this could be noisy.
return 0;
}
}
private void updateConnectionType() {
ConnectionType previousConnectionType = mConnectionType;
mConnectionType = getConnectionType();
@@ -177,23 +183,24 @@ public class GeckoNetworkManager extends
public void disableNotifications() {
mShouldNotify = false;
if (mShouldBeListening) {
stopListening();
}
}
- private static ConnectionType getConnectionType() {
- if (null == getApplicationContext()) {
+ private ConnectionType getConnectionType() {
+ final Context appContext = mApplicationContext;
+
+ if (null == appContext) {
return ConnectionType.NONE;
}
- ConnectivityManager cm =
- (ConnectivityManager)getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+ ConnectivityManager cm = (ConnectivityManager) appContext.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm == null) {
Log.e(LOGTAG, "Connectivity service does not exist");
return ConnectionType.NONE;
}
NetworkInfo ni = null;
try {
ni = cm.getActiveNetworkInfo();
@@ -214,21 +221,22 @@ public class GeckoNetworkManager extends
case ConnectivityManager.TYPE_WIFI:
return ConnectionType.WIFI;
default:
Log.w(LOGTAG, "Ignoring the current network type.");
return ConnectionType.OTHER;
}
}
- private static int getNetworkOperator(InfoType type) {
- if (null == getApplicationContext())
+ private static int getNetworkOperator(InfoType type, Context context) {
+ if (null == context) {
return -1;
+ }
- TelephonyManager tel = (TelephonyManager)getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
+ TelephonyManager tel = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (tel == null) {
Log.e(LOGTAG, "Telephony service does not exist");
return -1;
}
String networkOperator = tel.getNetworkOperator();
if (networkOperator == null || networkOperator.length() <= 3) {
return -1;
@@ -237,19 +245,24 @@ public class GeckoNetworkManager extends
return Integer.parseInt(networkOperator.substring(3));
} else if (type == InfoType.MCC) {
return Integer.parseInt(networkOperator.substring(0, 3));
}
return -1;
}
- /* These are called from javascript c-types. Avoid letting pro-guard delete them */
+ /**
+ * These are called from JavaScript ctypes. Avoid letting ProGuard delete them.
+ *
+ * Note that these methods must only be called after GeckoAppShell has been
+ * initialized: they depend on access to the context.
+ */
@JNITarget
public static int getMCC() {
- return getNetworkOperator(InfoType.MCC);
+ return getNetworkOperator(InfoType.MCC, GeckoAppShell.getContext().getApplicationContext());
}
@JNITarget
public static int getMNC() {
- return getNetworkOperator(InfoType.MNC);
+ return getNetworkOperator(InfoType.MNC, GeckoAppShell.getContext().getApplicationContext());
}
}