mobile/android/base/GeckoNetworkManager.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 package org.mozilla.gecko;
     8 import org.mozilla.gecko.mozglue.JNITarget;
    10 import android.content.BroadcastReceiver;
    11 import android.content.Context;
    12 import android.content.Intent;
    13 import android.content.IntentFilter;
    14 import android.net.ConnectivityManager;
    15 import android.net.DhcpInfo;
    16 import android.net.NetworkInfo;
    17 import android.net.wifi.WifiManager;
    18 import android.telephony.TelephonyManager;
    19 import android.util.Log;
    21 /*
    22  * A part of the work of GeckoNetworkManager is to give an general connection
    23  * type based on the current connection. According to spec of NetworkInformation
    24  * API version 3, connection types include: bluetooth, cellular, ethernet, none,
    25  * wifi and other. The objective of providing such general connection is due to
    26  * some security concerns. In short, we don't want to expose the information of
    27  * exact network type, especially the cellular network type.
    28  *
    29  * Current connection is firstly obtained from Android's ConnectivityManager,
    30  * which is represented by the constant, and then will be mapped into the
    31  * connection type defined in Network Information API version 3.
    32  */
    34 public class GeckoNetworkManager extends BroadcastReceiver {
    35     private static final String LOGTAG = "GeckoNetworkManager";
    37     static private final GeckoNetworkManager sInstance = new GeckoNetworkManager();
    39     // Connection Type defined in Network Information API v3.
    40     private enum ConnectionType {
    41         CELLULAR(0),
    42         BLUETOOTH(1),
    43         ETHERNET(2),
    44         WIFI(3),
    45         OTHER(4),
    46         NONE(5);
    48         public final int value;
    50         private ConnectionType(int value) {
    51             this.value = value;
    52         }
    53     }
    55     private enum InfoType {
    56         MCC,
    57         MNC
    58     }
    60     private ConnectionType mConnectionType = ConnectionType.NONE;
    61     private final IntentFilter mNetworkFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
    63     // Whether the manager should be listening to Network Information changes.
    64     private boolean mShouldBeListening = false;
    66     // Whether the manager should notify Gecko that a change in Network
    67     // Information happened.
    68     private boolean mShouldNotify = false;
    70     // The application context used for registering receivers, so
    71     // we can unregister them again later.
    72     private volatile Context mApplicationContext;
    74     public static GeckoNetworkManager getInstance() {
    75         return sInstance;
    76     }
    78     @Override
    79     public void onReceive(Context aContext, Intent aIntent) {
    80         updateConnectionType();
    81     }
    83     public void start(final Context context) {
    84         // Note that this initialization clause only runs once.
    85         mApplicationContext = context.getApplicationContext();
    86         if (mConnectionType == ConnectionType.NONE) {
    87             mConnectionType = getConnectionType();
    88         }
    90         mShouldBeListening = true;
    91         updateConnectionType();
    93         if (mShouldNotify) {
    94             startListening();
    95         }
    96     }
    98     private void startListening() {
    99         final Context appContext = mApplicationContext;
   100         if (appContext == null) {
   101             Log.w(LOGTAG, "Not registering receiver: no context!");
   102             return;
   103         }
   105         Log.v(LOGTAG, "Registering receiver.");
   106         appContext.registerReceiver(this, mNetworkFilter);
   107     }
   109     public void stop() {
   110         mShouldBeListening = false;
   112         if (mShouldNotify) {
   113             stopListening();
   114         }
   115     }
   117     private void stopListening() {
   118         if (null == mApplicationContext) {
   119             return;
   120         }
   122         mApplicationContext.unregisterReceiver(this);
   123     }
   125     private int wifiDhcpGatewayAddress() {
   126         if (mConnectionType != ConnectionType.WIFI) {
   127             return 0;
   128         }
   130         if (null == mApplicationContext) {
   131             return 0;
   132         }
   134         try {
   135             WifiManager mgr = (WifiManager) mApplicationContext.getSystemService(Context.WIFI_SERVICE);
   136             DhcpInfo d = mgr.getDhcpInfo();
   137             if (d == null) {
   138                 return 0;
   139             }
   141             return d.gateway;
   143         } catch (Exception ex) {
   144             // getDhcpInfo() is not documented to require any permissions, but on some devices
   145             // requires android.permission.ACCESS_WIFI_STATE. Just catch the generic exception
   146             // here and returning 0. Not logging because this could be noisy.
   147             return 0;
   148         }
   149     }
   151     private void updateConnectionType() {
   152         ConnectionType previousConnectionType = mConnectionType;
   153         mConnectionType = getConnectionType();
   155         if (mConnectionType == previousConnectionType || !mShouldNotify) {
   156             return;
   157         }
   159         GeckoAppShell.sendEventToGecko(GeckoEvent.createNetworkEvent(
   160                                        mConnectionType.value,
   161                                        mConnectionType == ConnectionType.WIFI,
   162                                        wifiDhcpGatewayAddress()));
   163     }
   165     public double[] getCurrentInformation() {
   166         return new double[] { mConnectionType.value,
   167                               (mConnectionType == ConnectionType.WIFI) ? 1.0 : 0.0,
   168                               wifiDhcpGatewayAddress()};
   169     }
   171     public void enableNotifications() {
   172         // We set mShouldNotify *after* calling updateConnectionType() to make sure we
   173         // don't notify an eventual change in mConnectionType.
   174         mConnectionType = ConnectionType.NONE; // force a notification
   175         updateConnectionType();
   176         mShouldNotify = true;
   178         if (mShouldBeListening) {
   179             startListening();
   180         }
   181     }
   183     public void disableNotifications() {
   184         mShouldNotify = false;
   186         if (mShouldBeListening) {
   187             stopListening();
   188         }
   189     }
   191     private ConnectionType getConnectionType() {
   192         final Context appContext = mApplicationContext;
   194         if (null == appContext) {
   195             return ConnectionType.NONE;
   196         }
   198         ConnectivityManager cm = (ConnectivityManager) appContext.getSystemService(Context.CONNECTIVITY_SERVICE);
   199         if (cm == null) {
   200             Log.e(LOGTAG, "Connectivity service does not exist");
   201             return ConnectionType.NONE;
   202         }
   204         NetworkInfo ni = null;
   205         try {
   206             ni = cm.getActiveNetworkInfo();
   207         } catch (SecurityException se) {} // if we don't have the permission, fall through to null check
   209         if (ni == null) {
   210             return ConnectionType.NONE;
   211         }
   213         switch (ni.getType()) {
   214         case ConnectivityManager.TYPE_BLUETOOTH:
   215             return ConnectionType.BLUETOOTH;
   216         case ConnectivityManager.TYPE_ETHERNET:
   217             return ConnectionType.ETHERNET;
   218         case ConnectivityManager.TYPE_MOBILE:
   219         case ConnectivityManager.TYPE_WIMAX:
   220             return ConnectionType.CELLULAR;
   221         case ConnectivityManager.TYPE_WIFI:
   222             return ConnectionType.WIFI;
   223         default:
   224             Log.w(LOGTAG, "Ignoring the current network type.");
   225             return ConnectionType.OTHER;
   226         }
   227     }
   229     private static int getNetworkOperator(InfoType type, Context context) {
   230         if (null == context) {
   231             return -1;
   232         }
   234         TelephonyManager tel = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
   235         if (tel == null) {
   236             Log.e(LOGTAG, "Telephony service does not exist");
   237             return -1;
   238         }
   240         String networkOperator = tel.getNetworkOperator();
   241         if (networkOperator == null || networkOperator.length() <= 3) {
   242             return -1;
   243         }
   244         if (type == InfoType.MNC) {
   245             return Integer.parseInt(networkOperator.substring(3));
   246         } else if (type == InfoType.MCC) {
   247             return Integer.parseInt(networkOperator.substring(0, 3));
   248         }
   250         return -1;
   251     }
   253     /**
   254      * These are called from JavaScript ctypes. Avoid letting ProGuard delete them.
   255      *
   256      * Note that these methods must only be called after GeckoAppShell has been
   257      * initialized: they depend on access to the context.
   258      */
   259     @JNITarget
   260     public static int getMCC() {
   261         return getNetworkOperator(InfoType.MCC, GeckoAppShell.getContext().getApplicationContext());
   262     }
   264     @JNITarget
   265     public static int getMNC() {
   266         return getNetworkOperator(InfoType.MNC, GeckoAppShell.getContext().getApplicationContext());
   267     }
   268 }

mercurial