blob: 4145854da2d097ae6fb91601feefd48a0819bbf0 [file] [log] [blame]
The Android Open Source Project28527d22009-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 Project28527d22009-03-03 19:31:44 -080021import android.content.Context;
TK MUN141623d2011-02-23 18:55:55 +090022import android.content.ContentResolver;
23import android.content.ContextWrapper;
The Android Open Source Project28527d22009-03-03 19:31:44 -080024import android.content.Intent;
25import android.content.pm.PackageManager;
TK MUN141623d2011-02-23 18:55:55 +090026import android.content.res.Resources;
27import android.content.res.Resources.NotFoundException;
The Android Open Source Project28527d22009-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;
Banavathu, Srinivas Naik7601f572010-08-10 20:13:53 +053033import android.net.NetworkUtils;
The Android Open Source Project28527d22009-03-03 19:31:44 -080034import android.net.wifi.WifiStateTracker;
TK MUN141623d2011-02-23 18:55:55 +090035import android.net.wimax.WimaxManagerConstants;
The Android Open Source Project28527d22009-03-03 19:31:44 -080036import android.os.Binder;
37import android.os.Handler;
Robert Greenwalt2034b912009-08-12 16:08:25 -070038import android.os.IBinder;
The Android Open Source Project28527d22009-03-03 19:31:44 -080039import android.os.Looper;
40import android.os.Message;
Robert Greenwalt2034b912009-08-12 16:08:25 -070041import android.os.RemoteException;
The Android Open Source Project28527d22009-03-03 19:31:44 -080042import android.os.ServiceManager;
43import android.os.SystemProperties;
44import android.provider.Settings;
Robert Greenwalt2034b912009-08-12 16:08:25 -070045import android.text.TextUtils;
The Android Open Source Project28527d22009-03-03 19:31:44 -080046import android.util.EventLog;
Joe Onoratoc2386bb2010-02-26 18:56:32 -080047import android.util.Slog;
Robert Greenwalt2034b912009-08-12 16:08:25 -070048import com.android.internal.telephony.Phone;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080049import com.android.server.connectivity.Tethering;
TK MUN141623d2011-02-23 18:55:55 +090050import dalvik.system.DexClassLoader;
The Android Open Source Project28527d22009-03-03 19:31:44 -080051import java.io.FileDescriptor;
52import java.io.PrintWriter;
TK MUN141623d2011-02-23 18:55:55 +090053import java.lang.reflect.Constructor;
54import java.lang.reflect.Method;
55import java.lang.reflect.Modifier;
56import java.lang.reflect.InvocationTargetException;
Robert Greenwalt2034b912009-08-12 16:08:25 -070057import java.util.ArrayList;
Robert Greenwalt0e80be12010-09-20 14:35:25 -070058import java.util.GregorianCalendar;
Robert Greenwalt2034b912009-08-12 16:08:25 -070059import java.util.List;
Banavathu, Srinivas Naik7601f572010-08-10 20:13:53 +053060import java.net.InetAddress;
61import java.net.UnknownHostException;
The Android Open Source Project28527d22009-03-03 19:31:44 -080062
TK MUN141623d2011-02-23 18:55:55 +090063
64
The Android Open Source Project28527d22009-03-03 19:31:44 -080065/**
66 * @hide
67 */
68public class ConnectivityService extends IConnectivityManager.Stub {
69
Dianne Hackborn8919f5a2010-09-30 18:27:22 -070070 private static final boolean DBG = false;
The Android Open Source Project28527d22009-03-03 19:31:44 -080071 private static final String TAG = "ConnectivityService";
72
Robert Greenwalt2034b912009-08-12 16:08:25 -070073 // how long to wait before switching back to a radio's default network
74 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
75 // system property that can override the above value
76 private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
77 "android.telephony.apn-restore";
78
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080079
80 private Tethering mTethering;
Robert Greenwaltf1b66e12010-02-25 12:29:30 -080081 private boolean mTetheringConfigValid = false;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080082
The Android Open Source Project28527d22009-03-03 19:31:44 -080083 /**
84 * Sometimes we want to refer to the individual network state
85 * trackers separately, and sometimes we just want to treat them
86 * abstractly.
87 */
88 private NetworkStateTracker mNetTrackers[];
Robert Greenwalt2034b912009-08-12 16:08:25 -070089
90 /**
91 * A per Net list of the PID's that requested access to the net
92 * used both as a refcount and for per-PID DNS selection
93 */
94 private List mNetRequestersPids[];
95
Robert Greenwalt2034b912009-08-12 16:08:25 -070096 // priority order of the nettrackers
97 // (excluding dynamically set mNetworkPreference)
98 // TODO - move mNetworkTypePreference into this
99 private int[] mPriorityList;
100
The Android Open Source Project28527d22009-03-03 19:31:44 -0800101 private Context mContext;
102 private int mNetworkPreference;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700103 private int mActiveDefaultNetwork = -1;
Robert Greenwalt986c7412010-09-08 15:24:47 -0700104 // 0 is full bad, 100 is full good
105 private int mDefaultInetCondition = 0;
106 private int mDefaultInetConditionPublished = 0;
107 private boolean mInetConditionChangeInFlight = false;
108 private int mDefaultConnectionSequence = 0;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800109
110 private int mNumDnsEntries;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800111
112 private boolean mTestMode;
113 private static ConnectivityService sServiceInstance;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700114 private static final int ENABLED = 1;
115 private static final int DISABLED = 0;
116
117 // Share the event space with NetworkStateTracker (which can't see this
118 // internal class but sends us events). If you change these, change
119 // NetworkStateTracker.java too.
120 private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1;
121 private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100;
122
123 /**
124 * used internally as a delayed event to make us switch back to the
125 * default network
126 */
127 private static final int EVENT_RESTORE_DEFAULT_NETWORK =
128 MAX_NETWORK_STATE_TRACKER_EVENT + 1;
129
130 /**
131 * used internally to change our mobile data enabled flag
132 */
133 private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED =
134 MAX_NETWORK_STATE_TRACKER_EVENT + 2;
135
136 /**
137 * used internally to change our network preference setting
138 * arg1 = networkType to prefer
139 */
140 private static final int EVENT_SET_NETWORK_PREFERENCE =
141 MAX_NETWORK_STATE_TRACKER_EVENT + 3;
142
143 /**
144 * used internally to synchronize inet condition reports
145 * arg1 = networkType
146 * arg2 = condition (0 bad, 100 good)
147 */
148 private static final int EVENT_INET_CONDITION_CHANGE =
149 MAX_NETWORK_STATE_TRACKER_EVENT + 4;
150
151 /**
152 * used internally to mark the end of inet condition hold periods
153 * arg1 = networkType
154 */
155 private static final int EVENT_INET_CONDITION_HOLD_END =
156 MAX_NETWORK_STATE_TRACKER_EVENT + 5;
157
158 /**
159 * used internally to set the background data preference
160 * arg1 = TRUE for enabled, FALSE for disabled
161 */
162 private static final int EVENT_SET_BACKGROUND_DATA =
163 MAX_NETWORK_STATE_TRACKER_EVENT + 6;
164
165 /**
166 * used internally to set enable/disable cellular data
167 * arg1 = ENBALED or DISABLED
168 */
169 private static final int EVENT_SET_MOBILE_DATA =
170 MAX_NETWORK_STATE_TRACKER_EVENT + 7;
171
Robert Greenwalt2034b912009-08-12 16:08:25 -0700172 private Handler mHandler;
173
174 // list of DeathRecipients used to make sure features are turned off when
175 // a process dies
176 private List mFeatureUsers;
177
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400178 private boolean mSystemReady;
Dianne Hackborna417ff82009-12-08 19:45:14 -0800179 private Intent mInitialBroadcast;
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400180
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700181 // used in DBG mode to track inet condition reports
182 private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
183 private ArrayList mInetLog;
184
Robert Greenwalt12c44552009-12-07 11:33:18 -0800185 private static class NetworkAttributes {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700186 /**
187 * Class for holding settings read from resources.
188 */
189 public String mName;
190 public int mType;
191 public int mRadio;
192 public int mPriority;
Robert Greenwalt12c44552009-12-07 11:33:18 -0800193 public NetworkInfo.State mLastState;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700194 public NetworkAttributes(String init) {
195 String fragments[] = init.split(",");
196 mName = fragments[0].toLowerCase();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700197 mType = Integer.parseInt(fragments[1]);
198 mRadio = Integer.parseInt(fragments[2]);
199 mPriority = Integer.parseInt(fragments[3]);
Robert Greenwalt12c44552009-12-07 11:33:18 -0800200 mLastState = NetworkInfo.State.UNKNOWN;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700201 }
202 public boolean isDefault() {
203 return (mType == mRadio);
204 }
205 }
206 NetworkAttributes[] mNetAttributes;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700207 int mNetworksDefined;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700208
Robert Greenwalt12c44552009-12-07 11:33:18 -0800209 private static class RadioAttributes {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700210 public int mSimultaneity;
211 public int mType;
212 public RadioAttributes(String init) {
213 String fragments[] = init.split(",");
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700214 mType = Integer.parseInt(fragments[0]);
215 mSimultaneity = Integer.parseInt(fragments[1]);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700216 }
217 }
218 RadioAttributes[] mRadioAttributes;
219
The Android Open Source Project28527d22009-03-03 19:31:44 -0800220 private static class ConnectivityThread extends Thread {
221 private Context mContext;
Robert Greenwalt0659da32009-07-16 17:21:39 -0700222
The Android Open Source Project28527d22009-03-03 19:31:44 -0800223 private ConnectivityThread(Context context) {
224 super("ConnectivityThread");
225 mContext = context;
226 }
227
228 @Override
229 public void run() {
230 Looper.prepare();
231 synchronized (this) {
232 sServiceInstance = new ConnectivityService(mContext);
233 notifyAll();
234 }
235 Looper.loop();
236 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700237
The Android Open Source Project28527d22009-03-03 19:31:44 -0800238 public static ConnectivityService getServiceInstance(Context context) {
239 ConnectivityThread thread = new ConnectivityThread(context);
240 thread.start();
Robert Greenwalt0659da32009-07-16 17:21:39 -0700241
The Android Open Source Project28527d22009-03-03 19:31:44 -0800242 synchronized (thread) {
243 while (sServiceInstance == null) {
244 try {
245 // Wait until sServiceInstance has been initialized.
246 thread.wait();
247 } catch (InterruptedException ignore) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800248 Slog.e(TAG,
Robert Greenwalt0659da32009-07-16 17:21:39 -0700249 "Unexpected InterruptedException while waiting"+
250 " for ConnectivityService thread");
The Android Open Source Project28527d22009-03-03 19:31:44 -0800251 }
252 }
253 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700254
The Android Open Source Project28527d22009-03-03 19:31:44 -0800255 return sServiceInstance;
256 }
257 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700258
The Android Open Source Project28527d22009-03-03 19:31:44 -0800259 public static ConnectivityService getInstance(Context context) {
260 return ConnectivityThread.getServiceInstance(context);
261 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700262
The Android Open Source Project28527d22009-03-03 19:31:44 -0800263 private ConnectivityService(Context context) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800264 if (DBG) Slog.v(TAG, "ConnectivityService starting up");
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800265
266 // setup our unique device name
267 String id = Settings.Secure.getString(context.getContentResolver(),
268 Settings.Secure.ANDROID_ID);
269 if (id != null && id.length() > 0) {
270 String name = new String("android_").concat(id);
271 SystemProperties.set("net.hostname", name);
272 }
273
The Android Open Source Project28527d22009-03-03 19:31:44 -0800274 mContext = context;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700275 mNetTrackers = new NetworkStateTracker[
276 ConnectivityManager.MAX_NETWORK_TYPE+1];
277 mHandler = new MyHandler();
Robert Greenwalt0659da32009-07-16 17:21:39 -0700278
The Android Open Source Project28527d22009-03-03 19:31:44 -0800279 mNetworkPreference = getPersistedNetworkPreference();
Robert Greenwalt0659da32009-07-16 17:21:39 -0700280
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700281 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
282 mNetAttributes = new NetworkAttributes[ConnectivityManager.MAX_NETWORK_TYPE+1];
283
Robert Greenwalt2034b912009-08-12 16:08:25 -0700284 // Load device network attributes from resources
Robert Greenwalt2034b912009-08-12 16:08:25 -0700285 String[] raStrings = context.getResources().getStringArray(
286 com.android.internal.R.array.radioAttributes);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700287 for (String raString : raStrings) {
288 RadioAttributes r = new RadioAttributes(raString);
289 if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800290 Slog.e(TAG, "Error in radioAttributes - ignoring attempt to define type " + r.mType);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700291 continue;
292 }
293 if (mRadioAttributes[r.mType] != null) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800294 Slog.e(TAG, "Error in radioAttributes - ignoring attempt to redefine type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700295 r.mType);
296 continue;
297 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700298 mRadioAttributes[r.mType] = r;
299 }
300
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700301 String[] naStrings = context.getResources().getStringArray(
302 com.android.internal.R.array.networkAttributes);
303 for (String naString : naStrings) {
304 try {
305 NetworkAttributes n = new NetworkAttributes(naString);
306 if (n.mType > ConnectivityManager.MAX_NETWORK_TYPE) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800307 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to define type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700308 n.mType);
309 continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700310 }
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700311 if (mNetAttributes[n.mType] != null) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800312 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to redefine type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700313 n.mType);
314 continue;
315 }
316 if (mRadioAttributes[n.mRadio] == null) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800317 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to use undefined " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700318 "radio " + n.mRadio + " in network type " + n.mType);
319 continue;
320 }
321 mNetAttributes[n.mType] = n;
322 mNetworksDefined++;
323 } catch(Exception e) {
324 // ignore it - leave the entry null
Robert Greenwalt2034b912009-08-12 16:08:25 -0700325 }
326 }
327
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700328 // high priority first
329 mPriorityList = new int[mNetworksDefined];
330 {
331 int insertionPoint = mNetworksDefined-1;
332 int currentLowest = 0;
333 int nextLowest = 0;
334 while (insertionPoint > -1) {
335 for (NetworkAttributes na : mNetAttributes) {
336 if (na == null) continue;
337 if (na.mPriority < currentLowest) continue;
338 if (na.mPriority > currentLowest) {
339 if (na.mPriority < nextLowest || nextLowest == 0) {
340 nextLowest = na.mPriority;
341 }
342 continue;
343 }
344 mPriorityList[insertionPoint--] = na.mType;
345 }
346 currentLowest = nextLowest;
347 nextLowest = 0;
348 }
349 }
350
351 mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
352 for (int i : mPriorityList) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700353 mNetRequestersPids[i] = new ArrayList();
354 }
355
356 mFeatureUsers = new ArrayList();
357
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700358 mNumDnsEntries = 0;
359
360 mTestMode = SystemProperties.get("cm.test.mode").equals("true")
361 && SystemProperties.get("ro.build.type").equals("eng");
The Android Open Source Project28527d22009-03-03 19:31:44 -0800362 /*
363 * Create the network state trackers for Wi-Fi and mobile
364 * data. Maybe this could be done with a factory class,
365 * but it's not clear that it's worth it, given that
366 * the number of different network types is not going
367 * to change very often.
368 */
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800369 boolean noMobileData = !getMobileDataEnabled();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700370 for (int netType : mPriorityList) {
371 switch (mNetAttributes[netType].mRadio) {
372 case ConnectivityManager.TYPE_WIFI:
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800373 if (DBG) Slog.v(TAG, "Starting Wifi Service.");
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700374 WifiStateTracker wst = new WifiStateTracker(context, mHandler);
375 WifiService wifiService = new WifiService(context, wst);
376 ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
Irfan Sheriff324ec572010-03-11 16:37:45 -0800377 wifiService.startWifi();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700378 mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
379 wst.startMonitoring();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800380
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700381 break;
382 case ConnectivityManager.TYPE_MOBILE:
383 mNetTrackers[netType] = new MobileDataStateTracker(context, mHandler,
384 netType, mNetAttributes[netType].mName);
385 mNetTrackers[netType].startMonitoring();
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800386 if (noMobileData) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800387 if (DBG) Slog.d(TAG, "tearing down Mobile networks due to setting");
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800388 mNetTrackers[netType].teardown();
389 }
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700390 break;
TK MUN141623d2011-02-23 18:55:55 +0900391 case ConnectivityManager.TYPE_WIMAX:
392 NetworkStateTracker nst = makeWimaxStateTracker();
393 if (nst != null) {
394 nst.startMonitoring();
395 }
396 mNetTrackers[netType] = nst;
397 break;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700398 default:
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800399 Slog.e(TAG, "Trying to create a DataStateTracker for an unknown radio type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700400 mNetAttributes[netType].mRadio);
401 continue;
402 }
403 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800404
Robert Greenwaltc0b6c602010-03-11 15:03:08 -0800405 mTethering = new Tethering(mContext, mHandler.getLooper());
Robert Greenwaltf1b66e12010-02-25 12:29:30 -0800406 mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) ||
407 !mTethering.isDunRequired()) &&
408 (mTethering.getTetherableUsbRegexs().length != 0 ||
409 mTethering.getTetherableWifiRegexs().length != 0) &&
410 mTethering.getUpstreamIfaceRegexs().length != 0);
411
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700412 if (DBG) {
413 mInetLog = new ArrayList();
414 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800415 }
416
TK MUN141623d2011-02-23 18:55:55 +0900417 private NetworkStateTracker makeWimaxStateTracker() {
418 //Initialize Wimax
419 DexClassLoader wimaxClassLoader;
420 Class wimaxStateTrackerClass = null;
421 Class wimaxServiceClass = null;
422 Class wimaxManagerClass;
423 String wimaxJarLocation;
424 String wimaxLibLocation;
425 String wimaxManagerClassName;
426 String wimaxServiceClassName;
427 String wimaxStateTrackerClassName;
428
429 NetworkStateTracker wimaxStateTracker = null;
430
431 boolean isWimaxEnabled = mContext.getResources().getBoolean(
432 com.android.internal.R.bool.config_wimaxEnabled);
433
434 if (isWimaxEnabled) {
435 try {
436 wimaxJarLocation = mContext.getResources().getString(
437 com.android.internal.R.string.config_wimaxServiceJarLocation);
438 wimaxLibLocation = mContext.getResources().getString(
439 com.android.internal.R.string.config_wimaxNativeLibLocation);
440 wimaxManagerClassName = mContext.getResources().getString(
441 com.android.internal.R.string.config_wimaxManagerClassname);
442 wimaxServiceClassName = mContext.getResources().getString(
443 com.android.internal.R.string.config_wimaxServiceClassname);
444 wimaxStateTrackerClassName = mContext.getResources().getString(
445 com.android.internal.R.string.config_wimaxStateTrackerClassname);
446
447 wimaxClassLoader = new DexClassLoader(wimaxJarLocation,
448 new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
449 wimaxLibLocation,ClassLoader.getSystemClassLoader());
450
451 try {
452 wimaxManagerClass = wimaxClassLoader.loadClass(wimaxManagerClassName);
453 wimaxStateTrackerClass = wimaxClassLoader.loadClass(wimaxStateTrackerClassName);
454 wimaxServiceClass = wimaxClassLoader.loadClass(wimaxServiceClassName);
455 } catch (ClassNotFoundException ex) {
456 ex.printStackTrace();
457 return null;
458 }
459 } catch(Resources.NotFoundException ex) {
460 Slog.e(TAG, "Wimax Resources does not exist!!! ");
461 return null;
462 }
463
464 try {
465 Slog.v(TAG, "Starting Wimax Service... ");
466
467 Constructor wmxStTrkrConst = wimaxStateTrackerClass.getConstructor
468 (new Class[] {Context.class,Handler.class});
469 wimaxStateTracker = (NetworkStateTracker)wmxStTrkrConst.newInstance(mContext,mHandler);
470
471 Constructor wmxSrvConst = wimaxServiceClass.getDeclaredConstructor
472 (new Class[] {Context.class,wimaxStateTrackerClass});
473 wmxSrvConst.setAccessible(true);
474 IBinder svcInvoker = (IBinder) wmxSrvConst.newInstance(mContext,wimaxStateTracker);
475 wmxSrvConst.setAccessible(false);
476
477 ServiceManager.addService(WimaxManagerConstants.WIMAX_SERVICE, svcInvoker);
478
479 } catch(ClassCastException ex) {
480 ex.printStackTrace();
481 return null;
482 } catch (NoSuchMethodException ex) {
483 ex.printStackTrace();
484 return null;
485 } catch (InstantiationException ex) {
486 ex.printStackTrace();
487 return null;
488 } catch(IllegalAccessException ex) {
489 ex.printStackTrace();
490 return null;
491 } catch(InvocationTargetException ex) {
492 ex.printStackTrace();
493 return null;
494 } catch(Exception ex) {
495 ex.printStackTrace();
496 return null;
497 }
498 } else {
499 Slog.e(TAG, "Wimax is not enabled or not added to the network attributes!!! ");
500 return null;
501 }
502
503 return wimaxStateTracker;
504 }
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700505
The Android Open Source Project28527d22009-03-03 19:31:44 -0800506 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700507 * Sets the preferred network.
The Android Open Source Project28527d22009-03-03 19:31:44 -0800508 * @param preference the new preference
509 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700510 public void setNetworkPreference(int preference) {
The Android Open Source Project28527d22009-03-03 19:31:44 -0800511 enforceChangePermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700512
513 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
The Android Open Source Project28527d22009-03-03 19:31:44 -0800514 }
515
516 public int getNetworkPreference() {
517 enforceAccessPermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700518 int preference;
519 synchronized(this) {
520 preference = mNetworkPreference;
521 }
522 return preference;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800523 }
524
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700525 private void handleSetNetworkPreference(int preference) {
526 if (ConnectivityManager.isNetworkTypeValid(preference) &&
527 mNetAttributes[preference] != null &&
528 mNetAttributes[preference].isDefault()) {
529 if (mNetworkPreference != preference) {
530 final ContentResolver cr = mContext.getContentResolver();
531 Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference);
532 synchronized(this) {
533 mNetworkPreference = preference;
534 }
535 enforcePreference();
536 }
537 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800538 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700539
The Android Open Source Project28527d22009-03-03 19:31:44 -0800540 private int getPersistedNetworkPreference() {
541 final ContentResolver cr = mContext.getContentResolver();
542
543 final int networkPrefSetting = Settings.Secure
544 .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
545 if (networkPrefSetting != -1) {
546 return networkPrefSetting;
547 }
548
549 return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
550 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700551
The Android Open Source Project28527d22009-03-03 19:31:44 -0800552 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700553 * Make the state of network connectivity conform to the preference settings
The Android Open Source Project28527d22009-03-03 19:31:44 -0800554 * In this method, we only tear down a non-preferred network. Establishing
555 * a connection to the preferred network is taken care of when we handle
556 * the disconnect event from the non-preferred network
557 * (see {@link #handleDisconnect(NetworkInfo)}).
558 */
559 private void enforcePreference() {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700560 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
The Android Open Source Project28527d22009-03-03 19:31:44 -0800561 return;
562
Robert Greenwalt2034b912009-08-12 16:08:25 -0700563 if (!mNetTrackers[mNetworkPreference].isAvailable())
564 return;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800565
Robert Greenwalt2034b912009-08-12 16:08:25 -0700566 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700567 if (t != mNetworkPreference && mNetTrackers[t] != null &&
Robert Greenwalt2034b912009-08-12 16:08:25 -0700568 mNetTrackers[t].getNetworkInfo().isConnected()) {
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700569 if (DBG) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800570 Slog.d(TAG, "tearing down " +
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700571 mNetTrackers[t].getNetworkInfo() +
572 " in enforcePreference");
573 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700574 teardown(mNetTrackers[t]);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800575 }
576 }
577 }
578
579 private boolean teardown(NetworkStateTracker netTracker) {
580 if (netTracker.teardown()) {
581 netTracker.setTeardownRequested(true);
582 return true;
583 } else {
584 return false;
585 }
586 }
587
588 /**
589 * Return NetworkInfo for the active (i.e., connected) network interface.
590 * It is assumed that at most one network is active at a time. If more
591 * than one is active, it is indeterminate which will be returned.
Robert Greenwalt0659da32009-07-16 17:21:39 -0700592 * @return the info for the active network, or {@code null} if none is
593 * active
The Android Open Source Project28527d22009-03-03 19:31:44 -0800594 */
595 public NetworkInfo getActiveNetworkInfo() {
596 enforceAccessPermission();
Robert Greenwalta71471b2011-03-24 21:41:41 -0700597 if (mActiveDefaultNetwork != -1) {
598 return mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800599 }
600 return null;
601 }
602
603 public NetworkInfo getNetworkInfo(int networkType) {
604 enforceAccessPermission();
605 if (ConnectivityManager.isNetworkTypeValid(networkType)) {
606 NetworkStateTracker t = mNetTrackers[networkType];
607 if (t != null)
608 return t.getNetworkInfo();
609 }
610 return null;
611 }
612
613 public NetworkInfo[] getAllNetworkInfo() {
614 enforceAccessPermission();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700615 NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
The Android Open Source Project28527d22009-03-03 19:31:44 -0800616 int i = 0;
617 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700618 if(t != null) result[i++] = t.getNetworkInfo();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800619 }
620 return result;
621 }
622
623 public boolean setRadios(boolean turnOn) {
624 boolean result = true;
625 enforceChangePermission();
626 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700627 if (t != null) result = t.setRadio(turnOn) && result;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800628 }
629 return result;
630 }
631
632 public boolean setRadio(int netType, boolean turnOn) {
633 enforceChangePermission();
634 if (!ConnectivityManager.isNetworkTypeValid(netType)) {
635 return false;
636 }
637 NetworkStateTracker tracker = mNetTrackers[netType];
638 return tracker != null && tracker.setRadio(turnOn);
639 }
640
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700641 /**
642 * Used to notice when the calling process dies so we can self-expire
643 *
644 * Also used to know if the process has cleaned up after itself when
645 * our auto-expire timer goes off. The timer has a link to an object.
646 *
647 */
Robert Greenwalt2034b912009-08-12 16:08:25 -0700648 private class FeatureUser implements IBinder.DeathRecipient {
649 int mNetworkType;
650 String mFeature;
651 IBinder mBinder;
652 int mPid;
653 int mUid;
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800654 long mCreateTime;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700655
656 FeatureUser(int type, String feature, IBinder binder) {
657 super();
658 mNetworkType = type;
659 mFeature = feature;
660 mBinder = binder;
661 mPid = getCallingPid();
662 mUid = getCallingUid();
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800663 mCreateTime = System.currentTimeMillis();
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700664
Robert Greenwalt2034b912009-08-12 16:08:25 -0700665 try {
666 mBinder.linkToDeath(this, 0);
667 } catch (RemoteException e) {
668 binderDied();
669 }
670 }
671
672 void unlinkDeathRecipient() {
673 mBinder.unlinkToDeath(this, 0);
674 }
675
676 public void binderDied() {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800677 Slog.d(TAG, "ConnectivityService FeatureUser binderDied(" +
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800678 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
679 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700680 stopUsingNetworkFeature(this, false);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700681 }
682
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700683 public void expire() {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800684 Slog.d(TAG, "ConnectivityService FeatureUser expire(" +
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800685 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
686 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700687 stopUsingNetworkFeature(this, false);
688 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800689
690 public String toString() {
691 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
692 (System.currentTimeMillis() - mCreateTime) + " mSec ago";
693 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700694 }
695
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700696 // javadoc from interface
Robert Greenwalt2034b912009-08-12 16:08:25 -0700697 public int startUsingNetworkFeature(int networkType, String feature,
698 IBinder binder) {
699 if (DBG) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800700 Slog.d(TAG, "startUsingNetworkFeature for net " + networkType +
Robert Greenwalt2034b912009-08-12 16:08:25 -0700701 ": " + feature);
702 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800703 enforceChangePermission();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700704 if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
705 mNetAttributes[networkType] == null) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700706 return Phone.APN_REQUEST_FAILED;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800707 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700708
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700709 FeatureUser f = new FeatureUser(networkType, feature, binder);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700710
711 // TODO - move this into the MobileDataStateTracker
712 int usedNetworkType = networkType;
713 if(networkType == ConnectivityManager.TYPE_MOBILE) {
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800714 if (!getMobileDataEnabled()) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800715 if (DBG) Slog.d(TAG, "requested special network with data disabled - rejected");
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800716 return Phone.APN_TYPE_NOT_AVAILABLE;
717 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700718 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
719 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
720 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
721 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
722 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
723 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
724 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
725 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
726 }
727 }
728 NetworkStateTracker network = mNetTrackers[usedNetworkType];
729 if (network != null) {
730 if (usedNetworkType != networkType) {
731 Integer currentPid = new Integer(getCallingPid());
732
733 NetworkStateTracker radio = mNetTrackers[networkType];
734 NetworkInfo ni = network.getNetworkInfo();
735
736 if (ni.isAvailable() == false) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800737 if (DBG) Slog.d(TAG, "special network not available");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700738 return Phone.APN_TYPE_NOT_AVAILABLE;
739 }
740
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700741 synchronized(this) {
742 mFeatureUsers.add(f);
743 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
744 // this gets used for per-pid dns when connected
745 mNetRequestersPids[usedNetworkType].add(currentPid);
746 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700747 }
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700748 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK,
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700749 f), getRestoreDefaultNetworkDelay());
750
Robert Greenwalt2034b912009-08-12 16:08:25 -0700751
Robert Greenwalta52c75a2009-08-19 20:19:33 -0700752 if ((ni.isConnectedOrConnecting() == true) &&
753 !network.isTeardownRequested()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700754 if (ni.isConnected() == true) {
755 // add the pid-specific dns
Robert Greenwalt0ef68752010-08-13 14:16:12 -0700756 handleDnsConfigurationChange(networkType);
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800757 if (DBG) Slog.d(TAG, "special network already active");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700758 return Phone.APN_ALREADY_ACTIVE;
759 }
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800760 if (DBG) Slog.d(TAG, "special network already connecting");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700761 return Phone.APN_REQUEST_STARTED;
762 }
763
764 // check if the radio in play can make another contact
765 // assume if cannot for now
766
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800767 if (DBG) Slog.d(TAG, "reconnecting to special network");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700768 network.reconnect();
769 return Phone.APN_REQUEST_STARTED;
770 } else {
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700771 synchronized(this) {
772 mFeatureUsers.add(f);
773 }
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700774 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK,
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700775 f), getRestoreDefaultNetworkDelay());
776
Robert Greenwalt2034b912009-08-12 16:08:25 -0700777 return network.startUsingNetworkFeature(feature,
778 getCallingPid(), getCallingUid());
779 }
780 }
781 return Phone.APN_TYPE_NOT_AVAILABLE;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800782 }
783
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700784 // javadoc from interface
The Android Open Source Project28527d22009-03-03 19:31:44 -0800785 public int stopUsingNetworkFeature(int networkType, String feature) {
Robert Greenwalt28f43012009-10-06 17:52:40 -0700786 enforceChangePermission();
787
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700788 int pid = getCallingPid();
789 int uid = getCallingUid();
790
791 FeatureUser u = null;
792 boolean found = false;
793
794 synchronized(this) {
795 for (int i = 0; i < mFeatureUsers.size() ; i++) {
796 u = (FeatureUser)mFeatureUsers.get(i);
797 if (uid == u.mUid && pid == u.mPid &&
798 networkType == u.mNetworkType &&
799 TextUtils.equals(feature, u.mFeature)) {
800 found = true;
801 break;
802 }
803 }
804 }
805 if (found && u != null) {
806 // stop regardless of how many other time this proc had called start
807 return stopUsingNetworkFeature(u, true);
808 } else {
809 // none found!
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800810 if (DBG) Slog.d(TAG, "ignoring stopUsingNetworkFeature - not a live request");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700811 return 1;
812 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700813 }
814
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700815 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
816 int networkType = u.mNetworkType;
817 String feature = u.mFeature;
818 int pid = u.mPid;
819 int uid = u.mUid;
820
821 NetworkStateTracker tracker = null;
822 boolean callTeardown = false; // used to carry our decision outside of sync block
823
Robert Greenwalt2034b912009-08-12 16:08:25 -0700824 if (DBG) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800825 Slog.d(TAG, "stopUsingNetworkFeature for net " + networkType +
Robert Greenwalt2034b912009-08-12 16:08:25 -0700826 ": " + feature);
827 }
Robert Greenwalt28f43012009-10-06 17:52:40 -0700828
The Android Open Source Project28527d22009-03-03 19:31:44 -0800829 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
830 return -1;
831 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700832
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700833 // need to link the mFeatureUsers list with the mNetRequestersPids state in this
834 // sync block
835 synchronized(this) {
836 // check if this process still has an outstanding start request
837 if (!mFeatureUsers.contains(u)) {
Robert Greenwalt46ceefa2010-03-10 16:10:43 -0800838 if (DBG) Slog.d(TAG, "ignoring - this process has no outstanding requests");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700839 return 1;
840 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700841 u.unlinkDeathRecipient();
842 mFeatureUsers.remove(mFeatureUsers.indexOf(u));
843 // If we care about duplicate requests, check for that here.
844 //
845 // This is done to support the extension of a request - the app
846 // can request we start the network feature again and renew the
847 // auto-shutoff delay. Normal "stop" calls from the app though
848 // do not pay attention to duplicate requests - in effect the
849 // API does not refcount and a single stop will counter multiple starts.
850 if (ignoreDups == false) {
851 for (int i = 0; i < mFeatureUsers.size() ; i++) {
852 FeatureUser x = (FeatureUser)mFeatureUsers.get(i);
853 if (x.mUid == u.mUid && x.mPid == u.mPid &&
854 x.mNetworkType == u.mNetworkType &&
855 TextUtils.equals(x.mFeature, u.mFeature)) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800856 if (DBG) Slog.d(TAG, "ignoring stopUsingNetworkFeature as dup is found");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700857 return 1;
858 }
859 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700860 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700861
862 // TODO - move to MobileDataStateTracker
863 int usedNetworkType = networkType;
864 if (networkType == ConnectivityManager.TYPE_MOBILE) {
865 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
866 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
867 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
868 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
869 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
870 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
871 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
872 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
873 }
874 }
875 tracker = mNetTrackers[usedNetworkType];
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700876 if (tracker == null) {
Robert Greenwalt46ceefa2010-03-10 16:10:43 -0800877 if (DBG) Slog.d(TAG, "ignoring - no known tracker for net type " + usedNetworkType);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700878 return -1;
879 }
880 if (usedNetworkType != networkType) {
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700881 Integer currentPid = new Integer(pid);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700882 mNetRequestersPids[usedNetworkType].remove(currentPid);
Robert Greenwalt0ca68a02009-12-17 14:54:59 -0800883 reassessPidDns(pid, true);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700884 if (mNetRequestersPids[usedNetworkType].size() != 0) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800885 if (DBG) Slog.d(TAG, "not tearing down special network - " +
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700886 "others still using it");
887 return 1;
888 }
889 callTeardown = true;
890 }
891 }
Robert Greenwalt46ceefa2010-03-10 16:10:43 -0800892 if (DBG) Slog.d(TAG, "Doing network teardown");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700893 if (callTeardown) {
894 tracker.teardown();
Robert Greenwalt2034b912009-08-12 16:08:25 -0700895 return 1;
896 } else {
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700897 // do it the old fashioned way
Robert Greenwalt2034b912009-08-12 16:08:25 -0700898 return tracker.stopUsingNetworkFeature(feature, pid, uid);
899 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800900 }
901
902 /**
Banavathu, Srinivas Naik7601f572010-08-10 20:13:53 +0530903 * @deprecated use requestRouteToHostAddress instead
904 *
The Android Open Source Project28527d22009-03-03 19:31:44 -0800905 * Ensure that a network route exists to deliver traffic to the specified
906 * host via the specified network interface.
Robert Greenwalt0659da32009-07-16 17:21:39 -0700907 * @param networkType the type of the network over which traffic to the
908 * specified host is to be routed
909 * @param hostAddress the IP address of the host to which the route is
910 * desired
The Android Open Source Project28527d22009-03-03 19:31:44 -0800911 * @return {@code true} on success, {@code false} on failure
912 */
913 public boolean requestRouteToHost(int networkType, int hostAddress) {
Banavathu, Srinivas Naik7601f572010-08-10 20:13:53 +0530914 InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
915
916 if (inetAddress == null) {
917 return false;
918 }
919
920 return requestRouteToHostAddress(networkType, inetAddress.getAddress());
921 }
922
923 /**
924 * Ensure that a network route exists to deliver traffic to the specified
925 * host via the specified network interface.
926 * @param networkType the type of the network over which traffic to the
927 * specified host is to be routed
928 * @param hostAddress the IP address of the host to which the route is
929 * desired
930 * @return {@code true} on success, {@code false} on failure
931 */
932 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
The Android Open Source Project28527d22009-03-03 19:31:44 -0800933 enforceChangePermission();
934 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
935 return false;
936 }
937 NetworkStateTracker tracker = mNetTrackers[networkType];
Robert Greenwalt4666ed02009-09-10 15:06:20 -0700938
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700939 if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
940 tracker.isTeardownRequested()) {
Robert Greenwalt4666ed02009-09-10 15:06:20 -0700941 if (DBG) {
Banavathu, Srinivas Naik7601f572010-08-10 20:13:53 +0530942 Slog.d(TAG, "requestRouteToHostAddress on down network " +
943 "(" + networkType + ") - dropped");
Robert Greenwalt4666ed02009-09-10 15:06:20 -0700944 }
945 return false;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800946 }
Banavathu, Srinivas Naik7601f572010-08-10 20:13:53 +0530947
948 try {
949 InetAddress inetAddress = InetAddress.getByAddress(hostAddress);
950 return tracker.requestRouteToHost(inetAddress);
951 } catch (UnknownHostException e) {
952 return false;
953 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800954 }
955
956 /**
957 * @see ConnectivityManager#getBackgroundDataSetting()
958 */
959 public boolean getBackgroundDataSetting() {
960 return Settings.Secure.getInt(mContext.getContentResolver(),
961 Settings.Secure.BACKGROUND_DATA, 1) == 1;
962 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700963
The Android Open Source Project28527d22009-03-03 19:31:44 -0800964 /**
965 * @see ConnectivityManager#setBackgroundDataSetting(boolean)
966 */
967 public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) {
968 mContext.enforceCallingOrSelfPermission(
969 android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
970 "ConnectivityService");
Robert Greenwalt0659da32009-07-16 17:21:39 -0700971
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700972 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA,
973 (allowBackgroundDataUsage ? ENABLED : DISABLED), 0));
974 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800975
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700976 private void handleSetBackgroundData(boolean enabled) {
977 if (enabled != getBackgroundDataSetting()) {
978 Settings.Secure.putInt(mContext.getContentResolver(),
979 Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0);
980 Intent broadcast = new Intent(
981 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
982 mContext.sendBroadcast(broadcast);
983 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700984 }
985
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800986 /**
987 * @see ConnectivityManager#getMobileDataEnabled()
988 */
989 public boolean getMobileDataEnabled() {
990 enforceAccessPermission();
991 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
992 Settings.Secure.MOBILE_DATA, 1) == 1;
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800993 if (DBG) Slog.d(TAG, "getMobileDataEnabled returning " + retVal);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800994 return retVal;
995 }
996
997 /**
998 * @see ConnectivityManager#setMobileDataEnabled(boolean)
999 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001000 public void setMobileDataEnabled(boolean enabled) {
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001001 enforceChangePermission();
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001002 if (DBG) Slog.d(TAG, "setMobileDataEnabled(" + enabled + ")");
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001003
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001004 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
1005 (enabled ? ENABLED : DISABLED), 0));
1006 }
1007
1008 private void handleSetMobileData(boolean enabled) {
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001009 if (getMobileDataEnabled() == enabled) return;
1010
1011 Settings.Secure.putInt(mContext.getContentResolver(),
1012 Settings.Secure.MOBILE_DATA, enabled ? 1 : 0);
1013
1014 if (enabled) {
1015 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001016 if (DBG) {
1017 Slog.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]);
1018 }
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001019 mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect();
1020 }
1021 } else {
1022 for (NetworkStateTracker nt : mNetTrackers) {
1023 if (nt == null) continue;
1024 int netType = nt.getNetworkInfo().getType();
1025 if (mNetAttributes[netType].mRadio == ConnectivityManager.TYPE_MOBILE) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001026 if (DBG) Slog.d(TAG, "tearing down " + nt);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001027 nt.teardown();
1028 }
1029 }
1030 }
1031 }
1032
The Android Open Source Project28527d22009-03-03 19:31:44 -08001033 private int getNumConnectedNetworks() {
1034 int numConnectedNets = 0;
1035
1036 for (NetworkStateTracker nt : mNetTrackers) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001037 if (nt != null && nt.getNetworkInfo().isConnected() &&
Robert Greenwalt0659da32009-07-16 17:21:39 -07001038 !nt.isTeardownRequested()) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001039 ++numConnectedNets;
1040 }
1041 }
1042 return numConnectedNets;
1043 }
1044
1045 private void enforceAccessPermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001046 mContext.enforceCallingOrSelfPermission(
1047 android.Manifest.permission.ACCESS_NETWORK_STATE,
1048 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001049 }
1050
1051 private void enforceChangePermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001052 mContext.enforceCallingOrSelfPermission(
1053 android.Manifest.permission.CHANGE_NETWORK_STATE,
1054 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001055 }
1056
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001057 // TODO Make this a special check when it goes public
1058 private void enforceTetherChangePermission() {
1059 mContext.enforceCallingOrSelfPermission(
1060 android.Manifest.permission.CHANGE_NETWORK_STATE,
1061 "ConnectivityService");
1062 }
1063
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001064 private void enforceTetherAccessPermission() {
1065 mContext.enforceCallingOrSelfPermission(
1066 android.Manifest.permission.ACCESS_NETWORK_STATE,
1067 "ConnectivityService");
1068 }
1069
The Android Open Source Project28527d22009-03-03 19:31:44 -08001070 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -07001071 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
1072 * network, we ignore it. If it is for the active network, we send out a
1073 * broadcast. But first, we check whether it might be possible to connect
1074 * to a different network.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001075 * @param info the {@code NetworkInfo} for the network
1076 */
1077 private void handleDisconnect(NetworkInfo info) {
1078
Robert Greenwalt2034b912009-08-12 16:08:25 -07001079 int prevNetType = info.getType();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001080
Robert Greenwalt2034b912009-08-12 16:08:25 -07001081 mNetTrackers[prevNetType].setTeardownRequested(false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001082 /*
1083 * If the disconnected network is not the active one, then don't report
1084 * this as a loss of connectivity. What probably happened is that we're
1085 * getting the disconnect for a network that we explicitly disabled
1086 * in accordance with network preference policies.
1087 */
Robert Greenwalt2034b912009-08-12 16:08:25 -07001088 if (!mNetAttributes[prevNetType].isDefault()) {
1089 List pids = mNetRequestersPids[prevNetType];
1090 for (int i = 0; i<pids.size(); i++) {
1091 Integer pid = (Integer)pids.get(i);
1092 // will remove them because the net's no longer connected
1093 // need to do this now as only now do we know the pids and
1094 // can properly null things that are no longer referenced.
1095 reassessPidDns(pid.intValue(), false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001096 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001097 }
1098
The Android Open Source Project28527d22009-03-03 19:31:44 -08001099 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1100 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1101 if (info.isFailover()) {
1102 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1103 info.setFailover(false);
1104 }
1105 if (info.getReason() != null) {
1106 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1107 }
1108 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001109 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1110 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001111 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001112
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001113 if (mNetAttributes[prevNetType].isDefault()) {
Robert Greenwalt9e081592011-03-10 16:58:31 -08001114 tryFailover(prevNetType);
1115 if (mActiveDefaultNetwork != -1) {
1116 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001117 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1118 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001119 mDefaultInetConditionPublished = 0; // we're not connected anymore
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001120 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1121 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001122 }
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001123 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001124 // do this before we broadcast the change
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001125 handleConnectivityChange(prevNetType);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001126
1127 sendStickyBroadcast(intent);
1128 /*
1129 * If the failover network is already connected, then immediately send
1130 * out a followup broadcast indicating successful failover
1131 */
Robert Greenwalt9e081592011-03-10 16:58:31 -08001132 if (mActiveDefaultNetwork != -1) {
1133 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001134 }
1135 }
1136
Robert Greenwalt9e081592011-03-10 16:58:31 -08001137 private void tryFailover(int prevNetType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001138 /*
1139 * If this is a default network, check if other defaults are available
1140 * or active
1141 */
Robert Greenwalt2034b912009-08-12 16:08:25 -07001142 if (mNetAttributes[prevNetType].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001143 if (mActiveDefaultNetwork == prevNetType) {
1144 mActiveDefaultNetwork = -1;
1145 }
1146
Robert Greenwalt72451bf2010-02-25 12:04:29 -08001147 boolean noMobileData = !getMobileDataEnabled();
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001148 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001149 if (checkType == prevNetType) continue;
1150 if (mNetAttributes[checkType] == null) continue;
Robert Greenwalt084e4772011-02-11 17:32:58 -08001151 if (mNetAttributes[checkType].isDefault() == false) continue;
Robert Greenwalt72451bf2010-02-25 12:04:29 -08001152 if (mNetAttributes[checkType].mRadio == ConnectivityManager.TYPE_MOBILE &&
1153 noMobileData) {
Robert Greenwalte981bc52010-10-08 16:35:52 -07001154 Slog.e(TAG, "not failing over to mobile type " + checkType +
1155 " because Mobile Data Disabled");
Robert Greenwalt72451bf2010-02-25 12:04:29 -08001156 continue;
1157 }
Robert Greenwalt9e081592011-03-10 16:58:31 -08001158 NetworkStateTracker checkTracker = mNetTrackers[checkType];
1159 NetworkInfo checkInfo = checkTracker.getNetworkInfo();
1160 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
1161 checkInfo.setFailover(true);
1162 checkTracker.reconnect();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001163 }
Robert Greenwalt9e081592011-03-10 16:58:31 -08001164 if (DBG) Slog.d(TAG, "Attempting to switch to " + checkInfo.getTypeName());
Robert Greenwalt2034b912009-08-12 16:08:25 -07001165 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001166 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001167 }
1168
1169 private void sendConnectedBroadcast(NetworkInfo info) {
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001170 sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION);
1171 }
1172
1173 private void sendInetConditionBroadcast(NetworkInfo info) {
1174 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1175 }
1176
1177 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1178 Intent intent = new Intent(bcastType);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001179 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1180 if (info.isFailover()) {
1181 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1182 info.setFailover(false);
1183 }
1184 if (info.getReason() != null) {
1185 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1186 }
1187 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001188 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1189 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001190 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07001191 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001192 sendStickyBroadcast(intent);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001193 }
1194
1195 /**
1196 * Called when an attempt to fail over to another network has failed.
1197 * @param info the {@link NetworkInfo} for the failed network
1198 */
1199 private void handleConnectionFailure(NetworkInfo info) {
1200 mNetTrackers[info.getType()].setTeardownRequested(false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001201
Robert Greenwalt2034b912009-08-12 16:08:25 -07001202 String reason = info.getReason();
1203 String extraInfo = info.getExtraInfo();
Robert Greenwalt0659da32009-07-16 17:21:39 -07001204
Robert Greenwalte981bc52010-10-08 16:35:52 -07001205 String reasonText;
1206 if (reason == null) {
1207 reasonText = ".";
1208 } else {
1209 reasonText = " (" + reason + ").";
The Android Open Source Project28527d22009-03-03 19:31:44 -08001210 }
Robert Greenwalte981bc52010-10-08 16:35:52 -07001211 Slog.e(TAG, "Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001212
1213 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1214 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1215 if (getActiveNetworkInfo() == null) {
1216 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1217 }
1218 if (reason != null) {
1219 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
1220 }
1221 if (extraInfo != null) {
1222 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
1223 }
1224 if (info.isFailover()) {
1225 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1226 info.setFailover(false);
1227 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001228
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001229 if (mNetAttributes[info.getType()].isDefault()) {
Robert Greenwalt9e081592011-03-10 16:58:31 -08001230 tryFailover(info.getType());
1231 if (mActiveDefaultNetwork != -1) {
1232 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001233 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1234 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001235 mDefaultInetConditionPublished = 0;
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001236 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1237 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001238 }
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001239
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001240 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001241 sendStickyBroadcast(intent);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001242 /*
1243 * If the failover network is already connected, then immediately send
1244 * out a followup broadcast indicating successful failover
1245 */
Robert Greenwalt9e081592011-03-10 16:58:31 -08001246 if (mActiveDefaultNetwork != -1) {
1247 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001248 }
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001249 }
1250
1251 private void sendStickyBroadcast(Intent intent) {
1252 synchronized(this) {
Dianne Hackborna417ff82009-12-08 19:45:14 -08001253 if (!mSystemReady) {
1254 mInitialBroadcast = new Intent(intent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001255 }
Dianne Hackborna417ff82009-12-08 19:45:14 -08001256 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1257 mContext.sendStickyBroadcast(intent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001258 }
1259 }
1260
1261 void systemReady() {
1262 synchronized(this) {
1263 mSystemReady = true;
Dianne Hackborna417ff82009-12-08 19:45:14 -08001264 if (mInitialBroadcast != null) {
1265 mContext.sendStickyBroadcast(mInitialBroadcast);
1266 mInitialBroadcast = null;
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001267 }
1268 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001269 }
1270
1271 private void handleConnect(NetworkInfo info) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001272 int type = info.getType();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001273
1274 // snapshot isFailover, because sendConnectedBroadcast() resets it
1275 boolean isFailover = info.isFailover();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001276 NetworkStateTracker thisNet = mNetTrackers[type];
The Android Open Source Project28527d22009-03-03 19:31:44 -08001277
Robert Greenwalt2034b912009-08-12 16:08:25 -07001278 // if this is a default net and other default is running
1279 // kill the one not preferred
1280 if (mNetAttributes[type].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001281 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
1282 if ((type != mNetworkPreference &&
1283 mNetAttributes[mActiveDefaultNetwork].mPriority >
1284 mNetAttributes[type].mPriority) ||
1285 mNetworkPreference == mActiveDefaultNetwork) {
1286 // don't accept this one
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001287 if (DBG) Slog.v(TAG, "Not broadcasting CONNECT_ACTION " +
Robert Greenwalt2034b912009-08-12 16:08:25 -07001288 "to torn down network " + info.getTypeName());
1289 teardown(thisNet);
1290 return;
1291 } else {
1292 // tear down the other
1293 NetworkStateTracker otherNet =
1294 mNetTrackers[mActiveDefaultNetwork];
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001295 if (DBG) Slog.v(TAG, "Policy requires " +
Robert Greenwalt2034b912009-08-12 16:08:25 -07001296 otherNet.getNetworkInfo().getTypeName() +
1297 " teardown");
1298 if (!teardown(otherNet)) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001299 Slog.e(TAG, "Network declined teardown request");
Robert Greenwalt2034b912009-08-12 16:08:25 -07001300 return;
1301 }
1302 if (isFailover) {
1303 otherNet.releaseWakeLock();
1304 }
1305 }
1306 }
1307 mActiveDefaultNetwork = type;
Robert Greenwalt986c7412010-09-08 15:24:47 -07001308 // this will cause us to come up initially as unconnected and switching
1309 // to connected after our normal pause unless somebody reports us as reall
1310 // disconnected
1311 mDefaultInetConditionPublished = 0;
1312 mDefaultConnectionSequence++;
1313 mInetConditionChangeInFlight = false;
1314 // Don't do this - if we never sign in stay, grey
1315 //reportNetworkCondition(mActiveDefaultNetwork, 100);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001316 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001317 thisNet.setTeardownRequested(false);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001318 thisNet.updateNetworkSettings();
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001319 handleConnectivityChange(type);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001320 sendConnectedBroadcast(info);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001321 }
1322
1323 private void handleScanResultsAvailable(NetworkInfo info) {
1324 int networkType = info.getType();
1325 if (networkType != ConnectivityManager.TYPE_WIFI) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001326 if (DBG) Slog.v(TAG, "Got ScanResultsAvailable for " +
Robert Greenwalt0659da32009-07-16 17:21:39 -07001327 info.getTypeName() + " network. Don't know how to handle.");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001328 }
Robert Greenwalt0659da32009-07-16 17:21:39 -07001329
The Android Open Source Project28527d22009-03-03 19:31:44 -08001330 mNetTrackers[networkType].interpretScanResultsAvailable();
1331 }
1332
Robert Greenwalt0659da32009-07-16 17:21:39 -07001333 private void handleNotificationChange(boolean visible, int id,
1334 Notification notification) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001335 NotificationManager notificationManager = (NotificationManager) mContext
1336 .getSystemService(Context.NOTIFICATION_SERVICE);
Robert Greenwalt0659da32009-07-16 17:21:39 -07001337
The Android Open Source Project28527d22009-03-03 19:31:44 -08001338 if (visible) {
1339 notificationManager.notify(id, notification);
1340 } else {
1341 notificationManager.cancel(id);
1342 }
1343 }
1344
1345 /**
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001346 * After a change in the connectivity state of any network, We're mainly
1347 * concerned with making sure that the list of DNS servers is setupup
1348 * according to which networks are connected, and ensuring that the
1349 * right routing table entries exist.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001350 */
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001351 private void handleConnectivityChange(int netType) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001352 /*
Robert Greenwalt2034b912009-08-12 16:08:25 -07001353 * If a non-default network is enabled, add the host routes that
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001354 * will allow it's DNS servers to be accessed.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001355 */
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001356 handleDnsConfigurationChange(netType);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001357
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001358 if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
1359 if (mNetAttributes[netType].isDefault()) {
1360 mNetTrackers[netType].addDefaultRoute();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001361 } else {
Robert Greenwalta71471b2011-03-24 21:41:41 -07001362 // many radios add a default route even when we don't want one.
1363 // remove the default interface unless we need it for our active network
1364 if (mActiveDefaultNetwork != -1) {
1365 String defaultIface = mNetTrackers[mActiveDefaultNetwork].getInterfaceName();
1366 if (defaultIface != null &&
1367 !defaultIface.equals(mNetTrackers[netType].getInterfaceName())) {
1368 mNetTrackers[netType].removeDefaultRoute();
1369 }
1370 }
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001371 mNetTrackers[netType].addPrivateDnsRoutes();
1372 }
1373 } else {
1374 if (mNetAttributes[netType].isDefault()) {
1375 mNetTrackers[netType].removeDefaultRoute();
1376 } else {
1377 mNetTrackers[netType].removePrivateDnsRoutes();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001378 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001379 }
1380 }
1381
Robert Greenwalt2034b912009-08-12 16:08:25 -07001382 /**
1383 * Adjust the per-process dns entries (net.dns<x>.<pid>) based
1384 * on the highest priority active net which this process requested.
1385 * If there aren't any, clear it out
1386 */
1387 private void reassessPidDns(int myPid, boolean doBump)
1388 {
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001389 if (DBG) Slog.d(TAG, "reassessPidDns for pid " + myPid);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001390 for(int i : mPriorityList) {
1391 if (mNetAttributes[i].isDefault()) {
1392 continue;
1393 }
1394 NetworkStateTracker nt = mNetTrackers[i];
Robert Greenwalt0659da32009-07-16 17:21:39 -07001395 if (nt.getNetworkInfo().isConnected() &&
1396 !nt.isTeardownRequested()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001397 List pids = mNetRequestersPids[i];
1398 for (int j=0; j<pids.size(); j++) {
1399 Integer pid = (Integer)pids.get(j);
1400 if (pid.intValue() == myPid) {
1401 String[] dnsList = nt.getNameServers();
1402 writePidDns(dnsList, myPid);
1403 if (doBump) {
1404 bumpDns();
1405 }
1406 return;
1407 }
1408 }
1409 }
1410 }
1411 // nothing found - delete
1412 for (int i = 1; ; i++) {
1413 String prop = "net.dns" + i + "." + myPid;
1414 if (SystemProperties.get(prop).length() == 0) {
1415 if (doBump) {
1416 bumpDns();
1417 }
1418 return;
1419 }
1420 SystemProperties.set(prop, "");
1421 }
1422 }
1423
1424 private void writePidDns(String[] dnsList, int pid) {
1425 int j = 1;
1426 for (String dns : dnsList) {
1427 if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
1428 SystemProperties.set("net.dns" + j++ + "." + pid, dns);
1429 }
1430 }
1431 }
1432
1433 private void bumpDns() {
1434 /*
1435 * Bump the property that tells the name resolver library to reread
1436 * the DNS server list from the properties.
1437 */
1438 String propVal = SystemProperties.get("net.dnschange");
1439 int n = 0;
1440 if (propVal.length() != 0) {
1441 try {
1442 n = Integer.parseInt(propVal);
1443 } catch (NumberFormatException e) {}
1444 }
1445 SystemProperties.set("net.dnschange", "" + (n+1));
1446 }
1447
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001448 private void handleDnsConfigurationChange(int netType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001449 // add default net's dns entries
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001450 NetworkStateTracker nt = mNetTrackers[netType];
1451 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
1452 String[] dnsList = nt.getNameServers();
1453 if (mNetAttributes[netType].isDefault()) {
1454 int j = 1;
1455 for (String dns : dnsList) {
1456 if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
1457 if (DBG) {
1458 Slog.d(TAG, "adding dns " + dns + " for " +
1459 nt.getNetworkInfo().getTypeName());
Robert Greenwalt2034b912009-08-12 16:08:25 -07001460 }
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001461 SystemProperties.set("net.dns" + j++, dns);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001462 }
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001463 }
1464 for (int k=j ; k<mNumDnsEntries; k++) {
1465 if (DBG) Slog.d(TAG, "erasing net.dns" + k);
1466 SystemProperties.set("net.dns" + k, "");
1467 }
1468 mNumDnsEntries = j;
1469 } else {
1470 // set per-pid dns for attached secondary nets
1471 List pids = mNetRequestersPids[netType];
1472 for (int y=0; y< pids.size(); y++) {
1473 Integer pid = (Integer)pids.get(y);
1474 writePidDns(dnsList, pid.intValue());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001475 }
1476 }
1477 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001478 bumpDns();
1479 }
1480
1481 private int getRestoreDefaultNetworkDelay() {
1482 String restoreDefaultNetworkDelayStr = SystemProperties.get(
1483 NETWORK_RESTORE_DELAY_PROP_NAME);
1484 if(restoreDefaultNetworkDelayStr != null &&
1485 restoreDefaultNetworkDelayStr.length() != 0) {
1486 try {
1487 return Integer.valueOf(restoreDefaultNetworkDelayStr);
1488 } catch (NumberFormatException e) {
1489 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001490 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001491 return RESTORE_DEFAULT_NETWORK_DELAY;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001492 }
1493
1494 @Override
1495 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001496 if (mContext.checkCallingOrSelfPermission(
1497 android.Manifest.permission.DUMP)
The Android Open Source Project28527d22009-03-03 19:31:44 -08001498 != PackageManager.PERMISSION_GRANTED) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001499 pw.println("Permission Denial: can't dump ConnectivityService " +
1500 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1501 Binder.getCallingUid());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001502 return;
1503 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001504 pw.println();
1505 for (NetworkStateTracker nst : mNetTrackers) {
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08001506 if (nst != null) {
1507 if (nst.getNetworkInfo().isConnected()) {
1508 pw.println("Active network: " + nst.getNetworkInfo().
1509 getTypeName());
1510 }
1511 pw.println(nst.getNetworkInfo());
1512 pw.println(nst);
1513 pw.println();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001514 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001515 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08001516
1517 pw.println("Network Requester Pids:");
1518 for (int net : mPriorityList) {
1519 String pidString = net + ": ";
1520 for (Object pid : mNetRequestersPids[net]) {
1521 pidString = pidString + pid.toString() + ", ";
1522 }
1523 pw.println(pidString);
1524 }
1525 pw.println();
1526
1527 pw.println("FeatureUsers:");
1528 for (Object requester : mFeatureUsers) {
1529 pw.println(requester.toString());
1530 }
1531 pw.println();
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001532
1533 mTethering.dump(fd, pw, args);
Robert Greenwalt0e80be12010-09-20 14:35:25 -07001534
1535 if (mInetLog != null) {
1536 pw.println();
1537 pw.println("Inet condition reports:");
1538 for(int i = 0; i < mInetLog.size(); i++) {
1539 pw.println(mInetLog.get(i));
1540 }
1541 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001542 }
1543
Robert Greenwalt2034b912009-08-12 16:08:25 -07001544 // must be stateless - things change under us.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001545 private class MyHandler extends Handler {
1546 @Override
1547 public void handleMessage(Message msg) {
1548 NetworkInfo info;
1549 switch (msg.what) {
1550 case NetworkStateTracker.EVENT_STATE_CHANGED:
1551 info = (NetworkInfo) msg.obj;
Robert Greenwalt12c44552009-12-07 11:33:18 -08001552 int type = info.getType();
1553 NetworkInfo.State state = info.getState();
Robert Greenwalt24e2d2b2010-01-25 16:14:00 -08001554 // only do this optimization for wifi. It going into scan mode for location
1555 // services generates alot of noise. Meanwhile the mms apn won't send out
1556 // subsequent notifications when on default cellular because it never
1557 // disconnects.. so only do this to wifi notifications. Fixed better when the
1558 // APN notifications are standardized.
1559 if (mNetAttributes[type].mLastState == state &&
1560 mNetAttributes[type].mRadio == ConnectivityManager.TYPE_WIFI) {
Robert Greenwalt12c44552009-12-07 11:33:18 -08001561 if (DBG) {
Robert Greenwalt24e2d2b2010-01-25 16:14:00 -08001562 // TODO - remove this after we validate the dropping doesn't break
1563 // anything
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001564 Slog.d(TAG, "Dropping ConnectivityChange for " +
Robert Greenwalt2adbc7f2010-01-13 09:36:31 -08001565 info.getTypeName() + ": " +
Robert Greenwalt12c44552009-12-07 11:33:18 -08001566 state + "/" + info.getDetailedState());
1567 }
1568 return;
1569 }
1570 mNetAttributes[type].mLastState = state;
1571
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001572 if (DBG) Slog.d(TAG, "ConnectivityChange for " +
Robert Greenwalt0659da32009-07-16 17:21:39 -07001573 info.getTypeName() + ": " +
Robert Greenwalt12c44552009-12-07 11:33:18 -08001574 state + "/" + info.getDetailedState());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001575
1576 // Connectivity state changed:
1577 // [31-13] Reserved for future use
Robert Greenwalt0659da32009-07-16 17:21:39 -07001578 // [12-9] Network subtype (for mobile network, as defined
1579 // by TelephonyManager)
1580 // [8-3] Detailed state ordinal (as defined by
1581 // NetworkInfo.DetailedState)
The Android Open Source Project28527d22009-03-03 19:31:44 -08001582 // [2-0] Network type (as defined by ConnectivityManager)
1583 int eventLogParam = (info.getType() & 0x7) |
1584 ((info.getDetailedState().ordinal() & 0x3f) << 3) |
1585 (info.getSubtype() << 9);
Doug Zongker2fc96232009-12-04 10:31:43 -08001586 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
Robert Greenwalt0659da32009-07-16 17:21:39 -07001587 eventLogParam);
1588
1589 if (info.getDetailedState() ==
1590 NetworkInfo.DetailedState.FAILED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001591 handleConnectionFailure(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08001592 } else if (state == NetworkInfo.State.DISCONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001593 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08001594 } else if (state == NetworkInfo.State.SUSPENDED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001595 // TODO: need to think this over.
Robert Greenwalt0659da32009-07-16 17:21:39 -07001596 // the logic here is, handle SUSPENDED the same as
1597 // DISCONNECTED. The only difference being we are
1598 // broadcasting an intent with NetworkInfo that's
1599 // suspended. This allows the applications an
1600 // opportunity to handle DISCONNECTED and SUSPENDED
1601 // differently, or not.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001602 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08001603 } else if (state == NetworkInfo.State.CONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001604 handleConnect(info);
1605 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001606 break;
1607
1608 case NetworkStateTracker.EVENT_SCAN_RESULTS_AVAILABLE:
1609 info = (NetworkInfo) msg.obj;
1610 handleScanResultsAvailable(info);
1611 break;
Robert Greenwalt0659da32009-07-16 17:21:39 -07001612
The Android Open Source Project28527d22009-03-03 19:31:44 -08001613 case NetworkStateTracker.EVENT_NOTIFICATION_CHANGED:
Robert Greenwalt0659da32009-07-16 17:21:39 -07001614 handleNotificationChange(msg.arg1 == 1, msg.arg2,
1615 (Notification) msg.obj);
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001616 break;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001617
1618 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001619 info = (NetworkInfo) msg.obj;
1620 type = info.getType();
1621 handleDnsConfigurationChange(type);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001622 break;
1623
1624 case NetworkStateTracker.EVENT_ROAMING_CHANGED:
1625 // fill me in
1626 break;
1627
1628 case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED:
1629 // fill me in
1630 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001631 case EVENT_RESTORE_DEFAULT_NETWORK:
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001632 FeatureUser u = (FeatureUser)msg.obj;
1633 u.expire();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001634 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001635 case EVENT_INET_CONDITION_CHANGE:
1636 {
1637 int netType = msg.arg1;
1638 int condition = msg.arg2;
1639 handleInetConditionChange(netType, condition);
Robert Greenwalt986c7412010-09-08 15:24:47 -07001640 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001641 }
1642 case EVENT_INET_CONDITION_HOLD_END:
1643 {
1644 int netType = msg.arg1;
1645 int sequence = msg.arg2;
1646 handleInetConditionHoldEnd(netType, sequence);
Robert Greenwalt986c7412010-09-08 15:24:47 -07001647 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001648 }
1649 case EVENT_SET_NETWORK_PREFERENCE:
1650 {
1651 int preference = msg.arg1;
1652 handleSetNetworkPreference(preference);
1653 break;
1654 }
1655 case EVENT_SET_BACKGROUND_DATA:
1656 {
1657 boolean enabled = (msg.arg1 == ENABLED);
1658 handleSetBackgroundData(enabled);
1659 break;
1660 }
1661 case EVENT_SET_MOBILE_DATA:
1662 {
1663 boolean enabled = (msg.arg1 == ENABLED);
1664 handleSetMobileData(enabled);
1665 break;
1666 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001667 }
1668 }
1669 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001670
1671 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001672 public int tether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001673 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001674
1675 if (isTetheringSupported()) {
1676 return mTethering.tether(iface);
1677 } else {
1678 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1679 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001680 }
1681
1682 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001683 public int untether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001684 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001685
1686 if (isTetheringSupported()) {
1687 return mTethering.untether(iface);
1688 } else {
1689 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1690 }
1691 }
1692
1693 // javadoc from interface
1694 public int getLastTetherError(String iface) {
1695 enforceTetherAccessPermission();
1696
1697 if (isTetheringSupported()) {
1698 return mTethering.getLastTetherError(iface);
1699 } else {
1700 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1701 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001702 }
1703
1704 // TODO - proper iface API for selection by property, inspection, etc
1705 public String[] getTetherableUsbRegexs() {
1706 enforceTetherAccessPermission();
1707 if (isTetheringSupported()) {
1708 return mTethering.getTetherableUsbRegexs();
1709 } else {
1710 return new String[0];
1711 }
1712 }
1713
1714 public String[] getTetherableWifiRegexs() {
1715 enforceTetherAccessPermission();
1716 if (isTetheringSupported()) {
1717 return mTethering.getTetherableWifiRegexs();
1718 } else {
1719 return new String[0];
1720 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001721 }
1722
1723 // TODO - move iface listing, queries, etc to new module
1724 // javadoc from interface
1725 public String[] getTetherableIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001726 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001727 return mTethering.getTetherableIfaces();
1728 }
1729
1730 public String[] getTetheredIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001731 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001732 return mTethering.getTetheredIfaces();
1733 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001734
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001735 public String[] getTetheringErroredIfaces() {
1736 enforceTetherAccessPermission();
1737 return mTethering.getErroredIfaces();
1738 }
1739
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001740 // if ro.tether.denied = true we default to no tethering
1741 // gservices could set the secure setting to 1 though to enable it on a build where it
1742 // had previously been turned off.
1743 public boolean isTetheringSupported() {
1744 enforceTetherAccessPermission();
1745 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
Robert Greenwaltf1b66e12010-02-25 12:29:30 -08001746 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
1747 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
1748 return tetherEnabledInSettings && mTetheringConfigValid;
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001749 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07001750
1751 // 100 percent is full good, 0 is full bad.
1752 public void reportInetCondition(int networkType, int percentage) {
1753 if (DBG) Slog.d(TAG, "reportNetworkCondition(" + networkType + ", " + percentage + ")");
1754 mContext.enforceCallingOrSelfPermission(
1755 android.Manifest.permission.STATUS_BAR,
1756 "ConnectivityService");
1757
Robert Greenwalt0e80be12010-09-20 14:35:25 -07001758 if (DBG) {
1759 int pid = getCallingPid();
1760 int uid = getCallingUid();
1761 String s = pid + "(" + uid + ") reports inet is " +
1762 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
1763 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
1764 mInetLog.add(s);
1765 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
1766 mInetLog.remove(0);
1767 }
1768 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07001769 mHandler.sendMessage(mHandler.obtainMessage(
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001770 EVENT_INET_CONDITION_CHANGE, networkType, percentage));
1771 }
1772
1773 private void handleInetConditionChange(int netType, int condition) {
1774 if (DBG) {
1775 Slog.d(TAG, "Inet connectivity change, net=" +
1776 netType + ", condition=" + condition +
1777 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
1778 }
1779 if (mActiveDefaultNetwork == -1) {
1780 if (DBG) Slog.d(TAG, "no active default network - aborting");
1781 return;
1782 }
1783 if (mActiveDefaultNetwork != netType) {
1784 if (DBG) Slog.d(TAG, "given net not default - aborting");
1785 return;
1786 }
1787 mDefaultInetCondition = condition;
1788 int delay;
1789 if (mInetConditionChangeInFlight == false) {
1790 if (DBG) Slog.d(TAG, "starting a change hold");
1791 // setup a new hold to debounce this
1792 if (mDefaultInetCondition > 50) {
1793 delay = Settings.Secure.getInt(mContext.getContentResolver(),
1794 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
1795 } else {
1796 delay = Settings.Secure.getInt(mContext.getContentResolver(),
1797 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
1798 }
1799 mInetConditionChangeInFlight = true;
1800 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
1801 mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
1802 } else {
1803 // we've set the new condition, when this hold ends that will get
1804 // picked up
1805 if (DBG) Slog.d(TAG, "currently in hold - not setting new end evt");
1806 }
1807 }
1808
1809 private void handleInetConditionHoldEnd(int netType, int sequence) {
1810 if (DBG) {
1811 Slog.d(TAG, "Inet hold end, net=" + netType +
1812 ", condition =" + mDefaultInetCondition +
1813 ", published condition =" + mDefaultInetConditionPublished);
1814 }
1815 mInetConditionChangeInFlight = false;
1816
1817 if (mActiveDefaultNetwork == -1) {
1818 if (DBG) Slog.d(TAG, "no active default network - aborting");
1819 return;
1820 }
1821 if (mDefaultConnectionSequence != sequence) {
1822 if (DBG) Slog.d(TAG, "event hold for obsolete network - aborting");
1823 return;
1824 }
1825 if (mDefaultInetConditionPublished == mDefaultInetCondition) {
1826 if (DBG) Slog.d(TAG, "no change in condition - aborting");
1827 return;
1828 }
1829 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
1830 if (networkInfo.isConnected() == false) {
1831 if (DBG) Slog.d(TAG, "default network not connected - aborting");
1832 return;
1833 }
1834 mDefaultInetConditionPublished = mDefaultInetCondition;
1835 sendInetConditionBroadcast(networkInfo);
1836 return;
Robert Greenwalt986c7412010-09-08 15:24:47 -07001837 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001838}