blob: 6cd3e9eb1ac412c616da1c01f241ff7673c4ecdb [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 Greenwalt44cc4742011-05-20 14:35:50 -070041import android.os.INetworkManagementService;
Robert Greenwalt2034b912009-08-12 16:08:25 -070042import android.os.RemoteException;
The Android Open Source Project28527d22009-03-03 19:31:44 -080043import android.os.ServiceManager;
44import android.os.SystemProperties;
45import android.provider.Settings;
Robert Greenwalt2034b912009-08-12 16:08:25 -070046import android.text.TextUtils;
The Android Open Source Project28527d22009-03-03 19:31:44 -080047import android.util.EventLog;
Joe Onoratoc2386bb2010-02-26 18:56:32 -080048import android.util.Slog;
Robert Greenwalt2034b912009-08-12 16:08:25 -070049import com.android.internal.telephony.Phone;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080050import com.android.server.connectivity.Tethering;
TK MUN141623d2011-02-23 18:55:55 +090051import dalvik.system.DexClassLoader;
The Android Open Source Project28527d22009-03-03 19:31:44 -080052import java.io.FileDescriptor;
53import java.io.PrintWriter;
TK MUN141623d2011-02-23 18:55:55 +090054import java.lang.reflect.Constructor;
55import java.lang.reflect.Method;
56import java.lang.reflect.Modifier;
57import java.lang.reflect.InvocationTargetException;
Robert Greenwalt2034b912009-08-12 16:08:25 -070058import java.util.ArrayList;
Robert Greenwalt0e80be12010-09-20 14:35:25 -070059import java.util.GregorianCalendar;
Robert Greenwalt2034b912009-08-12 16:08:25 -070060import java.util.List;
Banavathu, Srinivas Naik7601f572010-08-10 20:13:53 +053061import java.net.InetAddress;
62import java.net.UnknownHostException;
The Android Open Source Project28527d22009-03-03 19:31:44 -080063
TK MUN141623d2011-02-23 18:55:55 +090064
65
The Android Open Source Project28527d22009-03-03 19:31:44 -080066/**
67 * @hide
68 */
69public class ConnectivityService extends IConnectivityManager.Stub {
70
Dianne Hackborn8919f5a2010-09-30 18:27:22 -070071 private static final boolean DBG = false;
The Android Open Source Project28527d22009-03-03 19:31:44 -080072 private static final String TAG = "ConnectivityService";
73
Robert Greenwalt2034b912009-08-12 16:08:25 -070074 // how long to wait before switching back to a radio's default network
75 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
76 // system property that can override the above value
77 private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
78 "android.telephony.apn-restore";
79
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080080
81 private Tethering mTethering;
Robert Greenwaltf1b66e12010-02-25 12:29:30 -080082 private boolean mTetheringConfigValid = false;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080083
The Android Open Source Project28527d22009-03-03 19:31:44 -080084 /**
85 * Sometimes we want to refer to the individual network state
86 * trackers separately, and sometimes we just want to treat them
87 * abstractly.
88 */
89 private NetworkStateTracker mNetTrackers[];
Robert Greenwalt2034b912009-08-12 16:08:25 -070090
91 /**
92 * A per Net list of the PID's that requested access to the net
93 * used both as a refcount and for per-PID DNS selection
94 */
95 private List mNetRequestersPids[];
96
Robert Greenwalt2034b912009-08-12 16:08:25 -070097 // priority order of the nettrackers
98 // (excluding dynamically set mNetworkPreference)
99 // TODO - move mNetworkTypePreference into this
100 private int[] mPriorityList;
101
The Android Open Source Project28527d22009-03-03 19:31:44 -0800102 private Context mContext;
103 private int mNetworkPreference;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700104 private int mActiveDefaultNetwork = -1;
Robert Greenwalt986c7412010-09-08 15:24:47 -0700105 // 0 is full bad, 100 is full good
106 private int mDefaultInetCondition = 0;
107 private int mDefaultInetConditionPublished = 0;
108 private boolean mInetConditionChangeInFlight = false;
109 private int mDefaultConnectionSequence = 0;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800110
111 private int mNumDnsEntries;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800112
113 private boolean mTestMode;
114 private static ConnectivityService sServiceInstance;
Robert Greenwalt44cc4742011-05-20 14:35:50 -0700115
116 private INetworkManagementService mNetd;
117
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700118 private static final int ENABLED = 1;
119 private static final int DISABLED = 0;
120
121 // Share the event space with NetworkStateTracker (which can't see this
122 // internal class but sends us events). If you change these, change
123 // NetworkStateTracker.java too.
124 private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1;
125 private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100;
126
127 /**
128 * used internally as a delayed event to make us switch back to the
129 * default network
130 */
131 private static final int EVENT_RESTORE_DEFAULT_NETWORK =
132 MAX_NETWORK_STATE_TRACKER_EVENT + 1;
133
134 /**
135 * used internally to change our mobile data enabled flag
136 */
137 private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED =
138 MAX_NETWORK_STATE_TRACKER_EVENT + 2;
139
140 /**
141 * used internally to change our network preference setting
142 * arg1 = networkType to prefer
143 */
144 private static final int EVENT_SET_NETWORK_PREFERENCE =
145 MAX_NETWORK_STATE_TRACKER_EVENT + 3;
146
147 /**
148 * used internally to synchronize inet condition reports
149 * arg1 = networkType
150 * arg2 = condition (0 bad, 100 good)
151 */
152 private static final int EVENT_INET_CONDITION_CHANGE =
153 MAX_NETWORK_STATE_TRACKER_EVENT + 4;
154
155 /**
156 * used internally to mark the end of inet condition hold periods
157 * arg1 = networkType
158 */
159 private static final int EVENT_INET_CONDITION_HOLD_END =
160 MAX_NETWORK_STATE_TRACKER_EVENT + 5;
161
162 /**
163 * used internally to set the background data preference
164 * arg1 = TRUE for enabled, FALSE for disabled
165 */
166 private static final int EVENT_SET_BACKGROUND_DATA =
167 MAX_NETWORK_STATE_TRACKER_EVENT + 6;
168
169 /**
170 * used internally to set enable/disable cellular data
171 * arg1 = ENBALED or DISABLED
172 */
173 private static final int EVENT_SET_MOBILE_DATA =
174 MAX_NETWORK_STATE_TRACKER_EVENT + 7;
175
Robert Greenwalt2034b912009-08-12 16:08:25 -0700176 private Handler mHandler;
177
178 // list of DeathRecipients used to make sure features are turned off when
179 // a process dies
180 private List mFeatureUsers;
181
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400182 private boolean mSystemReady;
Dianne Hackborna417ff82009-12-08 19:45:14 -0800183 private Intent mInitialBroadcast;
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400184
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700185 // used in DBG mode to track inet condition reports
186 private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
187 private ArrayList mInetLog;
188
Robert Greenwalt12c44552009-12-07 11:33:18 -0800189 private static class NetworkAttributes {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700190 /**
191 * Class for holding settings read from resources.
192 */
193 public String mName;
194 public int mType;
195 public int mRadio;
196 public int mPriority;
Robert Greenwalt12c44552009-12-07 11:33:18 -0800197 public NetworkInfo.State mLastState;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700198 public NetworkAttributes(String init) {
199 String fragments[] = init.split(",");
200 mName = fragments[0].toLowerCase();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700201 mType = Integer.parseInt(fragments[1]);
202 mRadio = Integer.parseInt(fragments[2]);
203 mPriority = Integer.parseInt(fragments[3]);
Robert Greenwalt12c44552009-12-07 11:33:18 -0800204 mLastState = NetworkInfo.State.UNKNOWN;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700205 }
206 public boolean isDefault() {
207 return (mType == mRadio);
208 }
209 }
210 NetworkAttributes[] mNetAttributes;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700211 int mNetworksDefined;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700212
Robert Greenwalt12c44552009-12-07 11:33:18 -0800213 private static class RadioAttributes {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700214 public int mSimultaneity;
215 public int mType;
216 public RadioAttributes(String init) {
217 String fragments[] = init.split(",");
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700218 mType = Integer.parseInt(fragments[0]);
219 mSimultaneity = Integer.parseInt(fragments[1]);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700220 }
221 }
222 RadioAttributes[] mRadioAttributes;
223
The Android Open Source Project28527d22009-03-03 19:31:44 -0800224 private static class ConnectivityThread extends Thread {
225 private Context mContext;
Robert Greenwalt0659da32009-07-16 17:21:39 -0700226
The Android Open Source Project28527d22009-03-03 19:31:44 -0800227 private ConnectivityThread(Context context) {
228 super("ConnectivityThread");
229 mContext = context;
230 }
231
232 @Override
233 public void run() {
234 Looper.prepare();
235 synchronized (this) {
236 sServiceInstance = new ConnectivityService(mContext);
237 notifyAll();
238 }
239 Looper.loop();
240 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700241
The Android Open Source Project28527d22009-03-03 19:31:44 -0800242 public static ConnectivityService getServiceInstance(Context context) {
243 ConnectivityThread thread = new ConnectivityThread(context);
244 thread.start();
Robert Greenwalt0659da32009-07-16 17:21:39 -0700245
The Android Open Source Project28527d22009-03-03 19:31:44 -0800246 synchronized (thread) {
247 while (sServiceInstance == null) {
248 try {
249 // Wait until sServiceInstance has been initialized.
250 thread.wait();
251 } catch (InterruptedException ignore) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800252 Slog.e(TAG,
Robert Greenwalt0659da32009-07-16 17:21:39 -0700253 "Unexpected InterruptedException while waiting"+
254 " for ConnectivityService thread");
The Android Open Source Project28527d22009-03-03 19:31:44 -0800255 }
256 }
257 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700258
The Android Open Source Project28527d22009-03-03 19:31:44 -0800259 return sServiceInstance;
260 }
261 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700262
The Android Open Source Project28527d22009-03-03 19:31:44 -0800263 public static ConnectivityService getInstance(Context context) {
264 return ConnectivityThread.getServiceInstance(context);
265 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700266
The Android Open Source Project28527d22009-03-03 19:31:44 -0800267 private ConnectivityService(Context context) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800268 if (DBG) Slog.v(TAG, "ConnectivityService starting up");
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800269
270 // setup our unique device name
271 String id = Settings.Secure.getString(context.getContentResolver(),
272 Settings.Secure.ANDROID_ID);
273 if (id != null && id.length() > 0) {
274 String name = new String("android_").concat(id);
275 SystemProperties.set("net.hostname", name);
276 }
277
The Android Open Source Project28527d22009-03-03 19:31:44 -0800278 mContext = context;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700279 mNetTrackers = new NetworkStateTracker[
280 ConnectivityManager.MAX_NETWORK_TYPE+1];
281 mHandler = new MyHandler();
Robert Greenwalt0659da32009-07-16 17:21:39 -0700282
The Android Open Source Project28527d22009-03-03 19:31:44 -0800283 mNetworkPreference = getPersistedNetworkPreference();
Robert Greenwalt0659da32009-07-16 17:21:39 -0700284
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700285 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
286 mNetAttributes = new NetworkAttributes[ConnectivityManager.MAX_NETWORK_TYPE+1];
287
Robert Greenwalt2034b912009-08-12 16:08:25 -0700288 // Load device network attributes from resources
Robert Greenwalt2034b912009-08-12 16:08:25 -0700289 String[] raStrings = context.getResources().getStringArray(
290 com.android.internal.R.array.radioAttributes);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700291 for (String raString : raStrings) {
292 RadioAttributes r = new RadioAttributes(raString);
293 if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800294 Slog.e(TAG, "Error in radioAttributes - ignoring attempt to define type " + r.mType);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700295 continue;
296 }
297 if (mRadioAttributes[r.mType] != null) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800298 Slog.e(TAG, "Error in radioAttributes - ignoring attempt to redefine type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700299 r.mType);
300 continue;
301 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700302 mRadioAttributes[r.mType] = r;
303 }
304
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700305 String[] naStrings = context.getResources().getStringArray(
306 com.android.internal.R.array.networkAttributes);
307 for (String naString : naStrings) {
308 try {
309 NetworkAttributes n = new NetworkAttributes(naString);
310 if (n.mType > ConnectivityManager.MAX_NETWORK_TYPE) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800311 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to define type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700312 n.mType);
313 continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700314 }
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700315 if (mNetAttributes[n.mType] != null) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800316 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to redefine type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700317 n.mType);
318 continue;
319 }
320 if (mRadioAttributes[n.mRadio] == null) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800321 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to use undefined " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700322 "radio " + n.mRadio + " in network type " + n.mType);
323 continue;
324 }
325 mNetAttributes[n.mType] = n;
326 mNetworksDefined++;
327 } catch(Exception e) {
328 // ignore it - leave the entry null
Robert Greenwalt2034b912009-08-12 16:08:25 -0700329 }
330 }
331
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700332 // high priority first
333 mPriorityList = new int[mNetworksDefined];
334 {
335 int insertionPoint = mNetworksDefined-1;
336 int currentLowest = 0;
337 int nextLowest = 0;
338 while (insertionPoint > -1) {
339 for (NetworkAttributes na : mNetAttributes) {
340 if (na == null) continue;
341 if (na.mPriority < currentLowest) continue;
342 if (na.mPriority > currentLowest) {
343 if (na.mPriority < nextLowest || nextLowest == 0) {
344 nextLowest = na.mPriority;
345 }
346 continue;
347 }
348 mPriorityList[insertionPoint--] = na.mType;
349 }
350 currentLowest = nextLowest;
351 nextLowest = 0;
352 }
353 }
354
355 mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
356 for (int i : mPriorityList) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700357 mNetRequestersPids[i] = new ArrayList();
358 }
359
360 mFeatureUsers = new ArrayList();
361
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700362 mNumDnsEntries = 0;
363
364 mTestMode = SystemProperties.get("cm.test.mode").equals("true")
365 && SystemProperties.get("ro.build.type").equals("eng");
The Android Open Source Project28527d22009-03-03 19:31:44 -0800366 /*
367 * Create the network state trackers for Wi-Fi and mobile
368 * data. Maybe this could be done with a factory class,
369 * but it's not clear that it's worth it, given that
370 * the number of different network types is not going
371 * to change very often.
372 */
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800373 boolean noMobileData = !getMobileDataEnabled();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700374 for (int netType : mPriorityList) {
375 switch (mNetAttributes[netType].mRadio) {
376 case ConnectivityManager.TYPE_WIFI:
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800377 if (DBG) Slog.v(TAG, "Starting Wifi Service.");
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700378 WifiStateTracker wst = new WifiStateTracker(context, mHandler);
379 WifiService wifiService = new WifiService(context, wst);
380 ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
Irfan Sheriff324ec572010-03-11 16:37:45 -0800381 wifiService.startWifi();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700382 mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
383 wst.startMonitoring();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800384
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700385 break;
386 case ConnectivityManager.TYPE_MOBILE:
387 mNetTrackers[netType] = new MobileDataStateTracker(context, mHandler,
388 netType, mNetAttributes[netType].mName);
389 mNetTrackers[netType].startMonitoring();
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800390 if (noMobileData) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800391 if (DBG) Slog.d(TAG, "tearing down Mobile networks due to setting");
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800392 mNetTrackers[netType].teardown();
393 }
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700394 break;
TK MUN141623d2011-02-23 18:55:55 +0900395 case ConnectivityManager.TYPE_WIMAX:
396 NetworkStateTracker nst = makeWimaxStateTracker();
397 if (nst != null) {
398 nst.startMonitoring();
399 }
400 mNetTrackers[netType] = nst;
TK MUNdc9a5352011-03-30 09:27:07 +0900401 if (noMobileData) {
402 if (DBG) Slog.d(TAG, "tearing down WiMAX networks due to setting");
403 mNetTrackers[netType].teardown();
404 }
TK MUN141623d2011-02-23 18:55:55 +0900405 break;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700406 default:
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800407 Slog.e(TAG, "Trying to create a DataStateTracker for an unknown radio type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700408 mNetAttributes[netType].mRadio);
409 continue;
410 }
411 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800412
Robert Greenwaltc0b6c602010-03-11 15:03:08 -0800413 mTethering = new Tethering(mContext, mHandler.getLooper());
Robert Greenwaltf1b66e12010-02-25 12:29:30 -0800414 mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) ||
415 !mTethering.isDunRequired()) &&
416 (mTethering.getTetherableUsbRegexs().length != 0 ||
417 mTethering.getTetherableWifiRegexs().length != 0) &&
418 mTethering.getUpstreamIfaceRegexs().length != 0);
419
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700420 if (DBG) {
421 mInetLog = new ArrayList();
422 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800423 }
424
TK MUN141623d2011-02-23 18:55:55 +0900425 private NetworkStateTracker makeWimaxStateTracker() {
426 //Initialize Wimax
427 DexClassLoader wimaxClassLoader;
428 Class wimaxStateTrackerClass = null;
429 Class wimaxServiceClass = null;
430 Class wimaxManagerClass;
431 String wimaxJarLocation;
432 String wimaxLibLocation;
433 String wimaxManagerClassName;
434 String wimaxServiceClassName;
435 String wimaxStateTrackerClassName;
436
437 NetworkStateTracker wimaxStateTracker = null;
438
439 boolean isWimaxEnabled = mContext.getResources().getBoolean(
440 com.android.internal.R.bool.config_wimaxEnabled);
441
442 if (isWimaxEnabled) {
443 try {
444 wimaxJarLocation = mContext.getResources().getString(
445 com.android.internal.R.string.config_wimaxServiceJarLocation);
446 wimaxLibLocation = mContext.getResources().getString(
447 com.android.internal.R.string.config_wimaxNativeLibLocation);
448 wimaxManagerClassName = mContext.getResources().getString(
449 com.android.internal.R.string.config_wimaxManagerClassname);
450 wimaxServiceClassName = mContext.getResources().getString(
451 com.android.internal.R.string.config_wimaxServiceClassname);
452 wimaxStateTrackerClassName = mContext.getResources().getString(
453 com.android.internal.R.string.config_wimaxStateTrackerClassname);
454
455 wimaxClassLoader = new DexClassLoader(wimaxJarLocation,
456 new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
457 wimaxLibLocation,ClassLoader.getSystemClassLoader());
458
459 try {
460 wimaxManagerClass = wimaxClassLoader.loadClass(wimaxManagerClassName);
461 wimaxStateTrackerClass = wimaxClassLoader.loadClass(wimaxStateTrackerClassName);
462 wimaxServiceClass = wimaxClassLoader.loadClass(wimaxServiceClassName);
463 } catch (ClassNotFoundException ex) {
464 ex.printStackTrace();
465 return null;
466 }
467 } catch(Resources.NotFoundException ex) {
468 Slog.e(TAG, "Wimax Resources does not exist!!! ");
469 return null;
470 }
471
472 try {
473 Slog.v(TAG, "Starting Wimax Service... ");
474
475 Constructor wmxStTrkrConst = wimaxStateTrackerClass.getConstructor
476 (new Class[] {Context.class,Handler.class});
477 wimaxStateTracker = (NetworkStateTracker)wmxStTrkrConst.newInstance(mContext,mHandler);
478
479 Constructor wmxSrvConst = wimaxServiceClass.getDeclaredConstructor
480 (new Class[] {Context.class,wimaxStateTrackerClass});
481 wmxSrvConst.setAccessible(true);
482 IBinder svcInvoker = (IBinder) wmxSrvConst.newInstance(mContext,wimaxStateTracker);
483 wmxSrvConst.setAccessible(false);
484
485 ServiceManager.addService(WimaxManagerConstants.WIMAX_SERVICE, svcInvoker);
486
487 } catch(ClassCastException ex) {
488 ex.printStackTrace();
489 return null;
490 } catch (NoSuchMethodException ex) {
491 ex.printStackTrace();
492 return null;
493 } catch (InstantiationException ex) {
494 ex.printStackTrace();
495 return null;
496 } catch(IllegalAccessException ex) {
497 ex.printStackTrace();
498 return null;
499 } catch(InvocationTargetException ex) {
500 ex.printStackTrace();
501 return null;
502 } catch(Exception ex) {
503 ex.printStackTrace();
504 return null;
505 }
506 } else {
507 Slog.e(TAG, "Wimax is not enabled or not added to the network attributes!!! ");
508 return null;
509 }
510
511 return wimaxStateTracker;
512 }
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700513
The Android Open Source Project28527d22009-03-03 19:31:44 -0800514 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700515 * Sets the preferred network.
The Android Open Source Project28527d22009-03-03 19:31:44 -0800516 * @param preference the new preference
517 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700518 public void setNetworkPreference(int preference) {
The Android Open Source Project28527d22009-03-03 19:31:44 -0800519 enforceChangePermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700520
521 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
The Android Open Source Project28527d22009-03-03 19:31:44 -0800522 }
523
524 public int getNetworkPreference() {
525 enforceAccessPermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700526 int preference;
527 synchronized(this) {
528 preference = mNetworkPreference;
529 }
530 return preference;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800531 }
532
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700533 private void handleSetNetworkPreference(int preference) {
534 if (ConnectivityManager.isNetworkTypeValid(preference) &&
535 mNetAttributes[preference] != null &&
536 mNetAttributes[preference].isDefault()) {
537 if (mNetworkPreference != preference) {
538 final ContentResolver cr = mContext.getContentResolver();
539 Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference);
540 synchronized(this) {
541 mNetworkPreference = preference;
542 }
543 enforcePreference();
544 }
545 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800546 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700547
The Android Open Source Project28527d22009-03-03 19:31:44 -0800548 private int getPersistedNetworkPreference() {
549 final ContentResolver cr = mContext.getContentResolver();
550
551 final int networkPrefSetting = Settings.Secure
552 .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
553 if (networkPrefSetting != -1) {
554 return networkPrefSetting;
555 }
556
557 return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
558 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700559
The Android Open Source Project28527d22009-03-03 19:31:44 -0800560 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700561 * Make the state of network connectivity conform to the preference settings
The Android Open Source Project28527d22009-03-03 19:31:44 -0800562 * In this method, we only tear down a non-preferred network. Establishing
563 * a connection to the preferred network is taken care of when we handle
564 * the disconnect event from the non-preferred network
565 * (see {@link #handleDisconnect(NetworkInfo)}).
566 */
567 private void enforcePreference() {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700568 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
The Android Open Source Project28527d22009-03-03 19:31:44 -0800569 return;
570
Robert Greenwalt2034b912009-08-12 16:08:25 -0700571 if (!mNetTrackers[mNetworkPreference].isAvailable())
572 return;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800573
Robert Greenwalt2034b912009-08-12 16:08:25 -0700574 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700575 if (t != mNetworkPreference && mNetTrackers[t] != null &&
Robert Greenwalt2034b912009-08-12 16:08:25 -0700576 mNetTrackers[t].getNetworkInfo().isConnected()) {
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700577 if (DBG) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800578 Slog.d(TAG, "tearing down " +
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700579 mNetTrackers[t].getNetworkInfo() +
580 " in enforcePreference");
581 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700582 teardown(mNetTrackers[t]);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800583 }
584 }
585 }
586
587 private boolean teardown(NetworkStateTracker netTracker) {
588 if (netTracker.teardown()) {
589 netTracker.setTeardownRequested(true);
590 return true;
591 } else {
592 return false;
593 }
594 }
595
596 /**
597 * Return NetworkInfo for the active (i.e., connected) network interface.
598 * It is assumed that at most one network is active at a time. If more
599 * than one is active, it is indeterminate which will be returned.
Robert Greenwalt0659da32009-07-16 17:21:39 -0700600 * @return the info for the active network, or {@code null} if none is
601 * active
The Android Open Source Project28527d22009-03-03 19:31:44 -0800602 */
603 public NetworkInfo getActiveNetworkInfo() {
604 enforceAccessPermission();
Robert Greenwalta71471b2011-03-24 21:41:41 -0700605 if (mActiveDefaultNetwork != -1) {
606 return mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800607 }
608 return null;
609 }
610
611 public NetworkInfo getNetworkInfo(int networkType) {
612 enforceAccessPermission();
613 if (ConnectivityManager.isNetworkTypeValid(networkType)) {
614 NetworkStateTracker t = mNetTrackers[networkType];
615 if (t != null)
616 return t.getNetworkInfo();
617 }
618 return null;
619 }
620
621 public NetworkInfo[] getAllNetworkInfo() {
622 enforceAccessPermission();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700623 NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
The Android Open Source Project28527d22009-03-03 19:31:44 -0800624 int i = 0;
625 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700626 if(t != null) result[i++] = t.getNetworkInfo();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800627 }
628 return result;
629 }
630
631 public boolean setRadios(boolean turnOn) {
632 boolean result = true;
633 enforceChangePermission();
634 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700635 if (t != null) result = t.setRadio(turnOn) && result;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800636 }
637 return result;
638 }
639
640 public boolean setRadio(int netType, boolean turnOn) {
641 enforceChangePermission();
642 if (!ConnectivityManager.isNetworkTypeValid(netType)) {
643 return false;
644 }
645 NetworkStateTracker tracker = mNetTrackers[netType];
646 return tracker != null && tracker.setRadio(turnOn);
647 }
648
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700649 /**
650 * Used to notice when the calling process dies so we can self-expire
651 *
652 * Also used to know if the process has cleaned up after itself when
653 * our auto-expire timer goes off. The timer has a link to an object.
654 *
655 */
Robert Greenwalt2034b912009-08-12 16:08:25 -0700656 private class FeatureUser implements IBinder.DeathRecipient {
657 int mNetworkType;
658 String mFeature;
659 IBinder mBinder;
660 int mPid;
661 int mUid;
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800662 long mCreateTime;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700663
664 FeatureUser(int type, String feature, IBinder binder) {
665 super();
666 mNetworkType = type;
667 mFeature = feature;
668 mBinder = binder;
669 mPid = getCallingPid();
670 mUid = getCallingUid();
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800671 mCreateTime = System.currentTimeMillis();
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700672
Robert Greenwalt2034b912009-08-12 16:08:25 -0700673 try {
674 mBinder.linkToDeath(this, 0);
675 } catch (RemoteException e) {
676 binderDied();
677 }
678 }
679
680 void unlinkDeathRecipient() {
681 mBinder.unlinkToDeath(this, 0);
682 }
683
684 public void binderDied() {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800685 Slog.d(TAG, "ConnectivityService FeatureUser binderDied(" +
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800686 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
687 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700688 stopUsingNetworkFeature(this, false);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700689 }
690
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700691 public void expire() {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800692 Slog.d(TAG, "ConnectivityService FeatureUser expire(" +
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800693 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
694 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700695 stopUsingNetworkFeature(this, false);
696 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800697
698 public String toString() {
699 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
700 (System.currentTimeMillis() - mCreateTime) + " mSec ago";
701 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700702 }
703
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700704 // javadoc from interface
Robert Greenwalt2034b912009-08-12 16:08:25 -0700705 public int startUsingNetworkFeature(int networkType, String feature,
706 IBinder binder) {
707 if (DBG) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800708 Slog.d(TAG, "startUsingNetworkFeature for net " + networkType +
Robert Greenwalt2034b912009-08-12 16:08:25 -0700709 ": " + feature);
710 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800711 enforceChangePermission();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700712 if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
713 mNetAttributes[networkType] == null) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700714 return Phone.APN_REQUEST_FAILED;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800715 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700716
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700717 FeatureUser f = new FeatureUser(networkType, feature, binder);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700718
719 // TODO - move this into the MobileDataStateTracker
720 int usedNetworkType = networkType;
721 if(networkType == ConnectivityManager.TYPE_MOBILE) {
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800722 if (!getMobileDataEnabled()) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800723 if (DBG) Slog.d(TAG, "requested special network with data disabled - rejected");
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800724 return Phone.APN_TYPE_NOT_AVAILABLE;
725 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700726 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
727 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
728 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
729 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
730 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
731 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
732 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
733 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
734 }
735 }
736 NetworkStateTracker network = mNetTrackers[usedNetworkType];
737 if (network != null) {
738 if (usedNetworkType != networkType) {
739 Integer currentPid = new Integer(getCallingPid());
740
741 NetworkStateTracker radio = mNetTrackers[networkType];
742 NetworkInfo ni = network.getNetworkInfo();
743
744 if (ni.isAvailable() == false) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800745 if (DBG) Slog.d(TAG, "special network not available");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700746 return Phone.APN_TYPE_NOT_AVAILABLE;
747 }
748
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700749 synchronized(this) {
750 mFeatureUsers.add(f);
751 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
752 // this gets used for per-pid dns when connected
753 mNetRequestersPids[usedNetworkType].add(currentPid);
754 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700755 }
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700756 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK,
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700757 f), getRestoreDefaultNetworkDelay());
758
Robert Greenwalt2034b912009-08-12 16:08:25 -0700759
Robert Greenwalta52c75a2009-08-19 20:19:33 -0700760 if ((ni.isConnectedOrConnecting() == true) &&
761 !network.isTeardownRequested()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700762 if (ni.isConnected() == true) {
763 // add the pid-specific dns
Robert Greenwalt0ef68752010-08-13 14:16:12 -0700764 handleDnsConfigurationChange(networkType);
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800765 if (DBG) Slog.d(TAG, "special network already active");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700766 return Phone.APN_ALREADY_ACTIVE;
767 }
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800768 if (DBG) Slog.d(TAG, "special network already connecting");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700769 return Phone.APN_REQUEST_STARTED;
770 }
771
772 // check if the radio in play can make another contact
773 // assume if cannot for now
774
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800775 if (DBG) Slog.d(TAG, "reconnecting to special network");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700776 network.reconnect();
777 return Phone.APN_REQUEST_STARTED;
778 } else {
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700779 synchronized(this) {
780 mFeatureUsers.add(f);
781 }
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700782 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK,
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700783 f), getRestoreDefaultNetworkDelay());
784
Robert Greenwalt2034b912009-08-12 16:08:25 -0700785 return network.startUsingNetworkFeature(feature,
786 getCallingPid(), getCallingUid());
787 }
788 }
789 return Phone.APN_TYPE_NOT_AVAILABLE;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800790 }
791
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700792 // javadoc from interface
The Android Open Source Project28527d22009-03-03 19:31:44 -0800793 public int stopUsingNetworkFeature(int networkType, String feature) {
Robert Greenwalt28f43012009-10-06 17:52:40 -0700794 enforceChangePermission();
795
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700796 int pid = getCallingPid();
797 int uid = getCallingUid();
798
799 FeatureUser u = null;
800 boolean found = false;
801
802 synchronized(this) {
803 for (int i = 0; i < mFeatureUsers.size() ; i++) {
804 u = (FeatureUser)mFeatureUsers.get(i);
805 if (uid == u.mUid && pid == u.mPid &&
806 networkType == u.mNetworkType &&
807 TextUtils.equals(feature, u.mFeature)) {
808 found = true;
809 break;
810 }
811 }
812 }
813 if (found && u != null) {
814 // stop regardless of how many other time this proc had called start
815 return stopUsingNetworkFeature(u, true);
816 } else {
817 // none found!
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800818 if (DBG) Slog.d(TAG, "ignoring stopUsingNetworkFeature - not a live request");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700819 return 1;
820 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700821 }
822
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700823 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
824 int networkType = u.mNetworkType;
825 String feature = u.mFeature;
826 int pid = u.mPid;
827 int uid = u.mUid;
828
829 NetworkStateTracker tracker = null;
830 boolean callTeardown = false; // used to carry our decision outside of sync block
831
Robert Greenwalt2034b912009-08-12 16:08:25 -0700832 if (DBG) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800833 Slog.d(TAG, "stopUsingNetworkFeature for net " + networkType +
Robert Greenwalt2034b912009-08-12 16:08:25 -0700834 ": " + feature);
835 }
Robert Greenwalt28f43012009-10-06 17:52:40 -0700836
The Android Open Source Project28527d22009-03-03 19:31:44 -0800837 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
838 return -1;
839 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700840
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700841 // need to link the mFeatureUsers list with the mNetRequestersPids state in this
842 // sync block
843 synchronized(this) {
844 // check if this process still has an outstanding start request
845 if (!mFeatureUsers.contains(u)) {
Robert Greenwalt46ceefa2010-03-10 16:10:43 -0800846 if (DBG) Slog.d(TAG, "ignoring - this process has no outstanding requests");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700847 return 1;
848 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700849 u.unlinkDeathRecipient();
850 mFeatureUsers.remove(mFeatureUsers.indexOf(u));
851 // If we care about duplicate requests, check for that here.
852 //
853 // This is done to support the extension of a request - the app
854 // can request we start the network feature again and renew the
855 // auto-shutoff delay. Normal "stop" calls from the app though
856 // do not pay attention to duplicate requests - in effect the
857 // API does not refcount and a single stop will counter multiple starts.
858 if (ignoreDups == false) {
859 for (int i = 0; i < mFeatureUsers.size() ; i++) {
860 FeatureUser x = (FeatureUser)mFeatureUsers.get(i);
861 if (x.mUid == u.mUid && x.mPid == u.mPid &&
862 x.mNetworkType == u.mNetworkType &&
863 TextUtils.equals(x.mFeature, u.mFeature)) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800864 if (DBG) Slog.d(TAG, "ignoring stopUsingNetworkFeature as dup is found");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700865 return 1;
866 }
867 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700868 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700869
870 // TODO - move to MobileDataStateTracker
871 int usedNetworkType = networkType;
872 if (networkType == ConnectivityManager.TYPE_MOBILE) {
873 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
874 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
875 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
876 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
877 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
878 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
879 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
880 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
881 }
882 }
883 tracker = mNetTrackers[usedNetworkType];
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700884 if (tracker == null) {
Robert Greenwalt46ceefa2010-03-10 16:10:43 -0800885 if (DBG) Slog.d(TAG, "ignoring - no known tracker for net type " + usedNetworkType);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700886 return -1;
887 }
888 if (usedNetworkType != networkType) {
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700889 Integer currentPid = new Integer(pid);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700890 mNetRequestersPids[usedNetworkType].remove(currentPid);
Robert Greenwalt0ca68a02009-12-17 14:54:59 -0800891 reassessPidDns(pid, true);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700892 if (mNetRequestersPids[usedNetworkType].size() != 0) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -0800893 if (DBG) Slog.d(TAG, "not tearing down special network - " +
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700894 "others still using it");
895 return 1;
896 }
897 callTeardown = true;
898 }
899 }
Robert Greenwalt46ceefa2010-03-10 16:10:43 -0800900 if (DBG) Slog.d(TAG, "Doing network teardown");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700901 if (callTeardown) {
902 tracker.teardown();
Robert Greenwalt2034b912009-08-12 16:08:25 -0700903 return 1;
904 } else {
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700905 // do it the old fashioned way
Robert Greenwalt2034b912009-08-12 16:08:25 -0700906 return tracker.stopUsingNetworkFeature(feature, pid, uid);
907 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800908 }
909
910 /**
Banavathu, Srinivas Naik7601f572010-08-10 20:13:53 +0530911 * @deprecated use requestRouteToHostAddress instead
912 *
The Android Open Source Project28527d22009-03-03 19:31:44 -0800913 * Ensure that a network route exists to deliver traffic to the specified
914 * host via the specified network interface.
Robert Greenwalt0659da32009-07-16 17:21:39 -0700915 * @param networkType the type of the network over which traffic to the
916 * specified host is to be routed
917 * @param hostAddress the IP address of the host to which the route is
918 * desired
The Android Open Source Project28527d22009-03-03 19:31:44 -0800919 * @return {@code true} on success, {@code false} on failure
920 */
921 public boolean requestRouteToHost(int networkType, int hostAddress) {
Banavathu, Srinivas Naik7601f572010-08-10 20:13:53 +0530922 InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
923
924 if (inetAddress == null) {
925 return false;
926 }
927
928 return requestRouteToHostAddress(networkType, inetAddress.getAddress());
929 }
930
931 /**
932 * Ensure that a network route exists to deliver traffic to the specified
933 * host via the specified network interface.
934 * @param networkType the type of the network over which traffic to the
935 * specified host is to be routed
936 * @param hostAddress the IP address of the host to which the route is
937 * desired
938 * @return {@code true} on success, {@code false} on failure
939 */
940 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
The Android Open Source Project28527d22009-03-03 19:31:44 -0800941 enforceChangePermission();
942 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
943 return false;
944 }
945 NetworkStateTracker tracker = mNetTrackers[networkType];
Robert Greenwalt4666ed02009-09-10 15:06:20 -0700946
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700947 if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
948 tracker.isTeardownRequested()) {
Robert Greenwalt4666ed02009-09-10 15:06:20 -0700949 if (DBG) {
Banavathu, Srinivas Naik7601f572010-08-10 20:13:53 +0530950 Slog.d(TAG, "requestRouteToHostAddress on down network " +
951 "(" + networkType + ") - dropped");
Robert Greenwalt4666ed02009-09-10 15:06:20 -0700952 }
953 return false;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800954 }
Banavathu, Srinivas Naik7601f572010-08-10 20:13:53 +0530955
956 try {
957 InetAddress inetAddress = InetAddress.getByAddress(hostAddress);
958 return tracker.requestRouteToHost(inetAddress);
959 } catch (UnknownHostException e) {
960 return false;
961 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800962 }
963
964 /**
965 * @see ConnectivityManager#getBackgroundDataSetting()
966 */
967 public boolean getBackgroundDataSetting() {
968 return Settings.Secure.getInt(mContext.getContentResolver(),
969 Settings.Secure.BACKGROUND_DATA, 1) == 1;
970 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700971
The Android Open Source Project28527d22009-03-03 19:31:44 -0800972 /**
973 * @see ConnectivityManager#setBackgroundDataSetting(boolean)
974 */
975 public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) {
976 mContext.enforceCallingOrSelfPermission(
977 android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
978 "ConnectivityService");
Robert Greenwalt0659da32009-07-16 17:21:39 -0700979
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700980 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA,
981 (allowBackgroundDataUsage ? ENABLED : DISABLED), 0));
982 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800983
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700984 private void handleSetBackgroundData(boolean enabled) {
985 if (enabled != getBackgroundDataSetting()) {
986 Settings.Secure.putInt(mContext.getContentResolver(),
987 Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0);
988 Intent broadcast = new Intent(
989 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
990 mContext.sendBroadcast(broadcast);
991 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700992 }
993
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -0800994 /**
995 * @see ConnectivityManager#getMobileDataEnabled()
996 */
997 public boolean getMobileDataEnabled() {
998 enforceAccessPermission();
999 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
1000 Settings.Secure.MOBILE_DATA, 1) == 1;
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001001 if (DBG) Slog.d(TAG, "getMobileDataEnabled returning " + retVal);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001002 return retVal;
1003 }
1004
1005 /**
1006 * @see ConnectivityManager#setMobileDataEnabled(boolean)
1007 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001008 public void setMobileDataEnabled(boolean enabled) {
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001009 enforceChangePermission();
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001010 if (DBG) Slog.d(TAG, "setMobileDataEnabled(" + enabled + ")");
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001011
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001012 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
1013 (enabled ? ENABLED : DISABLED), 0));
1014 }
1015
1016 private void handleSetMobileData(boolean enabled) {
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001017 if (getMobileDataEnabled() == enabled) return;
1018
1019 Settings.Secure.putInt(mContext.getContentResolver(),
1020 Settings.Secure.MOBILE_DATA, enabled ? 1 : 0);
1021
1022 if (enabled) {
1023 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001024 if (DBG) {
1025 Slog.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]);
1026 }
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001027 mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect();
1028 }
TK MUNdc9a5352011-03-30 09:27:07 +09001029 if (mNetTrackers[ConnectivityManager.TYPE_WIMAX] != null) {
1030 if (DBG) {
1031 Slog.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_WIMAX]);
1032 }
1033 mNetTrackers[ConnectivityManager.TYPE_WIMAX].reconnect();
1034 }
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001035 } else {
1036 for (NetworkStateTracker nt : mNetTrackers) {
1037 if (nt == null) continue;
1038 int netType = nt.getNetworkInfo().getType();
1039 if (mNetAttributes[netType].mRadio == ConnectivityManager.TYPE_MOBILE) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001040 if (DBG) Slog.d(TAG, "tearing down " + nt);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001041 nt.teardown();
1042 }
1043 }
TK MUNdc9a5352011-03-30 09:27:07 +09001044 if (mNetTrackers[ConnectivityManager.TYPE_WIMAX] != null) {
1045 mNetTrackers[ConnectivityManager.TYPE_WIMAX].teardown();
1046 }
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001047 }
1048 }
1049
The Android Open Source Project28527d22009-03-03 19:31:44 -08001050 private int getNumConnectedNetworks() {
1051 int numConnectedNets = 0;
1052
1053 for (NetworkStateTracker nt : mNetTrackers) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001054 if (nt != null && nt.getNetworkInfo().isConnected() &&
Robert Greenwalt0659da32009-07-16 17:21:39 -07001055 !nt.isTeardownRequested()) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001056 ++numConnectedNets;
1057 }
1058 }
1059 return numConnectedNets;
1060 }
1061
1062 private void enforceAccessPermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001063 mContext.enforceCallingOrSelfPermission(
1064 android.Manifest.permission.ACCESS_NETWORK_STATE,
1065 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001066 }
1067
1068 private void enforceChangePermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001069 mContext.enforceCallingOrSelfPermission(
1070 android.Manifest.permission.CHANGE_NETWORK_STATE,
1071 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001072 }
1073
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001074 // TODO Make this a special check when it goes public
1075 private void enforceTetherChangePermission() {
1076 mContext.enforceCallingOrSelfPermission(
1077 android.Manifest.permission.CHANGE_NETWORK_STATE,
1078 "ConnectivityService");
1079 }
1080
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001081 private void enforceTetherAccessPermission() {
1082 mContext.enforceCallingOrSelfPermission(
1083 android.Manifest.permission.ACCESS_NETWORK_STATE,
1084 "ConnectivityService");
1085 }
1086
The Android Open Source Project28527d22009-03-03 19:31:44 -08001087 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -07001088 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
1089 * network, we ignore it. If it is for the active network, we send out a
1090 * broadcast. But first, we check whether it might be possible to connect
1091 * to a different network.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001092 * @param info the {@code NetworkInfo} for the network
1093 */
1094 private void handleDisconnect(NetworkInfo info) {
1095
Robert Greenwalt2034b912009-08-12 16:08:25 -07001096 int prevNetType = info.getType();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001097
Robert Greenwalt2034b912009-08-12 16:08:25 -07001098 mNetTrackers[prevNetType].setTeardownRequested(false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001099 /*
1100 * If the disconnected network is not the active one, then don't report
1101 * this as a loss of connectivity. What probably happened is that we're
1102 * getting the disconnect for a network that we explicitly disabled
1103 * in accordance with network preference policies.
1104 */
Robert Greenwalt2034b912009-08-12 16:08:25 -07001105 if (!mNetAttributes[prevNetType].isDefault()) {
1106 List pids = mNetRequestersPids[prevNetType];
1107 for (int i = 0; i<pids.size(); i++) {
1108 Integer pid = (Integer)pids.get(i);
1109 // will remove them because the net's no longer connected
1110 // need to do this now as only now do we know the pids and
1111 // can properly null things that are no longer referenced.
1112 reassessPidDns(pid.intValue(), false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001113 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001114 }
1115
The Android Open Source Project28527d22009-03-03 19:31:44 -08001116 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1117 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1118 if (info.isFailover()) {
1119 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1120 info.setFailover(false);
1121 }
1122 if (info.getReason() != null) {
1123 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1124 }
1125 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001126 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1127 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001128 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001129
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001130 if (mNetAttributes[prevNetType].isDefault()) {
Robert Greenwalt9e081592011-03-10 16:58:31 -08001131 tryFailover(prevNetType);
1132 if (mActiveDefaultNetwork != -1) {
1133 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001134 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1135 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001136 mDefaultInetConditionPublished = 0; // we're not connected anymore
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001137 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1138 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001139 }
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001140 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001141 // do this before we broadcast the change
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001142 handleConnectivityChange(prevNetType);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001143
1144 sendStickyBroadcast(intent);
1145 /*
1146 * If the failover network is already connected, then immediately send
1147 * out a followup broadcast indicating successful failover
1148 */
Robert Greenwalt9e081592011-03-10 16:58:31 -08001149 if (mActiveDefaultNetwork != -1) {
1150 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001151 }
1152 }
1153
Robert Greenwalt9e081592011-03-10 16:58:31 -08001154 private void tryFailover(int prevNetType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001155 /*
1156 * If this is a default network, check if other defaults are available
1157 * or active
1158 */
Robert Greenwalt2034b912009-08-12 16:08:25 -07001159 if (mNetAttributes[prevNetType].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001160 if (mActiveDefaultNetwork == prevNetType) {
1161 mActiveDefaultNetwork = -1;
1162 }
1163
Robert Greenwalt72451bf2010-02-25 12:04:29 -08001164 boolean noMobileData = !getMobileDataEnabled();
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001165 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001166 if (checkType == prevNetType) continue;
1167 if (mNetAttributes[checkType] == null) continue;
Robert Greenwalt084e4772011-02-11 17:32:58 -08001168 if (mNetAttributes[checkType].isDefault() == false) continue;
Robert Greenwalt72451bf2010-02-25 12:04:29 -08001169 if (mNetAttributes[checkType].mRadio == ConnectivityManager.TYPE_MOBILE &&
1170 noMobileData) {
Robert Greenwalte981bc52010-10-08 16:35:52 -07001171 Slog.e(TAG, "not failing over to mobile type " + checkType +
1172 " because Mobile Data Disabled");
Robert Greenwalt72451bf2010-02-25 12:04:29 -08001173 continue;
1174 }
TK MUNdc9a5352011-03-30 09:27:07 +09001175 if (mNetAttributes[checkType].mRadio == ConnectivityManager.TYPE_WIMAX &&
1176 noMobileData) {
1177 Slog.e(TAG, "not failing over to mobile type " + checkType +
1178 " because Mobile Data Disabled");
1179 continue;
1180 }
Robert Greenwalt9e081592011-03-10 16:58:31 -08001181 NetworkStateTracker checkTracker = mNetTrackers[checkType];
1182 NetworkInfo checkInfo = checkTracker.getNetworkInfo();
1183 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
1184 checkInfo.setFailover(true);
1185 checkTracker.reconnect();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001186 }
Robert Greenwalt9e081592011-03-10 16:58:31 -08001187 if (DBG) Slog.d(TAG, "Attempting to switch to " + checkInfo.getTypeName());
Robert Greenwalt2034b912009-08-12 16:08:25 -07001188 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001189 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001190 }
1191
1192 private void sendConnectedBroadcast(NetworkInfo info) {
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001193 sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION);
1194 }
1195
1196 private void sendInetConditionBroadcast(NetworkInfo info) {
1197 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1198 }
1199
1200 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1201 Intent intent = new Intent(bcastType);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001202 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1203 if (info.isFailover()) {
1204 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1205 info.setFailover(false);
1206 }
1207 if (info.getReason() != null) {
1208 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1209 }
1210 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001211 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1212 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001213 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07001214 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001215 sendStickyBroadcast(intent);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001216 }
1217
1218 /**
1219 * Called when an attempt to fail over to another network has failed.
1220 * @param info the {@link NetworkInfo} for the failed network
1221 */
1222 private void handleConnectionFailure(NetworkInfo info) {
1223 mNetTrackers[info.getType()].setTeardownRequested(false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001224
Robert Greenwalt2034b912009-08-12 16:08:25 -07001225 String reason = info.getReason();
1226 String extraInfo = info.getExtraInfo();
Robert Greenwalt0659da32009-07-16 17:21:39 -07001227
Robert Greenwalte981bc52010-10-08 16:35:52 -07001228 String reasonText;
1229 if (reason == null) {
1230 reasonText = ".";
1231 } else {
1232 reasonText = " (" + reason + ").";
The Android Open Source Project28527d22009-03-03 19:31:44 -08001233 }
Robert Greenwalte981bc52010-10-08 16:35:52 -07001234 Slog.e(TAG, "Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001235
1236 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1237 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1238 if (getActiveNetworkInfo() == null) {
1239 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1240 }
1241 if (reason != null) {
1242 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
1243 }
1244 if (extraInfo != null) {
1245 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
1246 }
1247 if (info.isFailover()) {
1248 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1249 info.setFailover(false);
1250 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001251
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001252 if (mNetAttributes[info.getType()].isDefault()) {
Robert Greenwalt9e081592011-03-10 16:58:31 -08001253 tryFailover(info.getType());
1254 if (mActiveDefaultNetwork != -1) {
1255 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001256 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1257 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001258 mDefaultInetConditionPublished = 0;
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001259 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1260 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001261 }
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001262
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001263 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001264 sendStickyBroadcast(intent);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001265 /*
1266 * If the failover network is already connected, then immediately send
1267 * out a followup broadcast indicating successful failover
1268 */
Robert Greenwalt9e081592011-03-10 16:58:31 -08001269 if (mActiveDefaultNetwork != -1) {
1270 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001271 }
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001272 }
1273
1274 private void sendStickyBroadcast(Intent intent) {
1275 synchronized(this) {
Dianne Hackborna417ff82009-12-08 19:45:14 -08001276 if (!mSystemReady) {
1277 mInitialBroadcast = new Intent(intent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001278 }
Dianne Hackborna417ff82009-12-08 19:45:14 -08001279 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1280 mContext.sendStickyBroadcast(intent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001281 }
1282 }
1283
1284 void systemReady() {
Robert Greenwalt44cc4742011-05-20 14:35:50 -07001285 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1286 mNetd = INetworkManagementService.Stub.asInterface(b);
1287
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001288 synchronized(this) {
1289 mSystemReady = true;
Dianne Hackborna417ff82009-12-08 19:45:14 -08001290 if (mInitialBroadcast != null) {
1291 mContext.sendStickyBroadcast(mInitialBroadcast);
1292 mInitialBroadcast = null;
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001293 }
1294 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001295 }
1296
1297 private void handleConnect(NetworkInfo info) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001298 int type = info.getType();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001299
1300 // snapshot isFailover, because sendConnectedBroadcast() resets it
1301 boolean isFailover = info.isFailover();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001302 NetworkStateTracker thisNet = mNetTrackers[type];
The Android Open Source Project28527d22009-03-03 19:31:44 -08001303
Robert Greenwalt2034b912009-08-12 16:08:25 -07001304 // if this is a default net and other default is running
1305 // kill the one not preferred
1306 if (mNetAttributes[type].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001307 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
1308 if ((type != mNetworkPreference &&
1309 mNetAttributes[mActiveDefaultNetwork].mPriority >
1310 mNetAttributes[type].mPriority) ||
1311 mNetworkPreference == mActiveDefaultNetwork) {
1312 // don't accept this one
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001313 if (DBG) Slog.v(TAG, "Not broadcasting CONNECT_ACTION " +
Robert Greenwalt2034b912009-08-12 16:08:25 -07001314 "to torn down network " + info.getTypeName());
1315 teardown(thisNet);
1316 return;
1317 } else {
1318 // tear down the other
1319 NetworkStateTracker otherNet =
1320 mNetTrackers[mActiveDefaultNetwork];
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001321 if (DBG) Slog.v(TAG, "Policy requires " +
Robert Greenwalt2034b912009-08-12 16:08:25 -07001322 otherNet.getNetworkInfo().getTypeName() +
1323 " teardown");
1324 if (!teardown(otherNet)) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001325 Slog.e(TAG, "Network declined teardown request");
Robert Greenwalt99910172011-03-29 11:36:28 -07001326 teardown(thisNet);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001327 return;
1328 }
1329 if (isFailover) {
1330 otherNet.releaseWakeLock();
1331 }
1332 }
1333 }
1334 mActiveDefaultNetwork = type;
Robert Greenwalt986c7412010-09-08 15:24:47 -07001335 // this will cause us to come up initially as unconnected and switching
1336 // to connected after our normal pause unless somebody reports us as reall
1337 // disconnected
1338 mDefaultInetConditionPublished = 0;
1339 mDefaultConnectionSequence++;
1340 mInetConditionChangeInFlight = false;
1341 // Don't do this - if we never sign in stay, grey
1342 //reportNetworkCondition(mActiveDefaultNetwork, 100);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001343 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001344 thisNet.setTeardownRequested(false);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001345 thisNet.updateNetworkSettings();
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001346 handleConnectivityChange(type);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001347 sendConnectedBroadcast(info);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001348 }
1349
1350 private void handleScanResultsAvailable(NetworkInfo info) {
1351 int networkType = info.getType();
1352 if (networkType != ConnectivityManager.TYPE_WIFI) {
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001353 if (DBG) Slog.v(TAG, "Got ScanResultsAvailable for " +
Robert Greenwalt0659da32009-07-16 17:21:39 -07001354 info.getTypeName() + " network. Don't know how to handle.");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001355 }
Robert Greenwalt0659da32009-07-16 17:21:39 -07001356
The Android Open Source Project28527d22009-03-03 19:31:44 -08001357 mNetTrackers[networkType].interpretScanResultsAvailable();
1358 }
1359
Robert Greenwalt0659da32009-07-16 17:21:39 -07001360 private void handleNotificationChange(boolean visible, int id,
1361 Notification notification) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001362 NotificationManager notificationManager = (NotificationManager) mContext
1363 .getSystemService(Context.NOTIFICATION_SERVICE);
Robert Greenwalt0659da32009-07-16 17:21:39 -07001364
The Android Open Source Project28527d22009-03-03 19:31:44 -08001365 if (visible) {
1366 notificationManager.notify(id, notification);
1367 } else {
1368 notificationManager.cancel(id);
1369 }
1370 }
1371
1372 /**
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001373 * After a change in the connectivity state of any network, We're mainly
1374 * concerned with making sure that the list of DNS servers is setupup
1375 * according to which networks are connected, and ensuring that the
1376 * right routing table entries exist.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001377 */
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001378 private void handleConnectivityChange(int netType) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001379 /*
Robert Greenwalt2034b912009-08-12 16:08:25 -07001380 * If a non-default network is enabled, add the host routes that
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001381 * will allow it's DNS servers to be accessed.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001382 */
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001383 handleDnsConfigurationChange(netType);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001384
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001385 if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
1386 if (mNetAttributes[netType].isDefault()) {
1387 mNetTrackers[netType].addDefaultRoute();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001388 } else {
Robert Greenwalta71471b2011-03-24 21:41:41 -07001389 // many radios add a default route even when we don't want one.
1390 // remove the default interface unless we need it for our active network
1391 if (mActiveDefaultNetwork != -1) {
1392 String defaultIface = mNetTrackers[mActiveDefaultNetwork].getInterfaceName();
1393 if (defaultIface != null &&
1394 !defaultIface.equals(mNetTrackers[netType].getInterfaceName())) {
1395 mNetTrackers[netType].removeDefaultRoute();
1396 }
1397 }
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001398 mNetTrackers[netType].addPrivateDnsRoutes();
1399 }
1400 } else {
1401 if (mNetAttributes[netType].isDefault()) {
1402 mNetTrackers[netType].removeDefaultRoute();
1403 } else {
1404 mNetTrackers[netType].removePrivateDnsRoutes();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001405 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001406 }
1407 }
1408
Robert Greenwalt2034b912009-08-12 16:08:25 -07001409 /**
1410 * Adjust the per-process dns entries (net.dns<x>.<pid>) based
1411 * on the highest priority active net which this process requested.
1412 * If there aren't any, clear it out
1413 */
1414 private void reassessPidDns(int myPid, boolean doBump)
1415 {
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001416 if (DBG) Slog.d(TAG, "reassessPidDns for pid " + myPid);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001417 for(int i : mPriorityList) {
1418 if (mNetAttributes[i].isDefault()) {
1419 continue;
1420 }
1421 NetworkStateTracker nt = mNetTrackers[i];
Robert Greenwalt0659da32009-07-16 17:21:39 -07001422 if (nt.getNetworkInfo().isConnected() &&
1423 !nt.isTeardownRequested()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001424 List pids = mNetRequestersPids[i];
1425 for (int j=0; j<pids.size(); j++) {
1426 Integer pid = (Integer)pids.get(j);
1427 if (pid.intValue() == myPid) {
1428 String[] dnsList = nt.getNameServers();
1429 writePidDns(dnsList, myPid);
1430 if (doBump) {
1431 bumpDns();
1432 }
1433 return;
1434 }
1435 }
1436 }
1437 }
1438 // nothing found - delete
1439 for (int i = 1; ; i++) {
1440 String prop = "net.dns" + i + "." + myPid;
1441 if (SystemProperties.get(prop).length() == 0) {
1442 if (doBump) {
1443 bumpDns();
1444 }
1445 return;
1446 }
1447 SystemProperties.set(prop, "");
1448 }
1449 }
1450
1451 private void writePidDns(String[] dnsList, int pid) {
1452 int j = 1;
1453 for (String dns : dnsList) {
1454 if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
1455 SystemProperties.set("net.dns" + j++ + "." + pid, dns);
1456 }
1457 }
1458 }
1459
1460 private void bumpDns() {
1461 /*
1462 * Bump the property that tells the name resolver library to reread
1463 * the DNS server list from the properties.
1464 */
1465 String propVal = SystemProperties.get("net.dnschange");
1466 int n = 0;
1467 if (propVal.length() != 0) {
1468 try {
1469 n = Integer.parseInt(propVal);
1470 } catch (NumberFormatException e) {}
1471 }
1472 SystemProperties.set("net.dnschange", "" + (n+1));
1473 }
1474
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001475 private void handleDnsConfigurationChange(int netType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001476 // add default net's dns entries
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001477 NetworkStateTracker nt = mNetTrackers[netType];
1478 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
1479 String[] dnsList = nt.getNameServers();
Robert Greenwalt44cc4742011-05-20 14:35:50 -07001480 try {
1481 mNetd.setDnsServersForInterface(Integer.toString(netType), dnsList);
1482 } catch (Exception e) {
1483 Slog.e(TAG, "exception setting dns servers: " + e);
1484 }
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001485 if (mNetAttributes[netType].isDefault()) {
1486 int j = 1;
1487 for (String dns : dnsList) {
1488 if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
1489 if (DBG) {
1490 Slog.d(TAG, "adding dns " + dns + " for " +
1491 nt.getNetworkInfo().getTypeName());
Robert Greenwalt2034b912009-08-12 16:08:25 -07001492 }
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001493 SystemProperties.set("net.dns" + j++, dns);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001494 }
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001495 }
Robert Greenwalt44cc4742011-05-20 14:35:50 -07001496 try {
1497 mNetd.setDefaultInterfaceForDns(Integer.toString(netType));
1498 } catch (Exception e) {
1499 Slog.e(TAG, "exception setting default dns interface: " + e);}
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001500 for (int k=j ; k<mNumDnsEntries; k++) {
1501 if (DBG) Slog.d(TAG, "erasing net.dns" + k);
1502 SystemProperties.set("net.dns" + k, "");
1503 }
1504 mNumDnsEntries = j;
1505 } else {
1506 // set per-pid dns for attached secondary nets
1507 List pids = mNetRequestersPids[netType];
1508 for (int y=0; y< pids.size(); y++) {
1509 Integer pid = (Integer)pids.get(y);
1510 writePidDns(dnsList, pid.intValue());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001511 }
1512 }
1513 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001514 bumpDns();
1515 }
1516
1517 private int getRestoreDefaultNetworkDelay() {
1518 String restoreDefaultNetworkDelayStr = SystemProperties.get(
1519 NETWORK_RESTORE_DELAY_PROP_NAME);
1520 if(restoreDefaultNetworkDelayStr != null &&
1521 restoreDefaultNetworkDelayStr.length() != 0) {
1522 try {
1523 return Integer.valueOf(restoreDefaultNetworkDelayStr);
1524 } catch (NumberFormatException e) {
1525 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001526 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001527 return RESTORE_DEFAULT_NETWORK_DELAY;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001528 }
1529
1530 @Override
1531 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001532 if (mContext.checkCallingOrSelfPermission(
1533 android.Manifest.permission.DUMP)
The Android Open Source Project28527d22009-03-03 19:31:44 -08001534 != PackageManager.PERMISSION_GRANTED) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001535 pw.println("Permission Denial: can't dump ConnectivityService " +
1536 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1537 Binder.getCallingUid());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001538 return;
1539 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001540 pw.println();
1541 for (NetworkStateTracker nst : mNetTrackers) {
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08001542 if (nst != null) {
1543 if (nst.getNetworkInfo().isConnected()) {
1544 pw.println("Active network: " + nst.getNetworkInfo().
1545 getTypeName());
1546 }
1547 pw.println(nst.getNetworkInfo());
1548 pw.println(nst);
1549 pw.println();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001550 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001551 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08001552
1553 pw.println("Network Requester Pids:");
1554 for (int net : mPriorityList) {
1555 String pidString = net + ": ";
1556 for (Object pid : mNetRequestersPids[net]) {
1557 pidString = pidString + pid.toString() + ", ";
1558 }
1559 pw.println(pidString);
1560 }
1561 pw.println();
1562
1563 pw.println("FeatureUsers:");
1564 for (Object requester : mFeatureUsers) {
1565 pw.println(requester.toString());
1566 }
1567 pw.println();
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001568
1569 mTethering.dump(fd, pw, args);
Robert Greenwalt0e80be12010-09-20 14:35:25 -07001570
1571 if (mInetLog != null) {
1572 pw.println();
1573 pw.println("Inet condition reports:");
1574 for(int i = 0; i < mInetLog.size(); i++) {
1575 pw.println(mInetLog.get(i));
1576 }
1577 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001578 }
1579
Robert Greenwalt2034b912009-08-12 16:08:25 -07001580 // must be stateless - things change under us.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001581 private class MyHandler extends Handler {
1582 @Override
1583 public void handleMessage(Message msg) {
1584 NetworkInfo info;
1585 switch (msg.what) {
1586 case NetworkStateTracker.EVENT_STATE_CHANGED:
1587 info = (NetworkInfo) msg.obj;
Robert Greenwalt12c44552009-12-07 11:33:18 -08001588 int type = info.getType();
1589 NetworkInfo.State state = info.getState();
Robert Greenwalt24e2d2b2010-01-25 16:14:00 -08001590 // only do this optimization for wifi. It going into scan mode for location
1591 // services generates alot of noise. Meanwhile the mms apn won't send out
1592 // subsequent notifications when on default cellular because it never
1593 // disconnects.. so only do this to wifi notifications. Fixed better when the
1594 // APN notifications are standardized.
1595 if (mNetAttributes[type].mLastState == state &&
1596 mNetAttributes[type].mRadio == ConnectivityManager.TYPE_WIFI) {
Robert Greenwalt12c44552009-12-07 11:33:18 -08001597 if (DBG) {
Robert Greenwalt24e2d2b2010-01-25 16:14:00 -08001598 // TODO - remove this after we validate the dropping doesn't break
1599 // anything
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001600 Slog.d(TAG, "Dropping ConnectivityChange for " +
Robert Greenwalt2adbc7f2010-01-13 09:36:31 -08001601 info.getTypeName() + ": " +
Robert Greenwalt12c44552009-12-07 11:33:18 -08001602 state + "/" + info.getDetailedState());
1603 }
1604 return;
1605 }
1606 mNetAttributes[type].mLastState = state;
1607
Joe Onoratoc2386bb2010-02-26 18:56:32 -08001608 if (DBG) Slog.d(TAG, "ConnectivityChange for " +
Robert Greenwalt0659da32009-07-16 17:21:39 -07001609 info.getTypeName() + ": " +
Robert Greenwalt12c44552009-12-07 11:33:18 -08001610 state + "/" + info.getDetailedState());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001611
1612 // Connectivity state changed:
1613 // [31-13] Reserved for future use
Robert Greenwalt0659da32009-07-16 17:21:39 -07001614 // [12-9] Network subtype (for mobile network, as defined
1615 // by TelephonyManager)
1616 // [8-3] Detailed state ordinal (as defined by
1617 // NetworkInfo.DetailedState)
The Android Open Source Project28527d22009-03-03 19:31:44 -08001618 // [2-0] Network type (as defined by ConnectivityManager)
1619 int eventLogParam = (info.getType() & 0x7) |
1620 ((info.getDetailedState().ordinal() & 0x3f) << 3) |
1621 (info.getSubtype() << 9);
Doug Zongker2fc96232009-12-04 10:31:43 -08001622 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
Robert Greenwalt0659da32009-07-16 17:21:39 -07001623 eventLogParam);
1624
1625 if (info.getDetailedState() ==
1626 NetworkInfo.DetailedState.FAILED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001627 handleConnectionFailure(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08001628 } else if (state == NetworkInfo.State.DISCONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001629 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08001630 } else if (state == NetworkInfo.State.SUSPENDED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001631 // TODO: need to think this over.
Robert Greenwalt0659da32009-07-16 17:21:39 -07001632 // the logic here is, handle SUSPENDED the same as
1633 // DISCONNECTED. The only difference being we are
1634 // broadcasting an intent with NetworkInfo that's
1635 // suspended. This allows the applications an
1636 // opportunity to handle DISCONNECTED and SUSPENDED
1637 // differently, or not.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001638 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08001639 } else if (state == NetworkInfo.State.CONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001640 handleConnect(info);
1641 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001642 break;
1643
1644 case NetworkStateTracker.EVENT_SCAN_RESULTS_AVAILABLE:
1645 info = (NetworkInfo) msg.obj;
1646 handleScanResultsAvailable(info);
1647 break;
Robert Greenwalt0659da32009-07-16 17:21:39 -07001648
The Android Open Source Project28527d22009-03-03 19:31:44 -08001649 case NetworkStateTracker.EVENT_NOTIFICATION_CHANGED:
Robert Greenwalt0659da32009-07-16 17:21:39 -07001650 handleNotificationChange(msg.arg1 == 1, msg.arg2,
1651 (Notification) msg.obj);
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001652 break;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001653
1654 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
Robert Greenwalt0ef68752010-08-13 14:16:12 -07001655 info = (NetworkInfo) msg.obj;
1656 type = info.getType();
1657 handleDnsConfigurationChange(type);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001658 break;
1659
1660 case NetworkStateTracker.EVENT_ROAMING_CHANGED:
1661 // fill me in
1662 break;
1663
1664 case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED:
1665 // fill me in
1666 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001667 case EVENT_RESTORE_DEFAULT_NETWORK:
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001668 FeatureUser u = (FeatureUser)msg.obj;
1669 u.expire();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001670 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001671 case EVENT_INET_CONDITION_CHANGE:
1672 {
1673 int netType = msg.arg1;
1674 int condition = msg.arg2;
1675 handleInetConditionChange(netType, condition);
Robert Greenwalt986c7412010-09-08 15:24:47 -07001676 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001677 }
1678 case EVENT_INET_CONDITION_HOLD_END:
1679 {
1680 int netType = msg.arg1;
1681 int sequence = msg.arg2;
1682 handleInetConditionHoldEnd(netType, sequence);
Robert Greenwalt986c7412010-09-08 15:24:47 -07001683 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001684 }
1685 case EVENT_SET_NETWORK_PREFERENCE:
1686 {
1687 int preference = msg.arg1;
1688 handleSetNetworkPreference(preference);
1689 break;
1690 }
1691 case EVENT_SET_BACKGROUND_DATA:
1692 {
1693 boolean enabled = (msg.arg1 == ENABLED);
1694 handleSetBackgroundData(enabled);
1695 break;
1696 }
1697 case EVENT_SET_MOBILE_DATA:
1698 {
1699 boolean enabled = (msg.arg1 == ENABLED);
1700 handleSetMobileData(enabled);
1701 break;
1702 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001703 }
1704 }
1705 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001706
1707 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001708 public int tether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001709 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001710
1711 if (isTetheringSupported()) {
1712 return mTethering.tether(iface);
1713 } else {
1714 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1715 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001716 }
1717
1718 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001719 public int untether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001720 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001721
1722 if (isTetheringSupported()) {
1723 return mTethering.untether(iface);
1724 } else {
1725 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1726 }
1727 }
1728
1729 // javadoc from interface
1730 public int getLastTetherError(String iface) {
1731 enforceTetherAccessPermission();
1732
1733 if (isTetheringSupported()) {
1734 return mTethering.getLastTetherError(iface);
1735 } else {
1736 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1737 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001738 }
1739
1740 // TODO - proper iface API for selection by property, inspection, etc
1741 public String[] getTetherableUsbRegexs() {
1742 enforceTetherAccessPermission();
1743 if (isTetheringSupported()) {
1744 return mTethering.getTetherableUsbRegexs();
1745 } else {
1746 return new String[0];
1747 }
1748 }
1749
1750 public String[] getTetherableWifiRegexs() {
1751 enforceTetherAccessPermission();
1752 if (isTetheringSupported()) {
1753 return mTethering.getTetherableWifiRegexs();
1754 } else {
1755 return new String[0];
1756 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001757 }
1758
1759 // TODO - move iface listing, queries, etc to new module
1760 // javadoc from interface
1761 public String[] getTetherableIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001762 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001763 return mTethering.getTetherableIfaces();
1764 }
1765
1766 public String[] getTetheredIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001767 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001768 return mTethering.getTetheredIfaces();
1769 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001770
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001771 public String[] getTetheringErroredIfaces() {
1772 enforceTetherAccessPermission();
1773 return mTethering.getErroredIfaces();
1774 }
1775
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001776 // if ro.tether.denied = true we default to no tethering
1777 // gservices could set the secure setting to 1 though to enable it on a build where it
1778 // had previously been turned off.
1779 public boolean isTetheringSupported() {
1780 enforceTetherAccessPermission();
1781 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
Robert Greenwaltf1b66e12010-02-25 12:29:30 -08001782 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
1783 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
1784 return tetherEnabledInSettings && mTetheringConfigValid;
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001785 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07001786
1787 // 100 percent is full good, 0 is full bad.
1788 public void reportInetCondition(int networkType, int percentage) {
1789 if (DBG) Slog.d(TAG, "reportNetworkCondition(" + networkType + ", " + percentage + ")");
1790 mContext.enforceCallingOrSelfPermission(
1791 android.Manifest.permission.STATUS_BAR,
1792 "ConnectivityService");
1793
Robert Greenwalt0e80be12010-09-20 14:35:25 -07001794 if (DBG) {
1795 int pid = getCallingPid();
1796 int uid = getCallingUid();
1797 String s = pid + "(" + uid + ") reports inet is " +
1798 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
1799 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
1800 mInetLog.add(s);
1801 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
1802 mInetLog.remove(0);
1803 }
1804 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07001805 mHandler.sendMessage(mHandler.obtainMessage(
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001806 EVENT_INET_CONDITION_CHANGE, networkType, percentage));
1807 }
1808
1809 private void handleInetConditionChange(int netType, int condition) {
1810 if (DBG) {
1811 Slog.d(TAG, "Inet connectivity change, net=" +
1812 netType + ", condition=" + condition +
1813 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
1814 }
1815 if (mActiveDefaultNetwork == -1) {
1816 if (DBG) Slog.d(TAG, "no active default network - aborting");
1817 return;
1818 }
1819 if (mActiveDefaultNetwork != netType) {
1820 if (DBG) Slog.d(TAG, "given net not default - aborting");
1821 return;
1822 }
1823 mDefaultInetCondition = condition;
1824 int delay;
1825 if (mInetConditionChangeInFlight == false) {
1826 if (DBG) Slog.d(TAG, "starting a change hold");
1827 // setup a new hold to debounce this
1828 if (mDefaultInetCondition > 50) {
1829 delay = Settings.Secure.getInt(mContext.getContentResolver(),
1830 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
1831 } else {
1832 delay = Settings.Secure.getInt(mContext.getContentResolver(),
1833 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
1834 }
1835 mInetConditionChangeInFlight = true;
1836 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
1837 mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
1838 } else {
1839 // we've set the new condition, when this hold ends that will get
1840 // picked up
1841 if (DBG) Slog.d(TAG, "currently in hold - not setting new end evt");
1842 }
1843 }
1844
1845 private void handleInetConditionHoldEnd(int netType, int sequence) {
1846 if (DBG) {
1847 Slog.d(TAG, "Inet hold end, net=" + netType +
1848 ", condition =" + mDefaultInetCondition +
1849 ", published condition =" + mDefaultInetConditionPublished);
1850 }
1851 mInetConditionChangeInFlight = false;
1852
1853 if (mActiveDefaultNetwork == -1) {
1854 if (DBG) Slog.d(TAG, "no active default network - aborting");
1855 return;
1856 }
1857 if (mDefaultConnectionSequence != sequence) {
1858 if (DBG) Slog.d(TAG, "event hold for obsolete network - aborting");
1859 return;
1860 }
1861 if (mDefaultInetConditionPublished == mDefaultInetCondition) {
1862 if (DBG) Slog.d(TAG, "no change in condition - aborting");
1863 return;
1864 }
1865 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
1866 if (networkInfo.isConnected() == false) {
1867 if (DBG) Slog.d(TAG, "default network not connected - aborting");
1868 return;
1869 }
1870 mDefaultInetConditionPublished = mDefaultInetCondition;
1871 sendInetConditionBroadcast(networkInfo);
1872 return;
Robert Greenwalt986c7412010-09-08 15:24:47 -07001873 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001874}