blob: 8f0816d5097ca21447c0904d254f6d48ac719131 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import android.app.Notification;
20import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import android.content.Context;
TK MUN4bdab172011-02-23 18:55:55 +090022import android.content.ContentResolver;
23import android.content.ContextWrapper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.Intent;
25import android.content.pm.PackageManager;
TK MUN4bdab172011-02-23 18:55:55 +090026import android.content.res.Resources;
27import android.content.res.Resources.NotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.net.ConnectivityManager;
29import android.net.IConnectivityManager;
30import android.net.MobileDataStateTracker;
31import android.net.NetworkInfo;
32import android.net.NetworkStateTracker;
33import android.net.wifi.WifiStateTracker;
TK MUN4bdab172011-02-23 18:55:55 +090034import android.net.wimax.WimaxManagerConstants;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.os.Binder;
36import android.os.Handler;
Robert Greenwalt42acef32009-08-12 16:08:25 -070037import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.os.Looper;
39import android.os.Message;
Robert Greenwalt42acef32009-08-12 16:08:25 -070040import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.os.ServiceManager;
42import android.os.SystemProperties;
43import android.provider.Settings;
Robert Greenwalt42acef32009-08-12 16:08:25 -070044import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -080046import android.util.Slog;
Robert Greenwalt42acef32009-08-12 16:08:25 -070047import com.android.internal.telephony.Phone;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080048import com.android.server.connectivity.Tethering;
TK MUN4bdab172011-02-23 18:55:55 +090049import dalvik.system.DexClassLoader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import java.io.FileDescriptor;
51import java.io.PrintWriter;
TK MUN4bdab172011-02-23 18:55:55 +090052import java.lang.reflect.Constructor;
53import java.lang.reflect.Method;
54import java.lang.reflect.Modifier;
55import java.lang.reflect.InvocationTargetException;
Robert Greenwalt42acef32009-08-12 16:08:25 -070056import java.util.ArrayList;
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -070057import java.util.GregorianCalendar;
Robert Greenwalt42acef32009-08-12 16:08:25 -070058import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059
TK MUN4bdab172011-02-23 18:55:55 +090060
61
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062/**
63 * @hide
64 */
65public class ConnectivityService extends IConnectivityManager.Stub {
66
Dianne Hackborncef65ee2010-09-30 18:27:22 -070067 private static final boolean DBG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 private static final String TAG = "ConnectivityService";
69
Robert Greenwalt42acef32009-08-12 16:08:25 -070070 // how long to wait before switching back to a radio's default network
71 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
72 // system property that can override the above value
73 private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
74 "android.telephony.apn-restore";
75
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080076
77 private Tethering mTethering;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -080078 private boolean mTetheringConfigValid = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 /**
81 * Sometimes we want to refer to the individual network state
82 * trackers separately, and sometimes we just want to treat them
83 * abstractly.
84 */
85 private NetworkStateTracker mNetTrackers[];
Robert Greenwalt42acef32009-08-12 16:08:25 -070086
87 /**
88 * A per Net list of the PID's that requested access to the net
89 * used both as a refcount and for per-PID DNS selection
90 */
91 private List mNetRequestersPids[];
92
Robert Greenwalt42acef32009-08-12 16:08:25 -070093 // priority order of the nettrackers
94 // (excluding dynamically set mNetworkPreference)
95 // TODO - move mNetworkTypePreference into this
96 private int[] mPriorityList;
97
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098 private Context mContext;
99 private int mNetworkPreference;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700100 private int mActiveDefaultNetwork = -1;
Robert Greenwaltd7085fc2010-09-08 15:24:47 -0700101 // 0 is full bad, 100 is full good
102 private int mDefaultInetCondition = 0;
103 private int mDefaultInetConditionPublished = 0;
104 private boolean mInetConditionChangeInFlight = false;
105 private int mDefaultConnectionSequence = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106
107 private int mNumDnsEntries;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108
109 private boolean mTestMode;
110 private static ConnectivityService sServiceInstance;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700111 private static final int ENABLED = 1;
112 private static final int DISABLED = 0;
113
114 // Share the event space with NetworkStateTracker (which can't see this
115 // internal class but sends us events). If you change these, change
116 // NetworkStateTracker.java too.
117 private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1;
118 private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100;
119
120 /**
121 * used internally as a delayed event to make us switch back to the
122 * default network
123 */
124 private static final int EVENT_RESTORE_DEFAULT_NETWORK =
125 MAX_NETWORK_STATE_TRACKER_EVENT + 1;
126
127 /**
128 * used internally to change our mobile data enabled flag
129 */
130 private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED =
131 MAX_NETWORK_STATE_TRACKER_EVENT + 2;
132
133 /**
134 * used internally to change our network preference setting
135 * arg1 = networkType to prefer
136 */
137 private static final int EVENT_SET_NETWORK_PREFERENCE =
138 MAX_NETWORK_STATE_TRACKER_EVENT + 3;
139
140 /**
141 * used internally to synchronize inet condition reports
142 * arg1 = networkType
143 * arg2 = condition (0 bad, 100 good)
144 */
145 private static final int EVENT_INET_CONDITION_CHANGE =
146 MAX_NETWORK_STATE_TRACKER_EVENT + 4;
147
148 /**
149 * used internally to mark the end of inet condition hold periods
150 * arg1 = networkType
151 */
152 private static final int EVENT_INET_CONDITION_HOLD_END =
153 MAX_NETWORK_STATE_TRACKER_EVENT + 5;
154
155 /**
156 * used internally to set the background data preference
157 * arg1 = TRUE for enabled, FALSE for disabled
158 */
159 private static final int EVENT_SET_BACKGROUND_DATA =
160 MAX_NETWORK_STATE_TRACKER_EVENT + 6;
161
162 /**
163 * used internally to set enable/disable cellular data
164 * arg1 = ENBALED or DISABLED
165 */
166 private static final int EVENT_SET_MOBILE_DATA =
167 MAX_NETWORK_STATE_TRACKER_EVENT + 7;
168
Robert Greenwalt42acef32009-08-12 16:08:25 -0700169 private Handler mHandler;
170
171 // list of DeathRecipients used to make sure features are turned off when
172 // a process dies
173 private List mFeatureUsers;
174
Mike Lockwood0f79b542009-08-14 14:18:49 -0400175 private boolean mSystemReady;
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800176 private Intent mInitialBroadcast;
Mike Lockwood0f79b542009-08-14 14:18:49 -0400177
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -0700178 // used in DBG mode to track inet condition reports
179 private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
180 private ArrayList mInetLog;
181
Robert Greenwalt511288a2009-12-07 11:33:18 -0800182 private static class NetworkAttributes {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700183 /**
184 * Class for holding settings read from resources.
185 */
186 public String mName;
187 public int mType;
188 public int mRadio;
189 public int mPriority;
Robert Greenwalt511288a2009-12-07 11:33:18 -0800190 public NetworkInfo.State mLastState;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700191 public NetworkAttributes(String init) {
192 String fragments[] = init.split(",");
193 mName = fragments[0].toLowerCase();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700194 mType = Integer.parseInt(fragments[1]);
195 mRadio = Integer.parseInt(fragments[2]);
196 mPriority = Integer.parseInt(fragments[3]);
Robert Greenwalt511288a2009-12-07 11:33:18 -0800197 mLastState = NetworkInfo.State.UNKNOWN;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700198 }
199 public boolean isDefault() {
200 return (mType == mRadio);
201 }
202 }
203 NetworkAttributes[] mNetAttributes;
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700204 int mNetworksDefined;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700205
Robert Greenwalt511288a2009-12-07 11:33:18 -0800206 private static class RadioAttributes {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700207 public int mSimultaneity;
208 public int mType;
209 public RadioAttributes(String init) {
210 String fragments[] = init.split(",");
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700211 mType = Integer.parseInt(fragments[0]);
212 mSimultaneity = Integer.parseInt(fragments[1]);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700213 }
214 }
215 RadioAttributes[] mRadioAttributes;
216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 private static class ConnectivityThread extends Thread {
218 private Context mContext;
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 private ConnectivityThread(Context context) {
221 super("ConnectivityThread");
222 mContext = context;
223 }
224
225 @Override
226 public void run() {
227 Looper.prepare();
228 synchronized (this) {
229 sServiceInstance = new ConnectivityService(mContext);
230 notifyAll();
231 }
232 Looper.loop();
233 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 public static ConnectivityService getServiceInstance(Context context) {
236 ConnectivityThread thread = new ConnectivityThread(context);
237 thread.start();
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 synchronized (thread) {
240 while (sServiceInstance == null) {
241 try {
242 // Wait until sServiceInstance has been initialized.
243 thread.wait();
244 } catch (InterruptedException ignore) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800245 Slog.e(TAG,
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700246 "Unexpected InterruptedException while waiting"+
247 " for ConnectivityService thread");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 }
249 }
250 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 return sServiceInstance;
253 }
254 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 public static ConnectivityService getInstance(Context context) {
257 return ConnectivityThread.getServiceInstance(context);
258 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 private ConnectivityService(Context context) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800261 if (DBG) Slog.v(TAG, "ConnectivityService starting up");
Robert Greenwaltde8383c2010-01-14 17:47:58 -0800262
263 // setup our unique device name
264 String id = Settings.Secure.getString(context.getContentResolver(),
265 Settings.Secure.ANDROID_ID);
266 if (id != null && id.length() > 0) {
267 String name = new String("android_").concat(id);
268 SystemProperties.set("net.hostname", name);
269 }
270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 mContext = context;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700272 mNetTrackers = new NetworkStateTracker[
273 ConnectivityManager.MAX_NETWORK_TYPE+1];
274 mHandler = new MyHandler();
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 mNetworkPreference = getPersistedNetworkPreference();
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700277
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700278 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
279 mNetAttributes = new NetworkAttributes[ConnectivityManager.MAX_NETWORK_TYPE+1];
280
Robert Greenwalt42acef32009-08-12 16:08:25 -0700281 // Load device network attributes from resources
Robert Greenwalt42acef32009-08-12 16:08:25 -0700282 String[] raStrings = context.getResources().getStringArray(
283 com.android.internal.R.array.radioAttributes);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700284 for (String raString : raStrings) {
285 RadioAttributes r = new RadioAttributes(raString);
286 if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800287 Slog.e(TAG, "Error in radioAttributes - ignoring attempt to define type " + r.mType);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700288 continue;
289 }
290 if (mRadioAttributes[r.mType] != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800291 Slog.e(TAG, "Error in radioAttributes - ignoring attempt to redefine type " +
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700292 r.mType);
293 continue;
294 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700295 mRadioAttributes[r.mType] = r;
296 }
297
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700298 String[] naStrings = context.getResources().getStringArray(
299 com.android.internal.R.array.networkAttributes);
300 for (String naString : naStrings) {
301 try {
302 NetworkAttributes n = new NetworkAttributes(naString);
303 if (n.mType > ConnectivityManager.MAX_NETWORK_TYPE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800304 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to define type " +
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700305 n.mType);
306 continue;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700307 }
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700308 if (mNetAttributes[n.mType] != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800309 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to redefine type " +
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700310 n.mType);
311 continue;
312 }
313 if (mRadioAttributes[n.mRadio] == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800314 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to use undefined " +
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700315 "radio " + n.mRadio + " in network type " + n.mType);
316 continue;
317 }
318 mNetAttributes[n.mType] = n;
319 mNetworksDefined++;
320 } catch(Exception e) {
321 // ignore it - leave the entry null
Robert Greenwalt42acef32009-08-12 16:08:25 -0700322 }
323 }
324
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700325 // high priority first
326 mPriorityList = new int[mNetworksDefined];
327 {
328 int insertionPoint = mNetworksDefined-1;
329 int currentLowest = 0;
330 int nextLowest = 0;
331 while (insertionPoint > -1) {
332 for (NetworkAttributes na : mNetAttributes) {
333 if (na == null) continue;
334 if (na.mPriority < currentLowest) continue;
335 if (na.mPriority > currentLowest) {
336 if (na.mPriority < nextLowest || nextLowest == 0) {
337 nextLowest = na.mPriority;
338 }
339 continue;
340 }
341 mPriorityList[insertionPoint--] = na.mType;
342 }
343 currentLowest = nextLowest;
344 nextLowest = 0;
345 }
346 }
347
348 mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
349 for (int i : mPriorityList) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700350 mNetRequestersPids[i] = new ArrayList();
351 }
352
353 mFeatureUsers = new ArrayList();
354
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700355 mNumDnsEntries = 0;
356
357 mTestMode = SystemProperties.get("cm.test.mode").equals("true")
358 && SystemProperties.get("ro.build.type").equals("eng");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 /*
360 * Create the network state trackers for Wi-Fi and mobile
361 * data. Maybe this could be done with a factory class,
362 * but it's not clear that it's worth it, given that
363 * the number of different network types is not going
364 * to change very often.
365 */
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800366 boolean noMobileData = !getMobileDataEnabled();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700367 for (int netType : mPriorityList) {
368 switch (mNetAttributes[netType].mRadio) {
369 case ConnectivityManager.TYPE_WIFI:
Joe Onorato8a9b2202010-02-26 18:56:32 -0800370 if (DBG) Slog.v(TAG, "Starting Wifi Service.");
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700371 WifiStateTracker wst = new WifiStateTracker(context, mHandler);
372 WifiService wifiService = new WifiService(context, wst);
373 ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
Irfan Sheriff7b009782010-03-11 16:37:45 -0800374 wifiService.startWifi();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700375 mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
376 wst.startMonitoring();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700378 break;
379 case ConnectivityManager.TYPE_MOBILE:
380 mNetTrackers[netType] = new MobileDataStateTracker(context, mHandler,
381 netType, mNetAttributes[netType].mName);
382 mNetTrackers[netType].startMonitoring();
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800383 if (noMobileData) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800384 if (DBG) Slog.d(TAG, "tearing down Mobile networks due to setting");
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800385 mNetTrackers[netType].teardown();
386 }
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700387 break;
TK MUN4bdab172011-02-23 18:55:55 +0900388 case ConnectivityManager.TYPE_WIMAX:
389 NetworkStateTracker nst = makeWimaxStateTracker();
390 if (nst != null) {
391 nst.startMonitoring();
392 }
393 mNetTrackers[netType] = nst;
394 break;
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700395 default:
Joe Onorato8a9b2202010-02-26 18:56:32 -0800396 Slog.e(TAG, "Trying to create a DataStateTracker for an unknown radio type " +
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700397 mNetAttributes[netType].mRadio);
398 continue;
399 }
400 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800401
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800402 mTethering = new Tethering(mContext, mHandler.getLooper());
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800403 mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) ||
404 !mTethering.isDunRequired()) &&
405 (mTethering.getTetherableUsbRegexs().length != 0 ||
406 mTethering.getTetherableWifiRegexs().length != 0) &&
407 mTethering.getUpstreamIfaceRegexs().length != 0);
408
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -0700409 if (DBG) {
410 mInetLog = new ArrayList();
411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 }
413
TK MUN4bdab172011-02-23 18:55:55 +0900414 private NetworkStateTracker makeWimaxStateTracker() {
415 //Initialize Wimax
416 DexClassLoader wimaxClassLoader;
417 Class wimaxStateTrackerClass = null;
418 Class wimaxServiceClass = null;
419 Class wimaxManagerClass;
420 String wimaxJarLocation;
421 String wimaxLibLocation;
422 String wimaxManagerClassName;
423 String wimaxServiceClassName;
424 String wimaxStateTrackerClassName;
425
426 NetworkStateTracker wimaxStateTracker = null;
427
428 boolean isWimaxEnabled = mContext.getResources().getBoolean(
429 com.android.internal.R.bool.config_wimaxEnabled);
430
431 if (isWimaxEnabled) {
432 try {
433 wimaxJarLocation = mContext.getResources().getString(
434 com.android.internal.R.string.config_wimaxServiceJarLocation);
435 wimaxLibLocation = mContext.getResources().getString(
436 com.android.internal.R.string.config_wimaxNativeLibLocation);
437 wimaxManagerClassName = mContext.getResources().getString(
438 com.android.internal.R.string.config_wimaxManagerClassname);
439 wimaxServiceClassName = mContext.getResources().getString(
440 com.android.internal.R.string.config_wimaxServiceClassname);
441 wimaxStateTrackerClassName = mContext.getResources().getString(
442 com.android.internal.R.string.config_wimaxStateTrackerClassname);
443
444 wimaxClassLoader = new DexClassLoader(wimaxJarLocation,
445 new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
446 wimaxLibLocation,ClassLoader.getSystemClassLoader());
447
448 try {
449 wimaxManagerClass = wimaxClassLoader.loadClass(wimaxManagerClassName);
450 wimaxStateTrackerClass = wimaxClassLoader.loadClass(wimaxStateTrackerClassName);
451 wimaxServiceClass = wimaxClassLoader.loadClass(wimaxServiceClassName);
452 } catch (ClassNotFoundException ex) {
453 ex.printStackTrace();
454 return null;
455 }
456 } catch(Resources.NotFoundException ex) {
457 Slog.e(TAG, "Wimax Resources does not exist!!! ");
458 return null;
459 }
460
461 try {
462 Slog.v(TAG, "Starting Wimax Service... ");
463
464 Constructor wmxStTrkrConst = wimaxStateTrackerClass.getConstructor
465 (new Class[] {Context.class,Handler.class});
466 wimaxStateTracker = (NetworkStateTracker)wmxStTrkrConst.newInstance(mContext,mHandler);
467
468 Constructor wmxSrvConst = wimaxServiceClass.getDeclaredConstructor
469 (new Class[] {Context.class,wimaxStateTrackerClass});
470 wmxSrvConst.setAccessible(true);
471 IBinder svcInvoker = (IBinder) wmxSrvConst.newInstance(mContext,wimaxStateTracker);
472 wmxSrvConst.setAccessible(false);
473
474 ServiceManager.addService(WimaxManagerConstants.WIMAX_SERVICE, svcInvoker);
475
476 } catch(ClassCastException ex) {
477 ex.printStackTrace();
478 return null;
479 } catch (NoSuchMethodException ex) {
480 ex.printStackTrace();
481 return null;
482 } catch (InstantiationException ex) {
483 ex.printStackTrace();
484 return null;
485 } catch(IllegalAccessException ex) {
486 ex.printStackTrace();
487 return null;
488 } catch(InvocationTargetException ex) {
489 ex.printStackTrace();
490 return null;
491 } catch(Exception ex) {
492 ex.printStackTrace();
493 return null;
494 }
495 } else {
496 Slog.e(TAG, "Wimax is not enabled or not added to the network attributes!!! ");
497 return null;
498 }
499
500 return wimaxStateTracker;
501 }
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 /**
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700504 * Sets the preferred network.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800505 * @param preference the new preference
506 */
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700507 public void setNetworkPreference(int preference) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 enforceChangePermission();
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700509
510 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 }
512
513 public int getNetworkPreference() {
514 enforceAccessPermission();
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700515 int preference;
516 synchronized(this) {
517 preference = mNetworkPreference;
518 }
519 return preference;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 }
521
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700522 private void handleSetNetworkPreference(int preference) {
523 if (ConnectivityManager.isNetworkTypeValid(preference) &&
524 mNetAttributes[preference] != null &&
525 mNetAttributes[preference].isDefault()) {
526 if (mNetworkPreference != preference) {
527 final ContentResolver cr = mContext.getContentResolver();
528 Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference);
529 synchronized(this) {
530 mNetworkPreference = preference;
531 }
532 enforcePreference();
533 }
534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 private int getPersistedNetworkPreference() {
538 final ContentResolver cr = mContext.getContentResolver();
539
540 final int networkPrefSetting = Settings.Secure
541 .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
542 if (networkPrefSetting != -1) {
543 return networkPrefSetting;
544 }
545
546 return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
547 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 /**
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700550 * Make the state of network connectivity conform to the preference settings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 * In this method, we only tear down a non-preferred network. Establishing
552 * a connection to the preferred network is taken care of when we handle
553 * the disconnect event from the non-preferred network
554 * (see {@link #handleDisconnect(NetworkInfo)}).
555 */
556 private void enforcePreference() {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700557 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 return;
559
Robert Greenwalt42acef32009-08-12 16:08:25 -0700560 if (!mNetTrackers[mNetworkPreference].isAvailable())
561 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562
Robert Greenwalt42acef32009-08-12 16:08:25 -0700563 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700564 if (t != mNetworkPreference && mNetTrackers[t] != null &&
Robert Greenwalt42acef32009-08-12 16:08:25 -0700565 mNetTrackers[t].getNetworkInfo().isConnected()) {
Robert Greenwaltec9fe462009-08-20 15:25:14 -0700566 if (DBG) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800567 Slog.d(TAG, "tearing down " +
Robert Greenwaltec9fe462009-08-20 15:25:14 -0700568 mNetTrackers[t].getNetworkInfo() +
569 " in enforcePreference");
570 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700571 teardown(mNetTrackers[t]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 }
573 }
574 }
575
576 private boolean teardown(NetworkStateTracker netTracker) {
577 if (netTracker.teardown()) {
578 netTracker.setTeardownRequested(true);
579 return true;
580 } else {
581 return false;
582 }
583 }
584
585 /**
586 * Return NetworkInfo for the active (i.e., connected) network interface.
587 * It is assumed that at most one network is active at a time. If more
588 * than one is active, it is indeterminate which will be returned.
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700589 * @return the info for the active network, or {@code null} if none is
590 * active
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 */
592 public NetworkInfo getActiveNetworkInfo() {
593 enforceAccessPermission();
Robert Greenwalt7cf5b412011-03-24 21:41:41 -0700594 if (mActiveDefaultNetwork != -1) {
595 return mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 }
597 return null;
598 }
599
600 public NetworkInfo getNetworkInfo(int networkType) {
601 enforceAccessPermission();
602 if (ConnectivityManager.isNetworkTypeValid(networkType)) {
603 NetworkStateTracker t = mNetTrackers[networkType];
604 if (t != null)
605 return t.getNetworkInfo();
606 }
607 return null;
608 }
609
610 public NetworkInfo[] getAllNetworkInfo() {
611 enforceAccessPermission();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700612 NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 int i = 0;
614 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700615 if(t != null) result[i++] = t.getNetworkInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 }
617 return result;
618 }
619
620 public boolean setRadios(boolean turnOn) {
621 boolean result = true;
622 enforceChangePermission();
623 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700624 if (t != null) result = t.setRadio(turnOn) && result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 }
626 return result;
627 }
628
629 public boolean setRadio(int netType, boolean turnOn) {
630 enforceChangePermission();
631 if (!ConnectivityManager.isNetworkTypeValid(netType)) {
632 return false;
633 }
634 NetworkStateTracker tracker = mNetTrackers[netType];
635 return tracker != null && tracker.setRadio(turnOn);
636 }
637
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700638 /**
639 * Used to notice when the calling process dies so we can self-expire
640 *
641 * Also used to know if the process has cleaned up after itself when
642 * our auto-expire timer goes off. The timer has a link to an object.
643 *
644 */
Robert Greenwalt42acef32009-08-12 16:08:25 -0700645 private class FeatureUser implements IBinder.DeathRecipient {
646 int mNetworkType;
647 String mFeature;
648 IBinder mBinder;
649 int mPid;
650 int mUid;
Robert Greenwaltb9285352009-12-21 18:24:07 -0800651 long mCreateTime;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700652
653 FeatureUser(int type, String feature, IBinder binder) {
654 super();
655 mNetworkType = type;
656 mFeature = feature;
657 mBinder = binder;
658 mPid = getCallingPid();
659 mUid = getCallingUid();
Robert Greenwaltb9285352009-12-21 18:24:07 -0800660 mCreateTime = System.currentTimeMillis();
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700661
Robert Greenwalt42acef32009-08-12 16:08:25 -0700662 try {
663 mBinder.linkToDeath(this, 0);
664 } catch (RemoteException e) {
665 binderDied();
666 }
667 }
668
669 void unlinkDeathRecipient() {
670 mBinder.unlinkToDeath(this, 0);
671 }
672
673 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800674 Slog.d(TAG, "ConnectivityService FeatureUser binderDied(" +
Robert Greenwaltb9285352009-12-21 18:24:07 -0800675 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
676 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700677 stopUsingNetworkFeature(this, false);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700678 }
679
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700680 public void expire() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800681 Slog.d(TAG, "ConnectivityService FeatureUser expire(" +
Robert Greenwaltb9285352009-12-21 18:24:07 -0800682 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
683 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700684 stopUsingNetworkFeature(this, false);
685 }
Robert Greenwaltb9285352009-12-21 18:24:07 -0800686
687 public String toString() {
688 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
689 (System.currentTimeMillis() - mCreateTime) + " mSec ago";
690 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700691 }
692
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700693 // javadoc from interface
Robert Greenwalt42acef32009-08-12 16:08:25 -0700694 public int startUsingNetworkFeature(int networkType, String feature,
695 IBinder binder) {
696 if (DBG) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800697 Slog.d(TAG, "startUsingNetworkFeature for net " + networkType +
Robert Greenwalt42acef32009-08-12 16:08:25 -0700698 ": " + feature);
699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 enforceChangePermission();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700701 if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
702 mNetAttributes[networkType] == null) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700703 return Phone.APN_REQUEST_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700705
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700706 FeatureUser f = new FeatureUser(networkType, feature, binder);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700707
708 // TODO - move this into the MobileDataStateTracker
709 int usedNetworkType = networkType;
710 if(networkType == ConnectivityManager.TYPE_MOBILE) {
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800711 if (!getMobileDataEnabled()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800712 if (DBG) Slog.d(TAG, "requested special network with data disabled - rejected");
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800713 return Phone.APN_TYPE_NOT_AVAILABLE;
714 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700715 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
716 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
717 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
718 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
719 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
720 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
721 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
722 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
723 }
724 }
725 NetworkStateTracker network = mNetTrackers[usedNetworkType];
726 if (network != null) {
727 if (usedNetworkType != networkType) {
728 Integer currentPid = new Integer(getCallingPid());
729
730 NetworkStateTracker radio = mNetTrackers[networkType];
731 NetworkInfo ni = network.getNetworkInfo();
732
733 if (ni.isAvailable() == false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800734 if (DBG) Slog.d(TAG, "special network not available");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700735 return Phone.APN_TYPE_NOT_AVAILABLE;
736 }
737
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700738 synchronized(this) {
739 mFeatureUsers.add(f);
740 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
741 // this gets used for per-pid dns when connected
742 mNetRequestersPids[usedNetworkType].add(currentPid);
743 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700744 }
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700745 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK,
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700746 f), getRestoreDefaultNetworkDelay());
747
Robert Greenwalt42acef32009-08-12 16:08:25 -0700748
Robert Greenwalta64bf832009-08-19 20:19:33 -0700749 if ((ni.isConnectedOrConnecting() == true) &&
750 !network.isTeardownRequested()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700751 if (ni.isConnected() == true) {
752 // add the pid-specific dns
Robert Greenwaltb738fb92010-08-13 14:16:12 -0700753 handleDnsConfigurationChange(networkType);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800754 if (DBG) Slog.d(TAG, "special network already active");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700755 return Phone.APN_ALREADY_ACTIVE;
756 }
Joe Onorato8a9b2202010-02-26 18:56:32 -0800757 if (DBG) Slog.d(TAG, "special network already connecting");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700758 return Phone.APN_REQUEST_STARTED;
759 }
760
761 // check if the radio in play can make another contact
762 // assume if cannot for now
763
Joe Onorato8a9b2202010-02-26 18:56:32 -0800764 if (DBG) Slog.d(TAG, "reconnecting to special network");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700765 network.reconnect();
766 return Phone.APN_REQUEST_STARTED;
767 } else {
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700768 synchronized(this) {
769 mFeatureUsers.add(f);
770 }
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700771 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK,
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700772 f), getRestoreDefaultNetworkDelay());
773
Robert Greenwalt42acef32009-08-12 16:08:25 -0700774 return network.startUsingNetworkFeature(feature,
775 getCallingPid(), getCallingUid());
776 }
777 }
778 return Phone.APN_TYPE_NOT_AVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 }
780
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700781 // javadoc from interface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 public int stopUsingNetworkFeature(int networkType, String feature) {
Robert Greenwaltb8f16342009-10-06 17:52:40 -0700783 enforceChangePermission();
784
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700785 int pid = getCallingPid();
786 int uid = getCallingUid();
787
788 FeatureUser u = null;
789 boolean found = false;
790
791 synchronized(this) {
792 for (int i = 0; i < mFeatureUsers.size() ; i++) {
793 u = (FeatureUser)mFeatureUsers.get(i);
794 if (uid == u.mUid && pid == u.mPid &&
795 networkType == u.mNetworkType &&
796 TextUtils.equals(feature, u.mFeature)) {
797 found = true;
798 break;
799 }
800 }
801 }
802 if (found && u != null) {
803 // stop regardless of how many other time this proc had called start
804 return stopUsingNetworkFeature(u, true);
805 } else {
806 // none found!
Joe Onorato8a9b2202010-02-26 18:56:32 -0800807 if (DBG) Slog.d(TAG, "ignoring stopUsingNetworkFeature - not a live request");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700808 return 1;
809 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700810 }
811
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700812 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
813 int networkType = u.mNetworkType;
814 String feature = u.mFeature;
815 int pid = u.mPid;
816 int uid = u.mUid;
817
818 NetworkStateTracker tracker = null;
819 boolean callTeardown = false; // used to carry our decision outside of sync block
820
Robert Greenwalt42acef32009-08-12 16:08:25 -0700821 if (DBG) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800822 Slog.d(TAG, "stopUsingNetworkFeature for net " + networkType +
Robert Greenwalt42acef32009-08-12 16:08:25 -0700823 ": " + feature);
824 }
Robert Greenwaltb8f16342009-10-06 17:52:40 -0700825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
827 return -1;
828 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700829
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700830 // need to link the mFeatureUsers list with the mNetRequestersPids state in this
831 // sync block
832 synchronized(this) {
833 // check if this process still has an outstanding start request
834 if (!mFeatureUsers.contains(u)) {
Robert Greenwalt78a640a2010-03-10 16:10:43 -0800835 if (DBG) Slog.d(TAG, "ignoring - this process has no outstanding requests");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700836 return 1;
837 }
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700838 u.unlinkDeathRecipient();
839 mFeatureUsers.remove(mFeatureUsers.indexOf(u));
840 // If we care about duplicate requests, check for that here.
841 //
842 // This is done to support the extension of a request - the app
843 // can request we start the network feature again and renew the
844 // auto-shutoff delay. Normal "stop" calls from the app though
845 // do not pay attention to duplicate requests - in effect the
846 // API does not refcount and a single stop will counter multiple starts.
847 if (ignoreDups == false) {
848 for (int i = 0; i < mFeatureUsers.size() ; i++) {
849 FeatureUser x = (FeatureUser)mFeatureUsers.get(i);
850 if (x.mUid == u.mUid && x.mPid == u.mPid &&
851 x.mNetworkType == u.mNetworkType &&
852 TextUtils.equals(x.mFeature, u.mFeature)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800853 if (DBG) Slog.d(TAG, "ignoring stopUsingNetworkFeature as dup is found");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700854 return 1;
855 }
856 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700857 }
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700858
859 // TODO - move to MobileDataStateTracker
860 int usedNetworkType = networkType;
861 if (networkType == ConnectivityManager.TYPE_MOBILE) {
862 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
863 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
864 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
865 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
866 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
867 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
868 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
869 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
870 }
871 }
872 tracker = mNetTrackers[usedNetworkType];
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700873 if (tracker == null) {
Robert Greenwalt78a640a2010-03-10 16:10:43 -0800874 if (DBG) Slog.d(TAG, "ignoring - no known tracker for net type " + usedNetworkType);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700875 return -1;
876 }
877 if (usedNetworkType != networkType) {
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700878 Integer currentPid = new Integer(pid);
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700879 mNetRequestersPids[usedNetworkType].remove(currentPid);
Robert Greenwalt421c72b2009-12-17 14:54:59 -0800880 reassessPidDns(pid, true);
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700881 if (mNetRequestersPids[usedNetworkType].size() != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800882 if (DBG) Slog.d(TAG, "not tearing down special network - " +
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700883 "others still using it");
884 return 1;
885 }
886 callTeardown = true;
887 }
888 }
Robert Greenwalt78a640a2010-03-10 16:10:43 -0800889 if (DBG) Slog.d(TAG, "Doing network teardown");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700890 if (callTeardown) {
891 tracker.teardown();
Robert Greenwalt42acef32009-08-12 16:08:25 -0700892 return 1;
893 } else {
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700894 // do it the old fashioned way
Robert Greenwalt42acef32009-08-12 16:08:25 -0700895 return tracker.stopUsingNetworkFeature(feature, pid, uid);
896 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 }
898
899 /**
900 * Ensure that a network route exists to deliver traffic to the specified
901 * host via the specified network interface.
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700902 * @param networkType the type of the network over which traffic to the
903 * specified host is to be routed
904 * @param hostAddress the IP address of the host to which the route is
905 * desired
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 * @return {@code true} on success, {@code false} on failure
907 */
908 public boolean requestRouteToHost(int networkType, int hostAddress) {
909 enforceChangePermission();
910 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
911 return false;
912 }
913 NetworkStateTracker tracker = mNetTrackers[networkType];
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700914
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700915 if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
916 tracker.isTeardownRequested()) {
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700917 if (DBG) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800918 Slog.d(TAG, "requestRouteToHost on down network (" + networkType + ") - dropped");
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700919 }
920 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 }
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700922 return tracker.requestRouteToHost(hostAddress);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 }
924
925 /**
926 * @see ConnectivityManager#getBackgroundDataSetting()
927 */
928 public boolean getBackgroundDataSetting() {
929 return Settings.Secure.getInt(mContext.getContentResolver(),
930 Settings.Secure.BACKGROUND_DATA, 1) == 1;
931 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 /**
934 * @see ConnectivityManager#setBackgroundDataSetting(boolean)
935 */
936 public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) {
937 mContext.enforceCallingOrSelfPermission(
938 android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
939 "ConnectivityService");
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700940
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700941 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA,
942 (allowBackgroundDataUsage ? ENABLED : DISABLED), 0));
943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700945 private void handleSetBackgroundData(boolean enabled) {
946 if (enabled != getBackgroundDataSetting()) {
947 Settings.Secure.putInt(mContext.getContentResolver(),
948 Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0);
949 Intent broadcast = new Intent(
950 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
951 mContext.sendBroadcast(broadcast);
952 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700953 }
954
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800955 /**
956 * @see ConnectivityManager#getMobileDataEnabled()
957 */
958 public boolean getMobileDataEnabled() {
959 enforceAccessPermission();
960 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
961 Settings.Secure.MOBILE_DATA, 1) == 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800962 if (DBG) Slog.d(TAG, "getMobileDataEnabled returning " + retVal);
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800963 return retVal;
964 }
965
966 /**
967 * @see ConnectivityManager#setMobileDataEnabled(boolean)
968 */
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700969 public void setMobileDataEnabled(boolean enabled) {
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800970 enforceChangePermission();
Joe Onorato8a9b2202010-02-26 18:56:32 -0800971 if (DBG) Slog.d(TAG, "setMobileDataEnabled(" + enabled + ")");
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800972
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700973 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
974 (enabled ? ENABLED : DISABLED), 0));
975 }
976
977 private void handleSetMobileData(boolean enabled) {
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800978 if (getMobileDataEnabled() == enabled) return;
979
980 Settings.Secure.putInt(mContext.getContentResolver(),
981 Settings.Secure.MOBILE_DATA, enabled ? 1 : 0);
982
983 if (enabled) {
984 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700985 if (DBG) {
986 Slog.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]);
987 }
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800988 mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect();
989 }
990 } else {
991 for (NetworkStateTracker nt : mNetTrackers) {
992 if (nt == null) continue;
993 int netType = nt.getNetworkInfo().getType();
994 if (mNetAttributes[netType].mRadio == ConnectivityManager.TYPE_MOBILE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800995 if (DBG) Slog.d(TAG, "tearing down " + nt);
Robert Greenwaltc03fa502010-02-23 18:58:05 -0800996 nt.teardown();
997 }
998 }
999 }
1000 }
1001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 private int getNumConnectedNetworks() {
1003 int numConnectedNets = 0;
1004
1005 for (NetworkStateTracker nt : mNetTrackers) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -07001006 if (nt != null && nt.getNetworkInfo().isConnected() &&
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001007 !nt.isTeardownRequested()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001008 ++numConnectedNets;
1009 }
1010 }
1011 return numConnectedNets;
1012 }
1013
1014 private void enforceAccessPermission() {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001015 mContext.enforceCallingOrSelfPermission(
1016 android.Manifest.permission.ACCESS_NETWORK_STATE,
1017 "ConnectivityService");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 }
1019
1020 private void enforceChangePermission() {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001021 mContext.enforceCallingOrSelfPermission(
1022 android.Manifest.permission.CHANGE_NETWORK_STATE,
1023 "ConnectivityService");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 }
1025
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001026 // TODO Make this a special check when it goes public
1027 private void enforceTetherChangePermission() {
1028 mContext.enforceCallingOrSelfPermission(
1029 android.Manifest.permission.CHANGE_NETWORK_STATE,
1030 "ConnectivityService");
1031 }
1032
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001033 private void enforceTetherAccessPermission() {
1034 mContext.enforceCallingOrSelfPermission(
1035 android.Manifest.permission.ACCESS_NETWORK_STATE,
1036 "ConnectivityService");
1037 }
1038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 /**
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001040 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
1041 * network, we ignore it. If it is for the active network, we send out a
1042 * broadcast. But first, we check whether it might be possible to connect
1043 * to a different network.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 * @param info the {@code NetworkInfo} for the network
1045 */
1046 private void handleDisconnect(NetworkInfo info) {
1047
Robert Greenwalt42acef32009-08-12 16:08:25 -07001048 int prevNetType = info.getType();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049
Robert Greenwalt42acef32009-08-12 16:08:25 -07001050 mNetTrackers[prevNetType].setTeardownRequested(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 /*
1052 * If the disconnected network is not the active one, then don't report
1053 * this as a loss of connectivity. What probably happened is that we're
1054 * getting the disconnect for a network that we explicitly disabled
1055 * in accordance with network preference policies.
1056 */
Robert Greenwalt42acef32009-08-12 16:08:25 -07001057 if (!mNetAttributes[prevNetType].isDefault()) {
1058 List pids = mNetRequestersPids[prevNetType];
1059 for (int i = 0; i<pids.size(); i++) {
1060 Integer pid = (Integer)pids.get(i);
1061 // will remove them because the net's no longer connected
1062 // need to do this now as only now do we know the pids and
1063 // can properly null things that are no longer referenced.
1064 reassessPidDns(pid.intValue(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 }
1067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1069 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1070 if (info.isFailover()) {
1071 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1072 info.setFailover(false);
1073 }
1074 if (info.getReason() != null) {
1075 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1076 }
1077 if (info.getExtraInfo() != null) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001078 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1079 info.getExtraInfo());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001081
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001082 if (mNetAttributes[prevNetType].isDefault()) {
Robert Greenwalt6b099162011-03-10 16:58:31 -08001083 tryFailover(prevNetType);
1084 if (mActiveDefaultNetwork != -1) {
1085 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001086 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1087 } else {
Robert Greenwalt029be812010-09-20 18:01:43 -07001088 mDefaultInetConditionPublished = 0; // we're not connected anymore
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001089 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1090 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001091 }
Robert Greenwalt029be812010-09-20 18:01:43 -07001092 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001093 // do this before we broadcast the change
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001094 handleConnectivityChange(prevNetType);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001095
1096 sendStickyBroadcast(intent);
1097 /*
1098 * If the failover network is already connected, then immediately send
1099 * out a followup broadcast indicating successful failover
1100 */
Robert Greenwalt6b099162011-03-10 16:58:31 -08001101 if (mActiveDefaultNetwork != -1) {
1102 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001103 }
1104 }
1105
Robert Greenwalt6b099162011-03-10 16:58:31 -08001106 private void tryFailover(int prevNetType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001107 /*
1108 * If this is a default network, check if other defaults are available
1109 * or active
1110 */
Robert Greenwalt42acef32009-08-12 16:08:25 -07001111 if (mNetAttributes[prevNetType].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001112 if (mActiveDefaultNetwork == prevNetType) {
1113 mActiveDefaultNetwork = -1;
1114 }
1115
Robert Greenwalt35429592010-02-25 12:04:29 -08001116 boolean noMobileData = !getMobileDataEnabled();
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001117 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -07001118 if (checkType == prevNetType) continue;
1119 if (mNetAttributes[checkType] == null) continue;
Robert Greenwalt7e62fd12011-02-11 17:32:58 -08001120 if (mNetAttributes[checkType].isDefault() == false) continue;
Robert Greenwalt35429592010-02-25 12:04:29 -08001121 if (mNetAttributes[checkType].mRadio == ConnectivityManager.TYPE_MOBILE &&
1122 noMobileData) {
Robert Greenwalt572172b2010-10-08 16:35:52 -07001123 Slog.e(TAG, "not failing over to mobile type " + checkType +
1124 " because Mobile Data Disabled");
Robert Greenwalt35429592010-02-25 12:04:29 -08001125 continue;
1126 }
Robert Greenwalt6b099162011-03-10 16:58:31 -08001127 NetworkStateTracker checkTracker = mNetTrackers[checkType];
1128 NetworkInfo checkInfo = checkTracker.getNetworkInfo();
1129 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
1130 checkInfo.setFailover(true);
1131 checkTracker.reconnect();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 }
Robert Greenwalt6b099162011-03-10 16:58:31 -08001133 if (DBG) Slog.d(TAG, "Attempting to switch to " + checkInfo.getTypeName());
Robert Greenwalt42acef32009-08-12 16:08:25 -07001134 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 }
1137
1138 private void sendConnectedBroadcast(NetworkInfo info) {
Robert Greenwalt1e9aac22010-09-15 17:36:33 -07001139 sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION);
1140 }
1141
1142 private void sendInetConditionBroadcast(NetworkInfo info) {
1143 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1144 }
1145
1146 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1147 Intent intent = new Intent(bcastType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1149 if (info.isFailover()) {
1150 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1151 info.setFailover(false);
1152 }
1153 if (info.getReason() != null) {
1154 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1155 }
1156 if (info.getExtraInfo() != null) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001157 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1158 info.getExtraInfo());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 }
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001160 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001161 sendStickyBroadcast(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 }
1163
1164 /**
1165 * Called when an attempt to fail over to another network has failed.
1166 * @param info the {@link NetworkInfo} for the failed network
1167 */
1168 private void handleConnectionFailure(NetworkInfo info) {
1169 mNetTrackers[info.getType()].setTeardownRequested(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170
Robert Greenwalt42acef32009-08-12 16:08:25 -07001171 String reason = info.getReason();
1172 String extraInfo = info.getExtraInfo();
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001173
Robert Greenwalt572172b2010-10-08 16:35:52 -07001174 String reasonText;
1175 if (reason == null) {
1176 reasonText = ".";
1177 } else {
1178 reasonText = " (" + reason + ").";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 }
Robert Greenwalt572172b2010-10-08 16:35:52 -07001180 Slog.e(TAG, "Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001181
1182 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1183 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1184 if (getActiveNetworkInfo() == null) {
1185 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1186 }
1187 if (reason != null) {
1188 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
1189 }
1190 if (extraInfo != null) {
1191 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
1192 }
1193 if (info.isFailover()) {
1194 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1195 info.setFailover(false);
1196 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001197
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001198 if (mNetAttributes[info.getType()].isDefault()) {
Robert Greenwalt6b099162011-03-10 16:58:31 -08001199 tryFailover(info.getType());
1200 if (mActiveDefaultNetwork != -1) {
1201 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001202 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1203 } else {
Robert Greenwalt029be812010-09-20 18:01:43 -07001204 mDefaultInetConditionPublished = 0;
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001205 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1206 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001207 }
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001208
Robert Greenwalt029be812010-09-20 18:01:43 -07001209 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001210 sendStickyBroadcast(intent);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001211 /*
1212 * If the failover network is already connected, then immediately send
1213 * out a followup broadcast indicating successful failover
1214 */
Robert Greenwalt6b099162011-03-10 16:58:31 -08001215 if (mActiveDefaultNetwork != -1) {
1216 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001217 }
Mike Lockwood0f79b542009-08-14 14:18:49 -04001218 }
1219
1220 private void sendStickyBroadcast(Intent intent) {
1221 synchronized(this) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001222 if (!mSystemReady) {
1223 mInitialBroadcast = new Intent(intent);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001224 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001225 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1226 mContext.sendStickyBroadcast(intent);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001227 }
1228 }
1229
1230 void systemReady() {
1231 synchronized(this) {
1232 mSystemReady = true;
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001233 if (mInitialBroadcast != null) {
1234 mContext.sendStickyBroadcast(mInitialBroadcast);
1235 mInitialBroadcast = null;
Mike Lockwood0f79b542009-08-14 14:18:49 -04001236 }
1237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 }
1239
1240 private void handleConnect(NetworkInfo info) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001241 int type = info.getType();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242
1243 // snapshot isFailover, because sendConnectedBroadcast() resets it
1244 boolean isFailover = info.isFailover();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001245 NetworkStateTracker thisNet = mNetTrackers[type];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001246
Robert Greenwalt42acef32009-08-12 16:08:25 -07001247 // if this is a default net and other default is running
1248 // kill the one not preferred
1249 if (mNetAttributes[type].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001250 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
1251 if ((type != mNetworkPreference &&
1252 mNetAttributes[mActiveDefaultNetwork].mPriority >
1253 mNetAttributes[type].mPriority) ||
1254 mNetworkPreference == mActiveDefaultNetwork) {
1255 // don't accept this one
Joe Onorato8a9b2202010-02-26 18:56:32 -08001256 if (DBG) Slog.v(TAG, "Not broadcasting CONNECT_ACTION " +
Robert Greenwalt42acef32009-08-12 16:08:25 -07001257 "to torn down network " + info.getTypeName());
1258 teardown(thisNet);
1259 return;
1260 } else {
1261 // tear down the other
1262 NetworkStateTracker otherNet =
1263 mNetTrackers[mActiveDefaultNetwork];
Joe Onorato8a9b2202010-02-26 18:56:32 -08001264 if (DBG) Slog.v(TAG, "Policy requires " +
Robert Greenwalt42acef32009-08-12 16:08:25 -07001265 otherNet.getNetworkInfo().getTypeName() +
1266 " teardown");
1267 if (!teardown(otherNet)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001268 Slog.e(TAG, "Network declined teardown request");
Robert Greenwalt27725e82011-03-29 11:36:28 -07001269 teardown(thisNet);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001270 return;
1271 }
1272 if (isFailover) {
1273 otherNet.releaseWakeLock();
1274 }
1275 }
1276 }
1277 mActiveDefaultNetwork = type;
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001278 // this will cause us to come up initially as unconnected and switching
1279 // to connected after our normal pause unless somebody reports us as reall
1280 // disconnected
1281 mDefaultInetConditionPublished = 0;
1282 mDefaultConnectionSequence++;
1283 mInetConditionChangeInFlight = false;
1284 // Don't do this - if we never sign in stay, grey
1285 //reportNetworkCondition(mActiveDefaultNetwork, 100);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 thisNet.setTeardownRequested(false);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001288 thisNet.updateNetworkSettings();
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001289 handleConnectivityChange(type);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001290 sendConnectedBroadcast(info);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 }
1292
1293 private void handleScanResultsAvailable(NetworkInfo info) {
1294 int networkType = info.getType();
1295 if (networkType != ConnectivityManager.TYPE_WIFI) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001296 if (DBG) Slog.v(TAG, "Got ScanResultsAvailable for " +
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001297 info.getTypeName() + " network. Don't know how to handle.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001300 mNetTrackers[networkType].interpretScanResultsAvailable();
1301 }
1302
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001303 private void handleNotificationChange(boolean visible, int id,
1304 Notification notification) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001305 NotificationManager notificationManager = (NotificationManager) mContext
1306 .getSystemService(Context.NOTIFICATION_SERVICE);
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001308 if (visible) {
1309 notificationManager.notify(id, notification);
1310 } else {
1311 notificationManager.cancel(id);
1312 }
1313 }
1314
1315 /**
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001316 * After a change in the connectivity state of any network, We're mainly
1317 * concerned with making sure that the list of DNS servers is setupup
1318 * according to which networks are connected, and ensuring that the
1319 * right routing table entries exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320 */
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001321 private void handleConnectivityChange(int netType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001322 /*
Robert Greenwalt42acef32009-08-12 16:08:25 -07001323 * If a non-default network is enabled, add the host routes that
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001324 * will allow it's DNS servers to be accessed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325 */
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001326 handleDnsConfigurationChange(netType);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001327
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001328 if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
1329 if (mNetAttributes[netType].isDefault()) {
1330 mNetTrackers[netType].addDefaultRoute();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001331 } else {
Robert Greenwalt7cf5b412011-03-24 21:41:41 -07001332 // many radios add a default route even when we don't want one.
1333 // remove the default interface unless we need it for our active network
1334 if (mActiveDefaultNetwork != -1) {
1335 String defaultIface = mNetTrackers[mActiveDefaultNetwork].getInterfaceName();
1336 if (defaultIface != null &&
1337 !defaultIface.equals(mNetTrackers[netType].getInterfaceName())) {
1338 mNetTrackers[netType].removeDefaultRoute();
1339 }
1340 }
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001341 mNetTrackers[netType].addPrivateDnsRoutes();
1342 }
1343 } else {
1344 if (mNetAttributes[netType].isDefault()) {
1345 mNetTrackers[netType].removeDefaultRoute();
1346 } else {
1347 mNetTrackers[netType].removePrivateDnsRoutes();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 }
1350 }
1351
Robert Greenwalt42acef32009-08-12 16:08:25 -07001352 /**
1353 * Adjust the per-process dns entries (net.dns<x>.<pid>) based
1354 * on the highest priority active net which this process requested.
1355 * If there aren't any, clear it out
1356 */
1357 private void reassessPidDns(int myPid, boolean doBump)
1358 {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001359 if (DBG) Slog.d(TAG, "reassessPidDns for pid " + myPid);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001360 for(int i : mPriorityList) {
1361 if (mNetAttributes[i].isDefault()) {
1362 continue;
1363 }
1364 NetworkStateTracker nt = mNetTrackers[i];
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001365 if (nt.getNetworkInfo().isConnected() &&
1366 !nt.isTeardownRequested()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001367 List pids = mNetRequestersPids[i];
1368 for (int j=0; j<pids.size(); j++) {
1369 Integer pid = (Integer)pids.get(j);
1370 if (pid.intValue() == myPid) {
1371 String[] dnsList = nt.getNameServers();
1372 writePidDns(dnsList, myPid);
1373 if (doBump) {
1374 bumpDns();
1375 }
1376 return;
1377 }
1378 }
1379 }
1380 }
1381 // nothing found - delete
1382 for (int i = 1; ; i++) {
1383 String prop = "net.dns" + i + "." + myPid;
1384 if (SystemProperties.get(prop).length() == 0) {
1385 if (doBump) {
1386 bumpDns();
1387 }
1388 return;
1389 }
1390 SystemProperties.set(prop, "");
1391 }
1392 }
1393
1394 private void writePidDns(String[] dnsList, int pid) {
1395 int j = 1;
1396 for (String dns : dnsList) {
1397 if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
1398 SystemProperties.set("net.dns" + j++ + "." + pid, dns);
1399 }
1400 }
1401 }
1402
1403 private void bumpDns() {
1404 /*
1405 * Bump the property that tells the name resolver library to reread
1406 * the DNS server list from the properties.
1407 */
1408 String propVal = SystemProperties.get("net.dnschange");
1409 int n = 0;
1410 if (propVal.length() != 0) {
1411 try {
1412 n = Integer.parseInt(propVal);
1413 } catch (NumberFormatException e) {}
1414 }
1415 SystemProperties.set("net.dnschange", "" + (n+1));
1416 }
1417
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001418 private void handleDnsConfigurationChange(int netType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001419 // add default net's dns entries
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001420 NetworkStateTracker nt = mNetTrackers[netType];
1421 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
1422 String[] dnsList = nt.getNameServers();
1423 if (mNetAttributes[netType].isDefault()) {
1424 int j = 1;
1425 for (String dns : dnsList) {
1426 if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
1427 if (DBG) {
1428 Slog.d(TAG, "adding dns " + dns + " for " +
1429 nt.getNetworkInfo().getTypeName());
Robert Greenwalt42acef32009-08-12 16:08:25 -07001430 }
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001431 SystemProperties.set("net.dns" + j++, dns);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001432 }
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001433 }
1434 for (int k=j ; k<mNumDnsEntries; k++) {
1435 if (DBG) Slog.d(TAG, "erasing net.dns" + k);
1436 SystemProperties.set("net.dns" + k, "");
1437 }
1438 mNumDnsEntries = j;
1439 } else {
1440 // set per-pid dns for attached secondary nets
1441 List pids = mNetRequestersPids[netType];
1442 for (int y=0; y< pids.size(); y++) {
1443 Integer pid = (Integer)pids.get(y);
1444 writePidDns(dnsList, pid.intValue());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 }
1446 }
1447 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001448 bumpDns();
1449 }
1450
1451 private int getRestoreDefaultNetworkDelay() {
1452 String restoreDefaultNetworkDelayStr = SystemProperties.get(
1453 NETWORK_RESTORE_DELAY_PROP_NAME);
1454 if(restoreDefaultNetworkDelayStr != null &&
1455 restoreDefaultNetworkDelayStr.length() != 0) {
1456 try {
1457 return Integer.valueOf(restoreDefaultNetworkDelayStr);
1458 } catch (NumberFormatException e) {
1459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001461 return RESTORE_DEFAULT_NETWORK_DELAY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 }
1463
1464 @Override
1465 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001466 if (mContext.checkCallingOrSelfPermission(
1467 android.Manifest.permission.DUMP)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001468 != PackageManager.PERMISSION_GRANTED) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001469 pw.println("Permission Denial: can't dump ConnectivityService " +
1470 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1471 Binder.getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 return;
1473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 pw.println();
1475 for (NetworkStateTracker nst : mNetTrackers) {
Robert Greenwaltb9285352009-12-21 18:24:07 -08001476 if (nst != null) {
1477 if (nst.getNetworkInfo().isConnected()) {
1478 pw.println("Active network: " + nst.getNetworkInfo().
1479 getTypeName());
1480 }
1481 pw.println(nst.getNetworkInfo());
1482 pw.println(nst);
1483 pw.println();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 }
Robert Greenwaltb9285352009-12-21 18:24:07 -08001486
1487 pw.println("Network Requester Pids:");
1488 for (int net : mPriorityList) {
1489 String pidString = net + ": ";
1490 for (Object pid : mNetRequestersPids[net]) {
1491 pidString = pidString + pid.toString() + ", ";
1492 }
1493 pw.println(pidString);
1494 }
1495 pw.println();
1496
1497 pw.println("FeatureUsers:");
1498 for (Object requester : mFeatureUsers) {
1499 pw.println(requester.toString());
1500 }
1501 pw.println();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001502
1503 mTethering.dump(fd, pw, args);
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -07001504
1505 if (mInetLog != null) {
1506 pw.println();
1507 pw.println("Inet condition reports:");
1508 for(int i = 0; i < mInetLog.size(); i++) {
1509 pw.println(mInetLog.get(i));
1510 }
1511 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 }
1513
Robert Greenwalt42acef32009-08-12 16:08:25 -07001514 // must be stateless - things change under us.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 private class MyHandler extends Handler {
1516 @Override
1517 public void handleMessage(Message msg) {
1518 NetworkInfo info;
1519 switch (msg.what) {
1520 case NetworkStateTracker.EVENT_STATE_CHANGED:
1521 info = (NetworkInfo) msg.obj;
Robert Greenwalt511288a2009-12-07 11:33:18 -08001522 int type = info.getType();
1523 NetworkInfo.State state = info.getState();
Robert Greenwalt6e6dec22010-01-25 16:14:00 -08001524 // only do this optimization for wifi. It going into scan mode for location
1525 // services generates alot of noise. Meanwhile the mms apn won't send out
1526 // subsequent notifications when on default cellular because it never
1527 // disconnects.. so only do this to wifi notifications. Fixed better when the
1528 // APN notifications are standardized.
1529 if (mNetAttributes[type].mLastState == state &&
1530 mNetAttributes[type].mRadio == ConnectivityManager.TYPE_WIFI) {
Robert Greenwalt511288a2009-12-07 11:33:18 -08001531 if (DBG) {
Robert Greenwalt6e6dec22010-01-25 16:14:00 -08001532 // TODO - remove this after we validate the dropping doesn't break
1533 // anything
Joe Onorato8a9b2202010-02-26 18:56:32 -08001534 Slog.d(TAG, "Dropping ConnectivityChange for " +
Robert Greenwalt1193ae42010-01-13 09:36:31 -08001535 info.getTypeName() + ": " +
Robert Greenwalt511288a2009-12-07 11:33:18 -08001536 state + "/" + info.getDetailedState());
1537 }
1538 return;
1539 }
1540 mNetAttributes[type].mLastState = state;
1541
Joe Onorato8a9b2202010-02-26 18:56:32 -08001542 if (DBG) Slog.d(TAG, "ConnectivityChange for " +
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001543 info.getTypeName() + ": " +
Robert Greenwalt511288a2009-12-07 11:33:18 -08001544 state + "/" + info.getDetailedState());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545
1546 // Connectivity state changed:
1547 // [31-13] Reserved for future use
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001548 // [12-9] Network subtype (for mobile network, as defined
1549 // by TelephonyManager)
1550 // [8-3] Detailed state ordinal (as defined by
1551 // NetworkInfo.DetailedState)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 // [2-0] Network type (as defined by ConnectivityManager)
1553 int eventLogParam = (info.getType() & 0x7) |
1554 ((info.getDetailedState().ordinal() & 0x3f) << 3) |
1555 (info.getSubtype() << 9);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001556 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001557 eventLogParam);
1558
1559 if (info.getDetailedState() ==
1560 NetworkInfo.DetailedState.FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 handleConnectionFailure(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001562 } else if (state == NetworkInfo.State.DISCONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 handleDisconnect(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001564 } else if (state == NetworkInfo.State.SUSPENDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 // TODO: need to think this over.
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001566 // the logic here is, handle SUSPENDED the same as
1567 // DISCONNECTED. The only difference being we are
1568 // broadcasting an intent with NetworkInfo that's
1569 // suspended. This allows the applications an
1570 // opportunity to handle DISCONNECTED and SUSPENDED
1571 // differently, or not.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 handleDisconnect(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001573 } else if (state == NetworkInfo.State.CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 handleConnect(info);
1575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 break;
1577
1578 case NetworkStateTracker.EVENT_SCAN_RESULTS_AVAILABLE:
1579 info = (NetworkInfo) msg.obj;
1580 handleScanResultsAvailable(info);
1581 break;
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 case NetworkStateTracker.EVENT_NOTIFICATION_CHANGED:
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001584 handleNotificationChange(msg.arg1 == 1, msg.arg2,
1585 (Notification) msg.obj);
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001586 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587
1588 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
Robert Greenwaltb738fb92010-08-13 14:16:12 -07001589 info = (NetworkInfo) msg.obj;
1590 type = info.getType();
1591 handleDnsConfigurationChange(type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 break;
1593
1594 case NetworkStateTracker.EVENT_ROAMING_CHANGED:
1595 // fill me in
1596 break;
1597
1598 case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED:
1599 // fill me in
1600 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001601 case EVENT_RESTORE_DEFAULT_NETWORK:
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -07001602 FeatureUser u = (FeatureUser)msg.obj;
1603 u.expire();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001604 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001605 case EVENT_INET_CONDITION_CHANGE:
1606 {
1607 int netType = msg.arg1;
1608 int condition = msg.arg2;
1609 handleInetConditionChange(netType, condition);
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001610 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001611 }
1612 case EVENT_INET_CONDITION_HOLD_END:
1613 {
1614 int netType = msg.arg1;
1615 int sequence = msg.arg2;
1616 handleInetConditionHoldEnd(netType, sequence);
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001617 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001618 }
1619 case EVENT_SET_NETWORK_PREFERENCE:
1620 {
1621 int preference = msg.arg1;
1622 handleSetNetworkPreference(preference);
1623 break;
1624 }
1625 case EVENT_SET_BACKGROUND_DATA:
1626 {
1627 boolean enabled = (msg.arg1 == ENABLED);
1628 handleSetBackgroundData(enabled);
1629 break;
1630 }
1631 case EVENT_SET_MOBILE_DATA:
1632 {
1633 boolean enabled = (msg.arg1 == ENABLED);
1634 handleSetMobileData(enabled);
1635 break;
1636 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 }
1638 }
1639 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001640
1641 // javadoc from interface
Robert Greenwalt5a735062010-03-02 17:25:02 -08001642 public int tether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001643 enforceTetherChangePermission();
Robert Greenwalt5a735062010-03-02 17:25:02 -08001644
1645 if (isTetheringSupported()) {
1646 return mTethering.tether(iface);
1647 } else {
1648 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1649 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001650 }
1651
1652 // javadoc from interface
Robert Greenwalt5a735062010-03-02 17:25:02 -08001653 public int untether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001654 enforceTetherChangePermission();
Robert Greenwalt5a735062010-03-02 17:25:02 -08001655
1656 if (isTetheringSupported()) {
1657 return mTethering.untether(iface);
1658 } else {
1659 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1660 }
1661 }
1662
1663 // javadoc from interface
1664 public int getLastTetherError(String iface) {
1665 enforceTetherAccessPermission();
1666
1667 if (isTetheringSupported()) {
1668 return mTethering.getLastTetherError(iface);
1669 } else {
1670 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1671 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001672 }
1673
1674 // TODO - proper iface API for selection by property, inspection, etc
1675 public String[] getTetherableUsbRegexs() {
1676 enforceTetherAccessPermission();
1677 if (isTetheringSupported()) {
1678 return mTethering.getTetherableUsbRegexs();
1679 } else {
1680 return new String[0];
1681 }
1682 }
1683
1684 public String[] getTetherableWifiRegexs() {
1685 enforceTetherAccessPermission();
1686 if (isTetheringSupported()) {
1687 return mTethering.getTetherableWifiRegexs();
1688 } else {
1689 return new String[0];
1690 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001691 }
1692
1693 // TODO - move iface listing, queries, etc to new module
1694 // javadoc from interface
1695 public String[] getTetherableIfaces() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001696 enforceTetherAccessPermission();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001697 return mTethering.getTetherableIfaces();
1698 }
1699
1700 public String[] getTetheredIfaces() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001701 enforceTetherAccessPermission();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001702 return mTethering.getTetheredIfaces();
1703 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001704
Robert Greenwalt5a735062010-03-02 17:25:02 -08001705 public String[] getTetheringErroredIfaces() {
1706 enforceTetherAccessPermission();
1707 return mTethering.getErroredIfaces();
1708 }
1709
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001710 // if ro.tether.denied = true we default to no tethering
1711 // gservices could set the secure setting to 1 though to enable it on a build where it
1712 // had previously been turned off.
1713 public boolean isTetheringSupported() {
1714 enforceTetherAccessPermission();
1715 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001716 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
1717 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
1718 return tetherEnabledInSettings && mTetheringConfigValid;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001719 }
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001720
1721 // 100 percent is full good, 0 is full bad.
1722 public void reportInetCondition(int networkType, int percentage) {
1723 if (DBG) Slog.d(TAG, "reportNetworkCondition(" + networkType + ", " + percentage + ")");
1724 mContext.enforceCallingOrSelfPermission(
1725 android.Manifest.permission.STATUS_BAR,
1726 "ConnectivityService");
1727
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -07001728 if (DBG) {
1729 int pid = getCallingPid();
1730 int uid = getCallingUid();
1731 String s = pid + "(" + uid + ") reports inet is " +
1732 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
1733 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
1734 mInetLog.add(s);
1735 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
1736 mInetLog.remove(0);
1737 }
1738 }
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001739 mHandler.sendMessage(mHandler.obtainMessage(
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001740 EVENT_INET_CONDITION_CHANGE, networkType, percentage));
1741 }
1742
1743 private void handleInetConditionChange(int netType, int condition) {
1744 if (DBG) {
1745 Slog.d(TAG, "Inet connectivity change, net=" +
1746 netType + ", condition=" + condition +
1747 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
1748 }
1749 if (mActiveDefaultNetwork == -1) {
1750 if (DBG) Slog.d(TAG, "no active default network - aborting");
1751 return;
1752 }
1753 if (mActiveDefaultNetwork != netType) {
1754 if (DBG) Slog.d(TAG, "given net not default - aborting");
1755 return;
1756 }
1757 mDefaultInetCondition = condition;
1758 int delay;
1759 if (mInetConditionChangeInFlight == false) {
1760 if (DBG) Slog.d(TAG, "starting a change hold");
1761 // setup a new hold to debounce this
1762 if (mDefaultInetCondition > 50) {
1763 delay = Settings.Secure.getInt(mContext.getContentResolver(),
1764 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
1765 } else {
1766 delay = Settings.Secure.getInt(mContext.getContentResolver(),
1767 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
1768 }
1769 mInetConditionChangeInFlight = true;
1770 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
1771 mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
1772 } else {
1773 // we've set the new condition, when this hold ends that will get
1774 // picked up
1775 if (DBG) Slog.d(TAG, "currently in hold - not setting new end evt");
1776 }
1777 }
1778
1779 private void handleInetConditionHoldEnd(int netType, int sequence) {
1780 if (DBG) {
1781 Slog.d(TAG, "Inet hold end, net=" + netType +
1782 ", condition =" + mDefaultInetCondition +
1783 ", published condition =" + mDefaultInetConditionPublished);
1784 }
1785 mInetConditionChangeInFlight = false;
1786
1787 if (mActiveDefaultNetwork == -1) {
1788 if (DBG) Slog.d(TAG, "no active default network - aborting");
1789 return;
1790 }
1791 if (mDefaultConnectionSequence != sequence) {
1792 if (DBG) Slog.d(TAG, "event hold for obsolete network - aborting");
1793 return;
1794 }
1795 if (mDefaultInetConditionPublished == mDefaultInetCondition) {
1796 if (DBG) Slog.d(TAG, "no change in condition - aborting");
1797 return;
1798 }
1799 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
1800 if (networkInfo.isConnected() == false) {
1801 if (DBG) Slog.d(TAG, "default network not connected - aborting");
1802 return;
1803 }
1804 mDefaultInetConditionPublished = mDefaultInetCondition;
1805 sendInetConditionBroadcast(networkInfo);
1806 return;
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808}