2012-01-16 05:44:07 -08:00
|
|
|
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
|
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Android code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Mozilla Foundation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Mounir Lamouri <mounir.lamouri@mozilla.com> (Original Author)
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
package org.mozilla.gecko;
|
|
|
|
|
|
|
|
import java.lang.Math;
|
|
|
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
2012-01-17 10:40:39 -08:00
|
|
|
import android.content.BroadcastReceiver;
|
2012-01-16 05:44:07 -08:00
|
|
|
import android.content.Context;
|
2012-01-17 10:40:39 -08:00
|
|
|
import android.content.Intent;
|
2012-01-16 09:17:34 -08:00
|
|
|
import android.content.IntentFilter;
|
2012-01-16 05:44:07 -08:00
|
|
|
|
|
|
|
import android.net.ConnectivityManager;
|
|
|
|
import android.net.NetworkInfo;
|
|
|
|
|
|
|
|
import android.telephony.TelephonyManager;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A part of the work of GeckoNetworkManager is to give an estimation of the
|
|
|
|
* download speed of the current connection. For known to be fast connection, we
|
|
|
|
* simply use a predefined value (we don't care about being precise). For mobile
|
|
|
|
* connections, we sort them in groups (generations) and estimate the average
|
|
|
|
* real life download speed of that specific generation. This value comes from
|
|
|
|
* researches (eg. Wikipedia articles) or is simply an arbitrary estimation.
|
|
|
|
* Precision isn't important, we mostly need an order of magnitude.
|
|
|
|
*
|
|
|
|
* Each group is composed with networks represented by the constant from
|
|
|
|
* Android's ConnectivityManager and the description comming from the same
|
|
|
|
* class.
|
|
|
|
*
|
|
|
|
* 2G (15 bk/s):
|
|
|
|
* int NETWORK_TYPE_IDEN Current network is iDen
|
|
|
|
* int NETWORK_TYPE_CDMA Current network is CDMA: Either IS95A or IS95B
|
|
|
|
*
|
|
|
|
* 2.5G (60 kb/s)
|
|
|
|
* int NETWORK_TYPE_GPRS Current network is GPRS
|
|
|
|
* int NETWORK_TYPE_1xRTT Current network is 1xRTT
|
|
|
|
*
|
|
|
|
* 2.75G (200 kb/s)
|
|
|
|
* int NETWORK_TYPE_EDGE Current network is EDGE
|
|
|
|
*
|
|
|
|
* 3G (300 kb/s)
|
|
|
|
* int NETWORK_TYPE_UMTS Current network is UMTS
|
|
|
|
* int NETWORK_TYPE_EVDO_0 Current network is EVDO revision 0
|
|
|
|
*
|
|
|
|
* 3.5G (7 Mb/s)
|
|
|
|
* int NETWORK_TYPE_HSPA Current network is HSPA
|
|
|
|
* int NETWORK_TYPE_HSDPA Current network is HSDPA
|
|
|
|
* int NETWORK_TYPE_HSUPA Current network is HSUPA
|
|
|
|
* int NETWORK_TYPE_EVDO_A Current network is EVDO revision A
|
|
|
|
* int NETWORK_TYPE_EVDO_B Current network is EVDO revision B
|
|
|
|
* int NETWORK_TYPE_EHRPD Current network is eHRPD
|
|
|
|
*
|
|
|
|
* 3.75G (20 Mb/s)
|
|
|
|
* int NETWORK_TYPE_HSPAP Current network is HSPA+
|
|
|
|
*
|
|
|
|
* 3.9G (50 Mb/s)
|
|
|
|
* int NETWORK_TYPE_LTE Current network is LTE
|
|
|
|
*/
|
|
|
|
|
|
|
|
public class GeckoNetworkManager
|
2012-01-17 10:40:39 -08:00
|
|
|
extends BroadcastReceiver
|
2012-01-16 05:44:07 -08:00
|
|
|
{
|
2012-01-16 09:17:34 -08:00
|
|
|
static private final GeckoNetworkManager sInstance = new GeckoNetworkManager();
|
|
|
|
|
2012-01-16 05:44:07 -08:00
|
|
|
static private final double kDefaultBandwidth = -1.0;
|
|
|
|
static private final boolean kDefaultCanBeMetered = false;
|
|
|
|
|
|
|
|
static private final double kMaxBandwidth = 20.0;
|
|
|
|
|
2012-01-17 10:40:39 -08:00
|
|
|
static private final double kNetworkSpeedEthernet = 20.0; // 20 Mb/s
|
|
|
|
static private final double kNetworkSpeedWifi = 20.0; // 20 Mb/s
|
|
|
|
static private final double kNetworkSpeedWiMax = 40.0; // 40 Mb/s
|
|
|
|
static private final double kNetworkSpeed_2_G = 15.0 / 1024.0; // 15 kb/s
|
|
|
|
static private final double kNetworkSpeed_2_5_G = 60.0 / 1024.0; // 60 kb/s
|
|
|
|
static private final double kNetworkSpeed_2_75_G = 200.0 / 1024.0; // 200 kb/s
|
|
|
|
static private final double kNetworkSpeed_3_G = 300.0 / 1024.0; // 300 kb/s
|
|
|
|
static private final double kNetworkSpeed_3_5_G = 7.0; // 7 Mb/s
|
|
|
|
static private final double kNetworkSpeed_3_75_G = 20.0; // 20 Mb/s
|
|
|
|
static private final double kNetworkSpeed_3_9_G = 50.0; // 50 Mb/s
|
2012-01-16 05:44:07 -08:00
|
|
|
|
2012-01-17 10:40:39 -08:00
|
|
|
private enum NetworkType {
|
|
|
|
NETWORK_NONE,
|
|
|
|
NETWORK_ETHERNET,
|
|
|
|
NETWORK_WIFI,
|
|
|
|
NETWORK_WIMAX,
|
2012-01-16 05:44:07 -08:00
|
|
|
NETWORK_2_G, // 2G
|
|
|
|
NETWORK_2_5_G, // 2.5G
|
|
|
|
NETWORK_2_75_G, // 2.75G
|
|
|
|
NETWORK_3_G, // 3G
|
|
|
|
NETWORK_3_5_G, // 3.5G
|
|
|
|
NETWORK_3_75_G, // 3.75G
|
|
|
|
NETWORK_3_9_G, // 3.9G
|
|
|
|
NETWORK_UNKNOWN
|
|
|
|
}
|
|
|
|
|
2012-01-16 09:17:34 -08:00
|
|
|
private NetworkType mNetworkType = NetworkType.NETWORK_NONE;
|
|
|
|
private IntentFilter mNetworkFilter = new IntentFilter();
|
2012-01-16 06:01:07 -08:00
|
|
|
// 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;
|
2012-01-16 09:17:34 -08:00
|
|
|
|
|
|
|
public static GeckoNetworkManager getInstance() {
|
|
|
|
return sInstance;
|
|
|
|
}
|
2012-01-17 10:40:39 -08:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context aContext, Intent aIntent) {
|
|
|
|
updateNetworkType();
|
|
|
|
}
|
|
|
|
|
2012-01-16 09:17:34 -08:00
|
|
|
public void init() {
|
|
|
|
mNetworkFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
|
|
|
|
|
|
|
mNetworkType = getNetworkType();
|
2012-01-17 10:40:39 -08:00
|
|
|
}
|
|
|
|
|
2012-01-16 09:17:34 -08:00
|
|
|
public void start() {
|
2012-01-16 06:01:07 -08:00
|
|
|
mShouldBeListening = true;
|
2012-01-17 10:40:39 -08:00
|
|
|
updateNetworkType();
|
2012-01-16 09:17:34 -08:00
|
|
|
|
2012-01-16 06:01:07 -08:00
|
|
|
if (mShouldNotify) {
|
|
|
|
startListening();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void startListening() {
|
2012-01-16 09:17:34 -08:00
|
|
|
GeckoApp.mAppContext.registerReceiver(sInstance, mNetworkFilter);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void stop() {
|
2012-01-16 06:01:07 -08:00
|
|
|
mShouldBeListening = false;
|
|
|
|
|
|
|
|
if (mShouldNotify) {
|
|
|
|
stopListening();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void stopListening() {
|
2012-01-16 09:17:34 -08:00
|
|
|
GeckoApp.mAppContext.unregisterReceiver(sInstance);
|
2012-01-17 10:40:39 -08:00
|
|
|
}
|
|
|
|
|
2012-01-16 09:17:34 -08:00
|
|
|
private void updateNetworkType() {
|
|
|
|
NetworkType previousNetworkType = mNetworkType;
|
|
|
|
mNetworkType = getNetworkType();
|
2012-01-17 10:40:39 -08:00
|
|
|
|
2012-01-16 06:01:07 -08:00
|
|
|
if (mNetworkType == previousNetworkType || !mShouldNotify) {
|
2012-01-17 10:40:39 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-01-16 09:17:34 -08:00
|
|
|
GeckoAppShell.sendEventToGecko(new GeckoEvent(getNetworkSpeed(mNetworkType),
|
|
|
|
isNetworkUsuallyMetered(mNetworkType)));
|
2012-01-17 10:40:39 -08:00
|
|
|
}
|
|
|
|
|
2012-01-16 09:17:34 -08:00
|
|
|
public double[] getCurrentInformation() {
|
|
|
|
return new double[] { getNetworkSpeed(mNetworkType),
|
|
|
|
isNetworkUsuallyMetered(mNetworkType) ? 1.0 : 0.0 };
|
2012-01-17 10:40:39 -08:00
|
|
|
}
|
|
|
|
|
2012-01-16 06:01:07 -08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-17 10:40:39 -08:00
|
|
|
private static NetworkType getNetworkType() {
|
|
|
|
ConnectivityManager cm =
|
|
|
|
(ConnectivityManager)GeckoApp.mAppContext.getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
|
|
|
|
|
|
if (cm.getActiveNetworkInfo() == null) {
|
|
|
|
return NetworkType.NETWORK_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (cm.getActiveNetworkInfo().getType()) {
|
|
|
|
case ConnectivityManager.TYPE_ETHERNET:
|
|
|
|
return NetworkType.NETWORK_ETHERNET;
|
|
|
|
case ConnectivityManager.TYPE_WIFI:
|
|
|
|
return NetworkType.NETWORK_WIFI;
|
|
|
|
case ConnectivityManager.TYPE_WIMAX:
|
|
|
|
return NetworkType.NETWORK_WIMAX;
|
|
|
|
case ConnectivityManager.TYPE_MOBILE:
|
|
|
|
break; // We will handle sub-types after the switch.
|
|
|
|
default:
|
|
|
|
Log.w("GeckoNetworkManager", "Ignoring the current network type.");
|
|
|
|
return NetworkType.NETWORK_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2012-01-16 05:44:07 -08:00
|
|
|
TelephonyManager tm =
|
|
|
|
(TelephonyManager)GeckoApp.mAppContext.getSystemService(Context.TELEPHONY_SERVICE);
|
|
|
|
|
|
|
|
switch (tm.getNetworkType()) {
|
|
|
|
case TelephonyManager.NETWORK_TYPE_IDEN:
|
|
|
|
case TelephonyManager.NETWORK_TYPE_CDMA:
|
2012-01-17 10:40:39 -08:00
|
|
|
return NetworkType.NETWORK_2_G;
|
2012-01-16 05:44:07 -08:00
|
|
|
case TelephonyManager.NETWORK_TYPE_GPRS:
|
|
|
|
case TelephonyManager.NETWORK_TYPE_1xRTT:
|
2012-01-17 10:40:39 -08:00
|
|
|
return NetworkType.NETWORK_2_5_G;
|
2012-01-16 05:44:07 -08:00
|
|
|
case TelephonyManager.NETWORK_TYPE_EDGE:
|
2012-01-17 10:40:39 -08:00
|
|
|
return NetworkType.NETWORK_2_75_G;
|
2012-01-16 05:44:07 -08:00
|
|
|
case TelephonyManager.NETWORK_TYPE_UMTS:
|
|
|
|
case TelephonyManager.NETWORK_TYPE_EVDO_0:
|
2012-01-17 10:40:39 -08:00
|
|
|
return NetworkType.NETWORK_3_G;
|
2012-01-16 05:44:07 -08:00
|
|
|
case TelephonyManager.NETWORK_TYPE_HSPA:
|
|
|
|
case TelephonyManager.NETWORK_TYPE_HSDPA:
|
|
|
|
case TelephonyManager.NETWORK_TYPE_HSUPA:
|
|
|
|
case TelephonyManager.NETWORK_TYPE_EVDO_A:
|
|
|
|
case TelephonyManager.NETWORK_TYPE_EVDO_B:
|
|
|
|
case TelephonyManager.NETWORK_TYPE_EHRPD:
|
2012-01-17 10:40:39 -08:00
|
|
|
return NetworkType.NETWORK_3_5_G;
|
2012-01-16 05:44:07 -08:00
|
|
|
case TelephonyManager.NETWORK_TYPE_HSPAP:
|
2012-01-17 10:40:39 -08:00
|
|
|
return NetworkType.NETWORK_3_75_G;
|
2012-01-16 05:44:07 -08:00
|
|
|
case TelephonyManager.NETWORK_TYPE_LTE:
|
2012-01-17 10:40:39 -08:00
|
|
|
return NetworkType.NETWORK_3_9_G;
|
2012-01-16 05:44:07 -08:00
|
|
|
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
|
|
|
|
default:
|
|
|
|
Log.w("GeckoNetworkManager", "Connected to an unknown mobile network!");
|
2012-01-17 10:40:39 -08:00
|
|
|
return NetworkType.NETWORK_UNKNOWN;
|
2012-01-16 05:44:07 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-17 10:40:39 -08:00
|
|
|
private static double getNetworkSpeed(NetworkType aType) {
|
2012-01-16 05:44:07 -08:00
|
|
|
switch (aType) {
|
2012-01-17 10:40:39 -08:00
|
|
|
case NETWORK_NONE:
|
|
|
|
return 0.0;
|
|
|
|
case NETWORK_ETHERNET:
|
|
|
|
return kNetworkSpeedEthernet;
|
|
|
|
case NETWORK_WIFI:
|
|
|
|
return kNetworkSpeedWifi;
|
|
|
|
case NETWORK_WIMAX:
|
|
|
|
return kNetworkSpeedWiMax;
|
2012-01-16 05:44:07 -08:00
|
|
|
case NETWORK_2_G:
|
|
|
|
return kNetworkSpeed_2_G;
|
|
|
|
case NETWORK_2_5_G:
|
|
|
|
return kNetworkSpeed_2_5_G;
|
|
|
|
case NETWORK_2_75_G:
|
|
|
|
return kNetworkSpeed_2_75_G;
|
|
|
|
case NETWORK_3_G:
|
|
|
|
return kNetworkSpeed_3_G;
|
|
|
|
case NETWORK_3_5_G:
|
|
|
|
return kNetworkSpeed_3_5_G;
|
|
|
|
case NETWORK_3_75_G:
|
|
|
|
return kNetworkSpeed_3_75_G;
|
|
|
|
case NETWORK_3_9_G:
|
|
|
|
return kNetworkSpeed_3_9_G;
|
|
|
|
case NETWORK_UNKNOWN:
|
|
|
|
default:
|
|
|
|
return kDefaultBandwidth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-17 10:40:39 -08:00
|
|
|
private static boolean isNetworkUsuallyMetered(NetworkType aType) {
|
|
|
|
switch (aType) {
|
|
|
|
case NETWORK_NONE:
|
|
|
|
case NETWORK_UNKNOWN:
|
|
|
|
case NETWORK_ETHERNET:
|
|
|
|
case NETWORK_WIFI:
|
|
|
|
case NETWORK_WIMAX:
|
|
|
|
return false;
|
|
|
|
case NETWORK_2_G:
|
|
|
|
case NETWORK_2_5_G:
|
|
|
|
case NETWORK_2_75_G:
|
|
|
|
case NETWORK_3_G:
|
|
|
|
case NETWORK_3_5_G:
|
|
|
|
case NETWORK_3_75_G:
|
|
|
|
case NETWORK_3_9_G:
|
|
|
|
return true;
|
2012-01-16 05:44:07 -08:00
|
|
|
default:
|
2012-01-17 10:40:39 -08:00
|
|
|
Log.e("GeckoNetworkManager", "Got an unexpected network type!");
|
|
|
|
return false;
|
2012-01-16 05:44:07 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|