File: GeckoNetworkManager.java

package info (click to toggle)
wine-gecko-2.24 2.24%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 740,092 kB
  • ctags: 688,789
  • sloc: cpp: 3,160,639; ansic: 1,619,153; python: 164,084; java: 128,022; asm: 114,527; xml: 69,863; sh: 55,281; makefile: 49,648; perl: 20,454; objc: 2,344; yacc: 2,066; pascal: 995; lex: 982; exp: 449; php: 244; lisp: 228; awk: 211; sed: 61; csh: 21; ada: 16; ruby: 3
file content (297 lines) | stat: -rw-r--r-- 10,601 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
/* -*- 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 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.telephony.TelephonyManager;
import android.util.Log;

/*
 * 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 extends BroadcastReceiver {
    private static final String LOGTAG = "GeckoNetworkManager";

    static private final GeckoNetworkManager sInstance = new GeckoNetworkManager();

    static private final double  kDefaultBandwidth    = -1.0;
    static private final boolean kDefaultCanBeMetered = false;

    static private final double  kMaxBandwidth = 20.0;

    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

    private enum NetworkType {
        NETWORK_NONE,
        NETWORK_ETHERNET,
        NETWORK_WIFI,
        NETWORK_WIMAX,
        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
    }

    private Context mApplicationContext;
    private NetworkType  mNetworkType = NetworkType.NETWORK_NONE;
    private IntentFilter mNetworkFilter = new IntentFilter();
    // 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;

    public static GeckoNetworkManager getInstance() {
        return sInstance;
    }

    @Override
    public void onReceive(Context aContext, Intent aIntent) {
        updateNetworkType();
    }

    public void init(Context context) {
        mApplicationContext = context.getApplicationContext();
        mNetworkFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mNetworkType = getNetworkType();
    }

    public void start() {
        mShouldBeListening = true;
        updateNetworkType();

        if (mShouldNotify) {
            startListening();
        }
    }

    private void startListening() {
        mApplicationContext.registerReceiver(sInstance, mNetworkFilter);
    }

    public void stop() {
        mShouldBeListening = false;

        if (mShouldNotify) {
        stopListening();
        }
    }

    private void stopListening() {
        mApplicationContext.unregisterReceiver(sInstance);
    }

    private void updateNetworkType() {
        NetworkType previousNetworkType = mNetworkType;
        mNetworkType = getNetworkType();

        if (mNetworkType == previousNetworkType || !mShouldNotify) {
            return;
        }

        GeckoAppShell.sendEventToGecko(GeckoEvent.createNetworkEvent(
                                       getNetworkSpeed(mNetworkType),
                                       isNetworkUsuallyMetered(mNetworkType)));
    }

    public double[] getCurrentInformation() {
        return new double[] { getNetworkSpeed(mNetworkType),
                              isNetworkUsuallyMetered(mNetworkType) ? 1.0 : 0.0 };
    }

    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();
        }
    }

    private static NetworkType getNetworkType() {
        ConnectivityManager cm =
            (ConnectivityManager)sInstance.mApplicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm == null) {
            Log.e(LOGTAG, "Connectivity service does not exist");
            return NetworkType.NETWORK_NONE;
        }

        NetworkInfo ni = cm.getActiveNetworkInfo();
        if (ni == null) {
            return NetworkType.NETWORK_NONE;
        }

        switch (ni.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(LOGTAG, "Ignoring the current network type.");
            return NetworkType.NETWORK_UNKNOWN;
        }

        TelephonyManager tm =
            (TelephonyManager)sInstance.mApplicationContext.getSystemService(Context.TELEPHONY_SERVICE);
        if (tm == null) {
            Log.e(LOGTAG, "Telephony service does not exist");
            return NetworkType.NETWORK_UNKNOWN;
        }

        switch (tm.getNetworkType()) {
        case TelephonyManager.NETWORK_TYPE_IDEN:
        case TelephonyManager.NETWORK_TYPE_CDMA:
            return NetworkType.NETWORK_2_G;
        case TelephonyManager.NETWORK_TYPE_GPRS:
        case TelephonyManager.NETWORK_TYPE_1xRTT:
            return NetworkType.NETWORK_2_5_G;
        case TelephonyManager.NETWORK_TYPE_EDGE:
            return NetworkType.NETWORK_2_75_G;
        case TelephonyManager.NETWORK_TYPE_UMTS:
        case TelephonyManager.NETWORK_TYPE_EVDO_0:
            return NetworkType.NETWORK_3_G;
        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:
            return NetworkType.NETWORK_3_5_G;
        case TelephonyManager.NETWORK_TYPE_HSPAP:
            return NetworkType.NETWORK_3_75_G;
        case TelephonyManager.NETWORK_TYPE_LTE:
            return NetworkType.NETWORK_3_9_G;
        case TelephonyManager.NETWORK_TYPE_UNKNOWN:
        default:
            Log.w(LOGTAG, "Connected to an unknown mobile network!");
            return NetworkType.NETWORK_UNKNOWN;
        }
    }

    private static double getNetworkSpeed(NetworkType aType) {
        switch (aType) {
        case NETWORK_NONE:
            return 0.0;
        case NETWORK_ETHERNET:
            return kNetworkSpeedEthernet;
        case NETWORK_WIFI:
            return kNetworkSpeedWifi;
        case NETWORK_WIMAX:
            return kNetworkSpeedWiMax;
        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;
        }
    }

    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;
        default:
            Log.e(LOGTAG, "Got an unexpected network type!");
            return false;
        }
    }
}