blob: 5f5e1db7f98d0d733ef0a74b66f4a80f4784c0ab [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
Jaikumar Ganesh0db51a02010-12-21 22:31:44 -080019import android.bluetooth.BluetoothTetheringDataTracker;
The Android Open Source Project28527d22009-03-03 19:31:44 -080020import android.content.ContentResolver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.pm.PackageManager;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -070024import android.database.ContentObserver;
The Android Open Source Project28527d22009-03-03 19:31:44 -080025import android.net.ConnectivityManager;
Robert Greenwalteb123ac2010-12-06 13:56:24 -080026import android.net.DummyDataStateTracker;
Benoit Goby6cec7f32010-12-22 14:29:40 -080027import android.net.EthernetDataTracker;
The Android Open Source Project28527d22009-03-03 19:31:44 -080028import android.net.IConnectivityManager;
Jaikumar Ganesh0db51a02010-12-21 22:31:44 -080029import android.net.LinkProperties;
The Android Open Source Project28527d22009-03-03 19:31:44 -080030import android.net.MobileDataStateTracker;
Robert Greenwalt34848c02011-03-25 13:09:25 -070031import android.net.NetworkConfig;
The Android Open Source Project28527d22009-03-03 19:31:44 -080032import android.net.NetworkInfo;
33import android.net.NetworkStateTracker;
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -070034import android.net.NetworkUtils;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -070035import android.net.Proxy;
36import android.net.ProxyProperties;
Robert Greenwalt5a901292011-04-28 14:28:50 -070037import android.net.RouteInfo;
Hung-ying Tyan4e723422011-01-19 16:48:38 +080038import android.net.vpn.VpnManager;
The Android Open Source Project28527d22009-03-03 19:31:44 -080039import android.net.wifi.WifiStateTracker;
40import android.os.Binder;
41import android.os.Handler;
Wink Saville775aad62010-09-02 19:23:52 -070042import android.os.HandlerThread;
Robert Greenwalt2034b912009-08-12 16:08:25 -070043import android.os.IBinder;
The Android Open Source Project28527d22009-03-03 19:31:44 -080044import android.os.Looper;
45import android.os.Message;
Robert Greenwalt93dc1042010-06-15 12:19:37 -070046import android.os.PowerManager;
Robert Greenwalt2034b912009-08-12 16:08:25 -070047import android.os.RemoteException;
The Android Open Source Project28527d22009-03-03 19:31:44 -080048import android.os.ServiceManager;
49import android.os.SystemProperties;
50import android.provider.Settings;
Robert Greenwalt2034b912009-08-12 16:08:25 -070051import android.text.TextUtils;
The Android Open Source Project28527d22009-03-03 19:31:44 -080052import android.util.EventLog;
Joe Onoratoc2386bb2010-02-26 18:56:32 -080053import android.util.Slog;
The Android Open Source Project28527d22009-03-03 19:31:44 -080054
Robert Greenwalt2034b912009-08-12 16:08:25 -070055import com.android.internal.telephony.Phone;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080056import com.android.server.connectivity.Tethering;
57
The Android Open Source Project28527d22009-03-03 19:31:44 -080058import java.io.FileDescriptor;
Irfan Sheriff7f132d92010-06-09 15:39:36 -070059import java.io.FileWriter;
60import java.io.IOException;
The Android Open Source Project28527d22009-03-03 19:31:44 -080061import java.io.PrintWriter;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070062import java.net.InetAddress;
63import java.net.UnknownHostException;
Robert Greenwalt2034b912009-08-12 16:08:25 -070064import java.util.ArrayList;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070065import java.util.Collection;
Robert Greenwaltd62c7002010-12-29 16:15:02 -080066import java.util.concurrent.atomic.AtomicBoolean;
Robert Greenwalt0e80be12010-09-20 14:35:25 -070067import java.util.GregorianCalendar;
Robert Greenwalt2034b912009-08-12 16:08:25 -070068import java.util.List;
The Android Open Source Project28527d22009-03-03 19:31:44 -080069
70/**
71 * @hide
72 */
73public class ConnectivityService extends IConnectivityManager.Stub {
74
Robert Greenwalt063dc7d2010-10-05 19:12:26 -070075 private static final boolean DBG = true;
The Android Open Source Project28527d22009-03-03 19:31:44 -080076 private static final String TAG = "ConnectivityService";
77
Robert Greenwalt2034b912009-08-12 16:08:25 -070078 // how long to wait before switching back to a radio's default network
79 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
80 // system property that can override the above value
81 private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
82 "android.telephony.apn-restore";
83
Robert Greenwaltbd492212011-05-06 17:10:53 -070084 // used in recursive route setting to add gateways for the host for which
85 // a host route was requested.
86 private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10;
87
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080088 private Tethering mTethering;
Robert Greenwaltf1b66e12010-02-25 12:29:30 -080089 private boolean mTetheringConfigValid = false;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080090
The Android Open Source Project28527d22009-03-03 19:31:44 -080091 /**
92 * Sometimes we want to refer to the individual network state
93 * trackers separately, and sometimes we just want to treat them
94 * abstractly.
95 */
96 private NetworkStateTracker mNetTrackers[];
Robert Greenwalt2034b912009-08-12 16:08:25 -070097
98 /**
99 * A per Net list of the PID's that requested access to the net
100 * used both as a refcount and for per-PID DNS selection
101 */
102 private List mNetRequestersPids[];
103
Irfan Sheriff653e2a22010-06-07 09:03:04 -0700104 private WifiWatchdogService mWifiWatchdogService;
105
Robert Greenwalt2034b912009-08-12 16:08:25 -0700106 // priority order of the nettrackers
107 // (excluding dynamically set mNetworkPreference)
108 // TODO - move mNetworkTypePreference into this
109 private int[] mPriorityList;
110
The Android Open Source Project28527d22009-03-03 19:31:44 -0800111 private Context mContext;
112 private int mNetworkPreference;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700113 private int mActiveDefaultNetwork = -1;
Robert Greenwalt986c7412010-09-08 15:24:47 -0700114 // 0 is full bad, 100 is full good
115 private int mDefaultInetCondition = 0;
116 private int mDefaultInetConditionPublished = 0;
117 private boolean mInetConditionChangeInFlight = false;
118 private int mDefaultConnectionSequence = 0;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800119
120 private int mNumDnsEntries;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800121
122 private boolean mTestMode;
Joe Onorato56023ad2010-09-01 21:18:22 -0700123 private static ConnectivityService sServiceInstance;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800124
Robert Greenwaltd62c7002010-12-29 16:15:02 -0800125 private AtomicBoolean mBackgroundDataEnabled = new AtomicBoolean(true);
126
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700127 private static final int ENABLED = 1;
128 private static final int DISABLED = 0;
129
130 // Share the event space with NetworkStateTracker (which can't see this
131 // internal class but sends us events). If you change these, change
132 // NetworkStateTracker.java too.
133 private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1;
134 private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100;
135
136 /**
137 * used internally as a delayed event to make us switch back to the
138 * default network
139 */
140 private static final int EVENT_RESTORE_DEFAULT_NETWORK =
141 MAX_NETWORK_STATE_TRACKER_EVENT + 1;
142
143 /**
144 * used internally to change our mobile data enabled flag
145 */
146 private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED =
147 MAX_NETWORK_STATE_TRACKER_EVENT + 2;
148
149 /**
150 * used internally to change our network preference setting
151 * arg1 = networkType to prefer
152 */
153 private static final int EVENT_SET_NETWORK_PREFERENCE =
154 MAX_NETWORK_STATE_TRACKER_EVENT + 3;
155
156 /**
157 * used internally to synchronize inet condition reports
158 * arg1 = networkType
159 * arg2 = condition (0 bad, 100 good)
160 */
161 private static final int EVENT_INET_CONDITION_CHANGE =
162 MAX_NETWORK_STATE_TRACKER_EVENT + 4;
163
164 /**
165 * used internally to mark the end of inet condition hold periods
166 * arg1 = networkType
167 */
168 private static final int EVENT_INET_CONDITION_HOLD_END =
169 MAX_NETWORK_STATE_TRACKER_EVENT + 5;
170
171 /**
172 * used internally to set the background data preference
173 * arg1 = TRUE for enabled, FALSE for disabled
174 */
175 private static final int EVENT_SET_BACKGROUND_DATA =
176 MAX_NETWORK_STATE_TRACKER_EVENT + 6;
177
178 /**
179 * used internally to set enable/disable cellular data
180 * arg1 = ENBALED or DISABLED
181 */
182 private static final int EVENT_SET_MOBILE_DATA =
183 MAX_NETWORK_STATE_TRACKER_EVENT + 7;
184
Robert Greenwaltccb36f92010-09-24 14:32:21 -0700185 /**
186 * used internally to clear a wakelock when transitioning
187 * from one net to another
188 */
189 private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK =
190 MAX_NETWORK_STATE_TRACKER_EVENT + 8;
191
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700192 /**
193 * used internally to reload global proxy settings
194 */
195 private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY =
196 MAX_NETWORK_STATE_TRACKER_EVENT + 9;
197
Robert Greenwalt34848c02011-03-25 13:09:25 -0700198 /**
199 * used internally to set external dependency met/unmet
200 * arg1 = ENABLED (met) or DISABLED (unmet)
201 * arg2 = NetworkType
202 */
203 private static final int EVENT_SET_DEPENDENCY_MET =
204 MAX_NETWORK_STATE_TRACKER_EVENT + 10;
205
Robert Greenwalt2034b912009-08-12 16:08:25 -0700206 private Handler mHandler;
207
208 // list of DeathRecipients used to make sure features are turned off when
209 // a process dies
210 private List mFeatureUsers;
211
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400212 private boolean mSystemReady;
Dianne Hackborna417ff82009-12-08 19:45:14 -0800213 private Intent mInitialBroadcast;
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400214
Robert Greenwalt93dc1042010-06-15 12:19:37 -0700215 private PowerManager.WakeLock mNetTransitionWakeLock;
216 private String mNetTransitionWakeLockCausedBy = "";
217 private int mNetTransitionWakeLockSerialNumber;
218 private int mNetTransitionWakeLockTimeout;
219
Robert Greenwalt94daa182010-09-01 11:34:05 -0700220 private InetAddress mDefaultDns;
221
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700222 // used in DBG mode to track inet condition reports
223 private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
224 private ArrayList mInetLog;
225
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700226 // track the current default http proxy - tell the world if we get a new one (real change)
227 private ProxyProperties mDefaultProxy = null;
228 // track the global proxy.
229 private ProxyProperties mGlobalProxy = null;
230 private final Object mGlobalProxyLock = new Object();
231
232 private SettingsObserver mSettingsObserver;
233
Robert Greenwalt34848c02011-03-25 13:09:25 -0700234 NetworkConfig[] mNetConfigs;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700235 int mNetworksDefined;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700236
Robert Greenwalt12c44552009-12-07 11:33:18 -0800237 private static class RadioAttributes {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700238 public int mSimultaneity;
239 public int mType;
240 public RadioAttributes(String init) {
241 String fragments[] = init.split(",");
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700242 mType = Integer.parseInt(fragments[0]);
243 mSimultaneity = Integer.parseInt(fragments[1]);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700244 }
245 }
246 RadioAttributes[] mRadioAttributes;
247
Wink Saville775aad62010-09-02 19:23:52 -0700248 public static synchronized ConnectivityService getInstance(Context context) {
249 if (sServiceInstance == null) {
250 sServiceInstance = new ConnectivityService(context);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800251 }
Wink Saville775aad62010-09-02 19:23:52 -0700252 return sServiceInstance;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800253 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700254
The Android Open Source Project28527d22009-03-03 19:31:44 -0800255 private ConnectivityService(Context context) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800256 if (DBG) log("ConnectivityService starting up");
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800257
Wink Saville775aad62010-09-02 19:23:52 -0700258 HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
259 handlerThread.start();
260 mHandler = new MyHandler(handlerThread.getLooper());
261
Robert Greenwaltd62c7002010-12-29 16:15:02 -0800262 mBackgroundDataEnabled.set(Settings.Secure.getInt(context.getContentResolver(),
263 Settings.Secure.BACKGROUND_DATA, 1) == 1);
264
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800265 // setup our unique device name
Robert Greenwalt82cde132010-12-06 09:30:17 -0800266 if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
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 }
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800273 }
274
Robert Greenwalt94daa182010-09-01 11:34:05 -0700275 // read our default dns server ip
276 String dns = Settings.Secure.getString(context.getContentResolver(),
277 Settings.Secure.DEFAULT_DNS_SERVER);
278 if (dns == null || dns.length() == 0) {
279 dns = context.getResources().getString(
280 com.android.internal.R.string.config_default_dns_server);
281 }
282 try {
Robert Greenwalt35e34d12011-02-22 16:00:42 -0800283 mDefaultDns = NetworkUtils.numericToInetAddress(dns);
284 } catch (IllegalArgumentException e) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800285 loge("Error setting defaultDns using " + dns);
Robert Greenwalt94daa182010-09-01 11:34:05 -0700286 }
287
The Android Open Source Project28527d22009-03-03 19:31:44 -0800288 mContext = context;
Robert Greenwalt93dc1042010-06-15 12:19:37 -0700289
290 PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
291 mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
292 mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
293 com.android.internal.R.integer.config_networkTransitionTimeout);
294
Robert Greenwalt2034b912009-08-12 16:08:25 -0700295 mNetTrackers = new NetworkStateTracker[
296 ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwalt0659da32009-07-16 17:21:39 -0700297
The Android Open Source Project28527d22009-03-03 19:31:44 -0800298 mNetworkPreference = getPersistedNetworkPreference();
Robert Greenwalt0659da32009-07-16 17:21:39 -0700299
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700300 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
Robert Greenwalt34848c02011-03-25 13:09:25 -0700301 mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700302
Robert Greenwalt2034b912009-08-12 16:08:25 -0700303 // Load device network attributes from resources
Robert Greenwalt2034b912009-08-12 16:08:25 -0700304 String[] raStrings = context.getResources().getStringArray(
305 com.android.internal.R.array.radioAttributes);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700306 for (String raString : raStrings) {
307 RadioAttributes r = new RadioAttributes(raString);
308 if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800309 loge("Error in radioAttributes - ignoring attempt to define type " + r.mType);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700310 continue;
311 }
312 if (mRadioAttributes[r.mType] != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800313 loge("Error in radioAttributes - ignoring attempt to redefine type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700314 r.mType);
315 continue;
316 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700317 mRadioAttributes[r.mType] = r;
318 }
319
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700320 String[] naStrings = context.getResources().getStringArray(
321 com.android.internal.R.array.networkAttributes);
322 for (String naString : naStrings) {
323 try {
Robert Greenwalt34848c02011-03-25 13:09:25 -0700324 NetworkConfig n = new NetworkConfig(naString);
Wink Savillef2a62832011-04-07 14:23:45 -0700325 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800326 loge("Error in networkAttributes - ignoring attempt to define type " +
Wink Savillef2a62832011-04-07 14:23:45 -0700327 n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700328 continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700329 }
Wink Savillef2a62832011-04-07 14:23:45 -0700330 if (mNetConfigs[n.type] != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800331 loge("Error in networkAttributes - ignoring attempt to redefine type " +
Wink Savillef2a62832011-04-07 14:23:45 -0700332 n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700333 continue;
334 }
Wink Savillef2a62832011-04-07 14:23:45 -0700335 if (mRadioAttributes[n.radio] == null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800336 loge("Error in networkAttributes - ignoring attempt to use undefined " +
Wink Savillef2a62832011-04-07 14:23:45 -0700337 "radio " + n.radio + " in network type " + n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700338 continue;
339 }
Wink Savillef2a62832011-04-07 14:23:45 -0700340 mNetConfigs[n.type] = n;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700341 mNetworksDefined++;
342 } catch(Exception e) {
343 // ignore it - leave the entry null
Robert Greenwalt2034b912009-08-12 16:08:25 -0700344 }
345 }
346
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700347 // high priority first
348 mPriorityList = new int[mNetworksDefined];
349 {
350 int insertionPoint = mNetworksDefined-1;
351 int currentLowest = 0;
352 int nextLowest = 0;
353 while (insertionPoint > -1) {
Robert Greenwalt34848c02011-03-25 13:09:25 -0700354 for (NetworkConfig na : mNetConfigs) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700355 if (na == null) continue;
Wink Savillef2a62832011-04-07 14:23:45 -0700356 if (na.priority < currentLowest) continue;
357 if (na.priority > currentLowest) {
358 if (na.priority < nextLowest || nextLowest == 0) {
359 nextLowest = na.priority;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700360 }
361 continue;
362 }
Wink Savillef2a62832011-04-07 14:23:45 -0700363 mPriorityList[insertionPoint--] = na.type;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700364 }
365 currentLowest = nextLowest;
366 nextLowest = 0;
367 }
368 }
369
370 mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
371 for (int i : mPriorityList) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700372 mNetRequestersPids[i] = new ArrayList();
373 }
374
375 mFeatureUsers = new ArrayList();
376
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700377 mNumDnsEntries = 0;
378
379 mTestMode = SystemProperties.get("cm.test.mode").equals("true")
380 && SystemProperties.get("ro.build.type").equals("eng");
The Android Open Source Project28527d22009-03-03 19:31:44 -0800381 /*
382 * Create the network state trackers for Wi-Fi and mobile
383 * data. Maybe this could be done with a factory class,
384 * but it's not clear that it's worth it, given that
385 * the number of different network types is not going
386 * to change very often.
387 */
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700388 for (int netType : mPriorityList) {
Wink Savillef2a62832011-04-07 14:23:45 -0700389 switch (mNetConfigs[netType].radio) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700390 case ConnectivityManager.TYPE_WIFI:
Wink Savillee70c6f52010-12-03 12:01:38 -0800391 if (DBG) log("Starting Wifi Service.");
Wink Saville7fabfa22010-08-13 16:11:42 -0700392 WifiStateTracker wst = new WifiStateTracker();
Irfan Sheriff25be0762010-07-28 09:35:20 -0700393 WifiService wifiService = new WifiService(context);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700394 ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
Irfan Sheriff25be0762010-07-28 09:35:20 -0700395 wifiService.checkAndStartWifi();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700396 mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
Wink Saville7fabfa22010-08-13 16:11:42 -0700397 wst.startMonitoring(context, mHandler);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800398
Irfan Sheriff653e2a22010-06-07 09:03:04 -0700399 //TODO: as part of WWS refactor, create only when needed
Irfan Sheriff25be0762010-07-28 09:35:20 -0700400 mWifiWatchdogService = new WifiWatchdogService(context);
Irfan Sheriff653e2a22010-06-07 09:03:04 -0700401
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700402 break;
403 case ConnectivityManager.TYPE_MOBILE:
Wink Saville7fabfa22010-08-13 16:11:42 -0700404 mNetTrackers[netType] = new MobileDataStateTracker(netType,
Wink Savillef2a62832011-04-07 14:23:45 -0700405 mNetConfigs[netType].name);
Wink Saville7fabfa22010-08-13 16:11:42 -0700406 mNetTrackers[netType].startMonitoring(context, mHandler);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700407 break;
Robert Greenwalteb123ac2010-12-06 13:56:24 -0800408 case ConnectivityManager.TYPE_DUMMY:
409 mNetTrackers[netType] = new DummyDataStateTracker(netType,
Wink Savillef2a62832011-04-07 14:23:45 -0700410 mNetConfigs[netType].name);
Robert Greenwalteb123ac2010-12-06 13:56:24 -0800411 mNetTrackers[netType].startMonitoring(context, mHandler);
412 break;
Jaikumar Ganesh0db51a02010-12-21 22:31:44 -0800413 case ConnectivityManager.TYPE_BLUETOOTH:
414 mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
415 mNetTrackers[netType].startMonitoring(context, mHandler);
416 break;
Benoit Goby6cec7f32010-12-22 14:29:40 -0800417 case ConnectivityManager.TYPE_ETHERNET:
418 mNetTrackers[netType] = EthernetDataTracker.getInstance();
419 mNetTrackers[netType].startMonitoring(context, mHandler);
420 break;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700421 default:
Wink Savillee70c6f52010-12-03 12:01:38 -0800422 loge("Trying to create a DataStateTracker for an unknown radio type " +
Wink Savillef2a62832011-04-07 14:23:45 -0700423 mNetConfigs[netType].radio);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700424 continue;
425 }
426 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800427
Robert Greenwaltc0b6c602010-03-11 15:03:08 -0800428 mTethering = new Tethering(mContext, mHandler.getLooper());
Robert Greenwaltf1b66e12010-02-25 12:29:30 -0800429 mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) ||
430 !mTethering.isDunRequired()) &&
431 (mTethering.getTetherableUsbRegexs().length != 0 ||
Danica Chang96567052010-08-11 14:54:43 -0700432 mTethering.getTetherableWifiRegexs().length != 0 ||
433 mTethering.getTetherableBluetoothRegexs().length != 0) &&
Robert Greenwaltf1b66e12010-02-25 12:29:30 -0800434 mTethering.getUpstreamIfaceRegexs().length != 0);
435
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700436 if (DBG) {
437 mInetLog = new ArrayList();
438 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700439
440 mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
441 mSettingsObserver.observe(mContext);
Robert Greenwalt6f7c6092010-12-02 11:31:00 -0800442
443 loadGlobalProxy();
Hung-ying Tyan4e723422011-01-19 16:48:38 +0800444
445 VpnManager.startVpnService(context);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800446 }
447
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700448
The Android Open Source Project28527d22009-03-03 19:31:44 -0800449 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700450 * Sets the preferred network.
The Android Open Source Project28527d22009-03-03 19:31:44 -0800451 * @param preference the new preference
452 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700453 public void setNetworkPreference(int preference) {
The Android Open Source Project28527d22009-03-03 19:31:44 -0800454 enforceChangePermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700455
456 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
The Android Open Source Project28527d22009-03-03 19:31:44 -0800457 }
458
459 public int getNetworkPreference() {
460 enforceAccessPermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700461 int preference;
462 synchronized(this) {
463 preference = mNetworkPreference;
464 }
465 return preference;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800466 }
467
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700468 private void handleSetNetworkPreference(int preference) {
469 if (ConnectivityManager.isNetworkTypeValid(preference) &&
Robert Greenwalt34848c02011-03-25 13:09:25 -0700470 mNetConfigs[preference] != null &&
471 mNetConfigs[preference].isDefault()) {
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700472 if (mNetworkPreference != preference) {
473 final ContentResolver cr = mContext.getContentResolver();
474 Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference);
475 synchronized(this) {
476 mNetworkPreference = preference;
477 }
478 enforcePreference();
479 }
480 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800481 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700482
The Android Open Source Project28527d22009-03-03 19:31:44 -0800483 private int getPersistedNetworkPreference() {
484 final ContentResolver cr = mContext.getContentResolver();
485
486 final int networkPrefSetting = Settings.Secure
487 .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
488 if (networkPrefSetting != -1) {
489 return networkPrefSetting;
490 }
491
492 return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
493 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700494
The Android Open Source Project28527d22009-03-03 19:31:44 -0800495 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700496 * Make the state of network connectivity conform to the preference settings
The Android Open Source Project28527d22009-03-03 19:31:44 -0800497 * In this method, we only tear down a non-preferred network. Establishing
498 * a connection to the preferred network is taken care of when we handle
499 * the disconnect event from the non-preferred network
500 * (see {@link #handleDisconnect(NetworkInfo)}).
501 */
502 private void enforcePreference() {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700503 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
The Android Open Source Project28527d22009-03-03 19:31:44 -0800504 return;
505
Robert Greenwalt2034b912009-08-12 16:08:25 -0700506 if (!mNetTrackers[mNetworkPreference].isAvailable())
507 return;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800508
Robert Greenwalt2034b912009-08-12 16:08:25 -0700509 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700510 if (t != mNetworkPreference && mNetTrackers[t] != null &&
Robert Greenwalt2034b912009-08-12 16:08:25 -0700511 mNetTrackers[t].getNetworkInfo().isConnected()) {
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700512 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800513 log("tearing down " + mNetTrackers[t].getNetworkInfo() +
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700514 " in enforcePreference");
515 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700516 teardown(mNetTrackers[t]);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800517 }
518 }
519 }
520
521 private boolean teardown(NetworkStateTracker netTracker) {
522 if (netTracker.teardown()) {
523 netTracker.setTeardownRequested(true);
524 return true;
525 } else {
526 return false;
527 }
528 }
529
530 /**
531 * Return NetworkInfo for the active (i.e., connected) network interface.
532 * It is assumed that at most one network is active at a time. If more
533 * than one is active, it is indeterminate which will be returned.
Robert Greenwalt0659da32009-07-16 17:21:39 -0700534 * @return the info for the active network, or {@code null} if none is
535 * active
The Android Open Source Project28527d22009-03-03 19:31:44 -0800536 */
537 public NetworkInfo getActiveNetworkInfo() {
538 enforceAccessPermission();
Robert Greenwalta71471b2011-03-24 21:41:41 -0700539 if (mActiveDefaultNetwork != -1) {
540 return mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800541 }
542 return null;
543 }
544
545 public NetworkInfo getNetworkInfo(int networkType) {
546 enforceAccessPermission();
547 if (ConnectivityManager.isNetworkTypeValid(networkType)) {
548 NetworkStateTracker t = mNetTrackers[networkType];
549 if (t != null)
550 return t.getNetworkInfo();
551 }
552 return null;
553 }
554
555 public NetworkInfo[] getAllNetworkInfo() {
556 enforceAccessPermission();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700557 NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
The Android Open Source Project28527d22009-03-03 19:31:44 -0800558 int i = 0;
559 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700560 if(t != null) result[i++] = t.getNetworkInfo();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800561 }
562 return result;
563 }
564
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700565 /**
566 * Return LinkProperties for the active (i.e., connected) default
567 * network interface. It is assumed that at most one default network
568 * is active at a time. If more than one is active, it is indeterminate
569 * which will be returned.
570 * @return the ip properties for the active network, or {@code null} if
571 * none is active
572 */
573 public LinkProperties getActiveLinkProperties() {
574 enforceAccessPermission();
575 for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
Robert Greenwalt34848c02011-03-25 13:09:25 -0700576 if (mNetConfigs[type] == null || !mNetConfigs[type].isDefault()) {
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700577 continue;
578 }
579 NetworkStateTracker t = mNetTrackers[type];
580 NetworkInfo info = t.getNetworkInfo();
581 if (info.isConnected()) {
582 return t.getLinkProperties();
583 }
584 }
585 return null;
586 }
587
588 public LinkProperties getLinkProperties(int networkType) {
589 enforceAccessPermission();
590 if (ConnectivityManager.isNetworkTypeValid(networkType)) {
591 NetworkStateTracker t = mNetTrackers[networkType];
592 if (t != null) return t.getLinkProperties();
593 }
594 return null;
595 }
596
The Android Open Source Project28527d22009-03-03 19:31:44 -0800597 public boolean setRadios(boolean turnOn) {
598 boolean result = true;
599 enforceChangePermission();
600 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700601 if (t != null) result = t.setRadio(turnOn) && result;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800602 }
603 return result;
604 }
605
606 public boolean setRadio(int netType, boolean turnOn) {
607 enforceChangePermission();
608 if (!ConnectivityManager.isNetworkTypeValid(netType)) {
609 return false;
610 }
611 NetworkStateTracker tracker = mNetTrackers[netType];
612 return tracker != null && tracker.setRadio(turnOn);
613 }
614
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700615 /**
616 * Used to notice when the calling process dies so we can self-expire
617 *
618 * Also used to know if the process has cleaned up after itself when
619 * our auto-expire timer goes off. The timer has a link to an object.
620 *
621 */
Robert Greenwalt2034b912009-08-12 16:08:25 -0700622 private class FeatureUser implements IBinder.DeathRecipient {
623 int mNetworkType;
624 String mFeature;
625 IBinder mBinder;
626 int mPid;
627 int mUid;
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800628 long mCreateTime;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700629
630 FeatureUser(int type, String feature, IBinder binder) {
631 super();
632 mNetworkType = type;
633 mFeature = feature;
634 mBinder = binder;
635 mPid = getCallingPid();
636 mUid = getCallingUid();
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800637 mCreateTime = System.currentTimeMillis();
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700638
Robert Greenwalt2034b912009-08-12 16:08:25 -0700639 try {
640 mBinder.linkToDeath(this, 0);
641 } catch (RemoteException e) {
642 binderDied();
643 }
644 }
645
646 void unlinkDeathRecipient() {
647 mBinder.unlinkToDeath(this, 0);
648 }
649
650 public void binderDied() {
Wink Savillee70c6f52010-12-03 12:01:38 -0800651 log("ConnectivityService FeatureUser binderDied(" +
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800652 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
653 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700654 stopUsingNetworkFeature(this, false);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700655 }
656
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700657 public void expire() {
Wink Savillee70c6f52010-12-03 12:01:38 -0800658 log("ConnectivityService FeatureUser expire(" +
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800659 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
660 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700661 stopUsingNetworkFeature(this, false);
662 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800663
664 public String toString() {
665 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
666 (System.currentTimeMillis() - mCreateTime) + " mSec ago";
667 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700668 }
669
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700670 // javadoc from interface
Robert Greenwalt2034b912009-08-12 16:08:25 -0700671 public int startUsingNetworkFeature(int networkType, String feature,
672 IBinder binder) {
673 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800674 log("startUsingNetworkFeature for net " + networkType + ": " + feature);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700675 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800676 enforceChangePermission();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700677 if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
Robert Greenwalt34848c02011-03-25 13:09:25 -0700678 mNetConfigs[networkType] == null) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700679 return Phone.APN_REQUEST_FAILED;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800680 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700681
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700682 FeatureUser f = new FeatureUser(networkType, feature, binder);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700683
684 // TODO - move this into the MobileDataStateTracker
685 int usedNetworkType = networkType;
686 if(networkType == ConnectivityManager.TYPE_MOBILE) {
Wink Savilleb7c92c72011-03-12 14:52:01 -0800687 usedNetworkType = convertFeatureToNetworkType(feature);
688 if (usedNetworkType < 0) {
689 Slog.e(TAG, "Can't match any netTracker!");
690 usedNetworkType = networkType;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700691 }
692 }
693 NetworkStateTracker network = mNetTrackers[usedNetworkType];
694 if (network != null) {
Robert Greenwalt5364d752010-12-15 13:26:33 -0800695 Integer currentPid = new Integer(getCallingPid());
Robert Greenwalt2034b912009-08-12 16:08:25 -0700696 if (usedNetworkType != networkType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700697 NetworkStateTracker radio = mNetTrackers[networkType];
698 NetworkInfo ni = network.getNetworkInfo();
699
700 if (ni.isAvailable() == false) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800701 if (DBG) log("special network not available");
Robert Greenwalt2cc87442010-12-29 14:35:21 -0800702 if (!TextUtils.equals(feature,Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
703 return Phone.APN_TYPE_NOT_AVAILABLE;
704 } else {
705 // else make the attempt anyway - probably giving REQUEST_STARTED below
706 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700707 }
708
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700709 synchronized(this) {
710 mFeatureUsers.add(f);
711 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
712 // this gets used for per-pid dns when connected
713 mNetRequestersPids[usedNetworkType].add(currentPid);
714 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700715 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700716
Robert Greenwalt20f819c2011-05-03 19:02:44 -0700717 int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
718
719 if (restoreTimer >= 0) {
720 mHandler.sendMessageDelayed(
721 mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer);
722 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700723
Robert Greenwalta52c75a2009-08-19 20:19:33 -0700724 if ((ni.isConnectedOrConnecting() == true) &&
725 !network.isTeardownRequested()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700726 if (ni.isConnected() == true) {
727 // add the pid-specific dns
Robert Greenwalt3afbead2010-07-23 15:46:26 -0700728 handleDnsConfigurationChange(networkType);
Wink Savillee70c6f52010-12-03 12:01:38 -0800729 if (DBG) log("special network already active");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700730 return Phone.APN_ALREADY_ACTIVE;
731 }
Wink Savillee70c6f52010-12-03 12:01:38 -0800732 if (DBG) log("special network already connecting");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700733 return Phone.APN_REQUEST_STARTED;
734 }
735
736 // check if the radio in play can make another contact
737 // assume if cannot for now
738
Wink Savillee70c6f52010-12-03 12:01:38 -0800739 if (DBG) log("reconnecting to special network");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700740 network.reconnect();
741 return Phone.APN_REQUEST_STARTED;
742 } else {
Robert Greenwalt5364d752010-12-15 13:26:33 -0800743 // need to remember this unsupported request so we respond appropriately on stop
744 synchronized(this) {
745 mFeatureUsers.add(f);
746 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
747 // this gets used for per-pid dns when connected
748 mNetRequestersPids[usedNetworkType].add(currentPid);
749 }
750 }
Robert Greenwaltd391e892010-05-18 10:52:51 -0700751 return -1;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700752 }
753 }
754 return Phone.APN_TYPE_NOT_AVAILABLE;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800755 }
756
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700757 // javadoc from interface
The Android Open Source Project28527d22009-03-03 19:31:44 -0800758 public int stopUsingNetworkFeature(int networkType, String feature) {
Robert Greenwalt28f43012009-10-06 17:52:40 -0700759 enforceChangePermission();
760
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700761 int pid = getCallingPid();
762 int uid = getCallingUid();
763
764 FeatureUser u = null;
765 boolean found = false;
766
767 synchronized(this) {
768 for (int i = 0; i < mFeatureUsers.size() ; i++) {
769 u = (FeatureUser)mFeatureUsers.get(i);
770 if (uid == u.mUid && pid == u.mPid &&
771 networkType == u.mNetworkType &&
772 TextUtils.equals(feature, u.mFeature)) {
773 found = true;
774 break;
775 }
776 }
777 }
778 if (found && u != null) {
779 // stop regardless of how many other time this proc had called start
780 return stopUsingNetworkFeature(u, true);
781 } else {
782 // none found!
Wink Savillee70c6f52010-12-03 12:01:38 -0800783 if (DBG) log("ignoring stopUsingNetworkFeature - not a live request");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700784 return 1;
785 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700786 }
787
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700788 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
789 int networkType = u.mNetworkType;
790 String feature = u.mFeature;
791 int pid = u.mPid;
792 int uid = u.mUid;
793
794 NetworkStateTracker tracker = null;
795 boolean callTeardown = false; // used to carry our decision outside of sync block
796
Robert Greenwalt2034b912009-08-12 16:08:25 -0700797 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800798 log("stopUsingNetworkFeature for net " + networkType +
Robert Greenwalt2034b912009-08-12 16:08:25 -0700799 ": " + feature);
800 }
Robert Greenwalt28f43012009-10-06 17:52:40 -0700801
The Android Open Source Project28527d22009-03-03 19:31:44 -0800802 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
803 return -1;
804 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700805
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700806 // need to link the mFeatureUsers list with the mNetRequestersPids state in this
807 // sync block
808 synchronized(this) {
809 // check if this process still has an outstanding start request
810 if (!mFeatureUsers.contains(u)) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800811 if (DBG) log("ignoring - this process has no outstanding requests");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700812 return 1;
813 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700814 u.unlinkDeathRecipient();
815 mFeatureUsers.remove(mFeatureUsers.indexOf(u));
816 // If we care about duplicate requests, check for that here.
817 //
818 // This is done to support the extension of a request - the app
819 // can request we start the network feature again and renew the
820 // auto-shutoff delay. Normal "stop" calls from the app though
821 // do not pay attention to duplicate requests - in effect the
822 // API does not refcount and a single stop will counter multiple starts.
823 if (ignoreDups == false) {
824 for (int i = 0; i < mFeatureUsers.size() ; i++) {
825 FeatureUser x = (FeatureUser)mFeatureUsers.get(i);
826 if (x.mUid == u.mUid && x.mPid == u.mPid &&
827 x.mNetworkType == u.mNetworkType &&
828 TextUtils.equals(x.mFeature, u.mFeature)) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800829 if (DBG) log("ignoring stopUsingNetworkFeature as dup is found");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700830 return 1;
831 }
832 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700833 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700834
835 // TODO - move to MobileDataStateTracker
836 int usedNetworkType = networkType;
837 if (networkType == ConnectivityManager.TYPE_MOBILE) {
Wink Savilleb7c92c72011-03-12 14:52:01 -0800838 usedNetworkType = convertFeatureToNetworkType(feature);
839 if (usedNetworkType < 0) {
840 usedNetworkType = networkType;
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700841 }
842 }
843 tracker = mNetTrackers[usedNetworkType];
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700844 if (tracker == null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800845 if (DBG) log("ignoring - no known tracker for net type " + usedNetworkType);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700846 return -1;
847 }
848 if (usedNetworkType != networkType) {
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700849 Integer currentPid = new Integer(pid);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700850 mNetRequestersPids[usedNetworkType].remove(currentPid);
Robert Greenwalt0ca68a02009-12-17 14:54:59 -0800851 reassessPidDns(pid, true);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700852 if (mNetRequestersPids[usedNetworkType].size() != 0) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800853 if (DBG) log("not tearing down special network - " +
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700854 "others still using it");
855 return 1;
856 }
857 callTeardown = true;
Robert Greenwalt9f3be4c2011-01-10 11:58:31 -0800858 } else {
859 if (DBG) log("not a known feature - dropping");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700860 }
861 }
Wink Savillee70c6f52010-12-03 12:01:38 -0800862 if (DBG) log("Doing network teardown");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700863 if (callTeardown) {
864 tracker.teardown();
Robert Greenwalt2034b912009-08-12 16:08:25 -0700865 return 1;
866 } else {
Robert Greenwaltd391e892010-05-18 10:52:51 -0700867 return -1;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700868 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800869 }
870
871 /**
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -0700872 * @deprecated use requestRouteToHostAddress instead
873 *
The Android Open Source Project28527d22009-03-03 19:31:44 -0800874 * Ensure that a network route exists to deliver traffic to the specified
875 * host via the specified network interface.
Robert Greenwalt0659da32009-07-16 17:21:39 -0700876 * @param networkType the type of the network over which traffic to the
877 * specified host is to be routed
878 * @param hostAddress the IP address of the host to which the route is
879 * desired
The Android Open Source Project28527d22009-03-03 19:31:44 -0800880 * @return {@code true} on success, {@code false} on failure
881 */
882 public boolean requestRouteToHost(int networkType, int hostAddress) {
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -0700883 InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
884
885 if (inetAddress == null) {
886 return false;
887 }
888
889 return requestRouteToHostAddress(networkType, inetAddress.getAddress());
890 }
891
892 /**
893 * Ensure that a network route exists to deliver traffic to the specified
894 * host via the specified network interface.
895 * @param networkType the type of the network over which traffic to the
896 * specified host is to be routed
897 * @param hostAddress the IP address of the host to which the route is
898 * desired
899 * @return {@code true} on success, {@code false} on failure
900 */
901 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
The Android Open Source Project28527d22009-03-03 19:31:44 -0800902 enforceChangePermission();
903 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
904 return false;
905 }
906 NetworkStateTracker tracker = mNetTrackers[networkType];
Robert Greenwalt4666ed02009-09-10 15:06:20 -0700907
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700908 if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
909 tracker.isTeardownRequested()) {
Robert Greenwalt4666ed02009-09-10 15:06:20 -0700910 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800911 log("requestRouteToHostAddress on down network " +
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -0700912 "(" + networkType + ") - dropped");
Robert Greenwalt4666ed02009-09-10 15:06:20 -0700913 }
914 return false;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800915 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700916 try {
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -0700917 InetAddress addr = InetAddress.getByAddress(hostAddress);
Robert Greenwaltbd492212011-05-06 17:10:53 -0700918 return addHostRoute(tracker, addr, 0);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700919 } catch (UnknownHostException e) {}
920 return false;
Irfan Sheriff7f132d92010-06-09 15:39:36 -0700921 }
922
923 /**
924 * Ensure that a network route exists to deliver traffic to the specified
925 * host via the mobile data network.
926 * @param hostAddress the IP address of the host to which the route is desired,
927 * in network byte order.
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700928 * TODO - deprecate
Irfan Sheriff7f132d92010-06-09 15:39:36 -0700929 * @return {@code true} on success, {@code false} on failure
930 */
Robert Greenwaltbd492212011-05-06 17:10:53 -0700931 private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress, int cycleCount) {
Irfan Sheriff7f132d92010-06-09 15:39:36 -0700932 if (nt.getNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI) {
933 return false;
934 }
935
Robert Greenwaltbd492212011-05-06 17:10:53 -0700936 LinkProperties lp = nt.getLinkProperties();
937 if ((lp == null) || (hostAddress == null)) return false;
Irfan Sheriff7f132d92010-06-09 15:39:36 -0700938
Robert Greenwaltbd492212011-05-06 17:10:53 -0700939 String interfaceName = lp.getInterfaceName();
Irfan Sheriff7f132d92010-06-09 15:39:36 -0700940 if (DBG) {
Robert Greenwaltbd492212011-05-06 17:10:53 -0700941 log("Requested host route to " + hostAddress + "(" + interfaceName + "), cycleCount=" +
942 cycleCount);
Irfan Sheriff7f132d92010-06-09 15:39:36 -0700943 }
Robert Greenwaltbd492212011-05-06 17:10:53 -0700944 if (interfaceName == null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800945 if (DBG) loge("addHostRoute failed due to null interface name");
Irfan Sheriff7f132d92010-06-09 15:39:36 -0700946 return false;
947 }
Robert Greenwaltbd492212011-05-06 17:10:53 -0700948
949 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), hostAddress);
950 InetAddress gateway = null;
951 if (bestRoute != null) {
952 gateway = bestRoute.getGateway();
953 // if the best route is ourself, don't relf-reference, just add the host route
954 if (hostAddress.equals(gateway)) gateway = null;
955 }
956 if (gateway != null) {
957 if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
958 loge("Error adding hostroute - too much recursion");
959 return false;
960 }
961 if (!addHostRoute(nt, gateway, cycleCount+1)) return false;
962 }
963 return NetworkUtils.addHostRoute(interfaceName, hostAddress, gateway);
964 }
965
966 // TODO support the removal of single host routes. Keep a ref count of them so we
967 // aren't over-zealous
968 private boolean removeHostRoute(NetworkStateTracker nt, InetAddress hostAddress) {
969 return false;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800970 }
971
972 /**
973 * @see ConnectivityManager#getBackgroundDataSetting()
974 */
975 public boolean getBackgroundDataSetting() {
Robert Greenwaltd62c7002010-12-29 16:15:02 -0800976 return mBackgroundDataEnabled.get();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800977 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700978
The Android Open Source Project28527d22009-03-03 19:31:44 -0800979 /**
980 * @see ConnectivityManager#setBackgroundDataSetting(boolean)
981 */
982 public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) {
983 mContext.enforceCallingOrSelfPermission(
984 android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
985 "ConnectivityService");
Robert Greenwalt0659da32009-07-16 17:21:39 -0700986
Robert Greenwaltd62c7002010-12-29 16:15:02 -0800987 mBackgroundDataEnabled.set(allowBackgroundDataUsage);
988
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700989 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA,
990 (allowBackgroundDataUsage ? ENABLED : DISABLED), 0));
991 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800992
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700993 private void handleSetBackgroundData(boolean enabled) {
Robert Greenwalt0ffdef12011-02-25 13:44:09 -0800994 Settings.Secure.putInt(mContext.getContentResolver(),
995 Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0);
996 Intent broadcast = new Intent(
997 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
998 mContext.sendBroadcast(broadcast);
Robert Greenwalt0659da32009-07-16 17:21:39 -0700999 }
1000
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001001 /**
1002 * @see ConnectivityManager#getMobileDataEnabled()
1003 */
1004 public boolean getMobileDataEnabled() {
Wink Savilleb9024c62010-12-07 10:31:02 -08001005 // TODO: This detail should probably be in DataConnectionTracker's
1006 // which is where we store the value and maybe make this
1007 // asynchronous.
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001008 enforceAccessPermission();
1009 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
1010 Settings.Secure.MOBILE_DATA, 1) == 1;
Wink Savillee70c6f52010-12-03 12:01:38 -08001011 if (DBG) log("getMobileDataEnabled returning " + retVal);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001012 return retVal;
1013 }
1014
Robert Greenwalt34848c02011-03-25 13:09:25 -07001015 public void setDataDependency(int networkType, boolean met) {
1016 enforceChangePermission();
1017 if (DBG) {
1018 log("setDataDependency(" + networkType + ", " + met + ")");
1019 }
1020 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
1021 (met ? ENABLED : DISABLED), networkType));
1022 }
1023
1024 private void handleSetDependencyMet(int networkType, boolean met) {
1025 if (mNetTrackers[networkType] != null) {
1026 if (DBG) {
1027 log("handleSetDependencyMet(" + networkType + ", " + met + ")");
1028 }
1029 mNetTrackers[networkType].setDependencyMet(met);
1030 }
1031 }
1032
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001033 /**
1034 * @see ConnectivityManager#setMobileDataEnabled(boolean)
1035 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001036 public void setMobileDataEnabled(boolean enabled) {
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001037 enforceChangePermission();
Wink Savillee70c6f52010-12-03 12:01:38 -08001038 if (DBG) log("setMobileDataEnabled(" + enabled + ")");
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001039
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001040 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
Robert Greenwalt34848c02011-03-25 13:09:25 -07001041 (enabled ? ENABLED : DISABLED), 0));
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001042 }
1043
1044 private void handleSetMobileData(boolean enabled) {
Wink Savilleb9024c62010-12-07 10:31:02 -08001045 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
1046 if (DBG) {
1047 Slog.d(TAG, mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001048 }
Wink Savilleb9024c62010-12-07 10:31:02 -08001049 mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001050 }
1051 }
1052
The Android Open Source Project28527d22009-03-03 19:31:44 -08001053 private void enforceAccessPermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001054 mContext.enforceCallingOrSelfPermission(
1055 android.Manifest.permission.ACCESS_NETWORK_STATE,
1056 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001057 }
1058
1059 private void enforceChangePermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001060 mContext.enforceCallingOrSelfPermission(
1061 android.Manifest.permission.CHANGE_NETWORK_STATE,
1062 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001063 }
1064
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001065 // TODO Make this a special check when it goes public
1066 private void enforceTetherChangePermission() {
1067 mContext.enforceCallingOrSelfPermission(
1068 android.Manifest.permission.CHANGE_NETWORK_STATE,
1069 "ConnectivityService");
1070 }
1071
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001072 private void enforceTetherAccessPermission() {
1073 mContext.enforceCallingOrSelfPermission(
1074 android.Manifest.permission.ACCESS_NETWORK_STATE,
1075 "ConnectivityService");
1076 }
1077
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001078 private void enforceConnectivityInternalPermission() {
1079 mContext.enforceCallingOrSelfPermission(
1080 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1081 "ConnectivityService");
1082 }
1083
The Android Open Source Project28527d22009-03-03 19:31:44 -08001084 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -07001085 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
1086 * network, we ignore it. If it is for the active network, we send out a
1087 * broadcast. But first, we check whether it might be possible to connect
1088 * to a different network.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001089 * @param info the {@code NetworkInfo} for the network
1090 */
1091 private void handleDisconnect(NetworkInfo info) {
1092
Robert Greenwalt2034b912009-08-12 16:08:25 -07001093 int prevNetType = info.getType();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001094
Robert Greenwalt2034b912009-08-12 16:08:25 -07001095 mNetTrackers[prevNetType].setTeardownRequested(false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001096 /*
1097 * If the disconnected network is not the active one, then don't report
1098 * this as a loss of connectivity. What probably happened is that we're
1099 * getting the disconnect for a network that we explicitly disabled
1100 * in accordance with network preference policies.
1101 */
Robert Greenwalt34848c02011-03-25 13:09:25 -07001102 if (!mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001103 List pids = mNetRequestersPids[prevNetType];
1104 for (int i = 0; i<pids.size(); i++) {
1105 Integer pid = (Integer)pids.get(i);
1106 // will remove them because the net's no longer connected
1107 // need to do this now as only now do we know the pids and
1108 // can properly null things that are no longer referenced.
1109 reassessPidDns(pid.intValue(), false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001110 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001111 }
1112
The Android Open Source Project28527d22009-03-03 19:31:44 -08001113 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1114 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1115 if (info.isFailover()) {
1116 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1117 info.setFailover(false);
1118 }
1119 if (info.getReason() != null) {
1120 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1121 }
1122 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001123 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1124 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001125 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001126
Robert Greenwalt34848c02011-03-25 13:09:25 -07001127 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001128 tryFailover(prevNetType);
1129 if (mActiveDefaultNetwork != -1) {
1130 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001131 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1132 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001133 mDefaultInetConditionPublished = 0; // we're not connected anymore
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001134 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1135 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001136 }
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001137 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001138 // do this before we broadcast the change
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001139 handleConnectivityChange(prevNetType);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001140
1141 sendStickyBroadcast(intent);
1142 /*
1143 * If the failover network is already connected, then immediately send
1144 * out a followup broadcast indicating successful failover
1145 */
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001146 if (mActiveDefaultNetwork != -1) {
1147 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001148 }
1149 }
1150
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001151 private void tryFailover(int prevNetType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001152 /*
Robert Greenwalt92564852011-01-06 15:41:07 -08001153 * If this is a default network, check if other defaults are available.
1154 * Try to reconnect on all available and let them hash it out when
1155 * more than one connects.
Robert Greenwalt2034b912009-08-12 16:08:25 -07001156 */
Robert Greenwalt34848c02011-03-25 13:09:25 -07001157 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001158 if (mActiveDefaultNetwork == prevNetType) {
1159 mActiveDefaultNetwork = -1;
1160 }
1161
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001162 // don't signal a reconnect for anything lower or equal priority than our
1163 // current connected default
1164 // TODO - don't filter by priority now - nice optimization but risky
1165// int currentPriority = -1;
1166// if (mActiveDefaultNetwork != -1) {
Robert Greenwalt34848c02011-03-25 13:09:25 -07001167// currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority;
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001168// }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001169 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001170 if (checkType == prevNetType) continue;
Robert Greenwalt34848c02011-03-25 13:09:25 -07001171 if (mNetConfigs[checkType] == null) continue;
1172 if (!mNetConfigs[checkType].isDefault()) continue;
Wink Saville72a95b92011-01-26 15:43:49 -08001173
1174// Enabling the isAvailable() optimization caused mobile to not get
1175// selected if it was in the middle of error handling. Specifically
1176// a moble connection that took 30 seconds to complete the DEACTIVATE_DATA_CALL
1177// would not be available and we wouldn't get connected to anything.
1178// So removing the isAvailable() optimization below for now. TODO: This
1179// optimization should work and we need to investigate why it doesn't work.
1180// This could be related to how DEACTIVATE_DATA_CALL is reporting its
1181// complete before it is really complete.
1182// if (!mNetTrackers[checkType].isAvailable()) continue;
1183
Robert Greenwalt34848c02011-03-25 13:09:25 -07001184// if (currentPriority >= mNetConfigs[checkType].mPriority) continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001185
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001186 NetworkStateTracker checkTracker = mNetTrackers[checkType];
1187 NetworkInfo checkInfo = checkTracker.getNetworkInfo();
1188 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
1189 checkInfo.setFailover(true);
1190 checkTracker.reconnect();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001191 }
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001192 if (DBG) log("Attempting to switch to " + checkInfo.getTypeName());
Robert Greenwalt2034b912009-08-12 16:08:25 -07001193 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001194 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001195 }
1196
1197 private void sendConnectedBroadcast(NetworkInfo info) {
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001198 sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION);
1199 }
1200
1201 private void sendInetConditionBroadcast(NetworkInfo info) {
1202 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1203 }
1204
1205 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1206 Intent intent = new Intent(bcastType);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001207 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1208 if (info.isFailover()) {
1209 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1210 info.setFailover(false);
1211 }
1212 if (info.getReason() != null) {
1213 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1214 }
1215 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001216 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1217 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001218 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07001219 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001220 sendStickyBroadcast(intent);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001221 }
1222
1223 /**
1224 * Called when an attempt to fail over to another network has failed.
1225 * @param info the {@link NetworkInfo} for the failed network
1226 */
1227 private void handleConnectionFailure(NetworkInfo info) {
1228 mNetTrackers[info.getType()].setTeardownRequested(false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001229
Robert Greenwalt2034b912009-08-12 16:08:25 -07001230 String reason = info.getReason();
1231 String extraInfo = info.getExtraInfo();
Robert Greenwalt0659da32009-07-16 17:21:39 -07001232
Robert Greenwalte981bc52010-10-08 16:35:52 -07001233 String reasonText;
1234 if (reason == null) {
1235 reasonText = ".";
1236 } else {
1237 reasonText = " (" + reason + ").";
The Android Open Source Project28527d22009-03-03 19:31:44 -08001238 }
Wink Savillee70c6f52010-12-03 12:01:38 -08001239 loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001240
1241 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1242 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1243 if (getActiveNetworkInfo() == null) {
1244 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1245 }
1246 if (reason != null) {
1247 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
1248 }
1249 if (extraInfo != null) {
1250 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
1251 }
1252 if (info.isFailover()) {
1253 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1254 info.setFailover(false);
1255 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001256
Robert Greenwalt34848c02011-03-25 13:09:25 -07001257 if (mNetConfigs[info.getType()].isDefault()) {
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001258 tryFailover(info.getType());
1259 if (mActiveDefaultNetwork != -1) {
1260 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001261 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1262 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001263 mDefaultInetConditionPublished = 0;
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001264 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1265 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001266 }
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001267
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001268 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001269 sendStickyBroadcast(intent);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001270 /*
1271 * If the failover network is already connected, then immediately send
1272 * out a followup broadcast indicating successful failover
1273 */
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001274 if (mActiveDefaultNetwork != -1) {
1275 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001276 }
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001277 }
1278
1279 private void sendStickyBroadcast(Intent intent) {
1280 synchronized(this) {
Dianne Hackborna417ff82009-12-08 19:45:14 -08001281 if (!mSystemReady) {
1282 mInitialBroadcast = new Intent(intent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001283 }
Dianne Hackborna417ff82009-12-08 19:45:14 -08001284 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1285 mContext.sendStickyBroadcast(intent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001286 }
1287 }
1288
1289 void systemReady() {
1290 synchronized(this) {
1291 mSystemReady = true;
Dianne Hackborna417ff82009-12-08 19:45:14 -08001292 if (mInitialBroadcast != null) {
1293 mContext.sendStickyBroadcast(mInitialBroadcast);
1294 mInitialBroadcast = null;
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001295 }
1296 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07001297 // load the global proxy at startup
1298 mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
The Android Open Source Project28527d22009-03-03 19:31:44 -08001299 }
1300
1301 private void handleConnect(NetworkInfo info) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001302 int type = info.getType();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001303
1304 // snapshot isFailover, because sendConnectedBroadcast() resets it
1305 boolean isFailover = info.isFailover();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001306 NetworkStateTracker thisNet = mNetTrackers[type];
The Android Open Source Project28527d22009-03-03 19:31:44 -08001307
Robert Greenwalt2034b912009-08-12 16:08:25 -07001308 // if this is a default net and other default is running
1309 // kill the one not preferred
Robert Greenwalt34848c02011-03-25 13:09:25 -07001310 if (mNetConfigs[type].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001311 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
1312 if ((type != mNetworkPreference &&
Wink Savillef2a62832011-04-07 14:23:45 -07001313 mNetConfigs[mActiveDefaultNetwork].priority >
1314 mNetConfigs[type].priority) ||
Robert Greenwalt2034b912009-08-12 16:08:25 -07001315 mNetworkPreference == mActiveDefaultNetwork) {
1316 // don't accept this one
Wink Savillee70c6f52010-12-03 12:01:38 -08001317 if (DBG) {
1318 log("Not broadcasting CONNECT_ACTION " +
Robert Greenwalt2034b912009-08-12 16:08:25 -07001319 "to torn down network " + info.getTypeName());
Wink Savillee70c6f52010-12-03 12:01:38 -08001320 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001321 teardown(thisNet);
1322 return;
1323 } else {
1324 // tear down the other
1325 NetworkStateTracker otherNet =
1326 mNetTrackers[mActiveDefaultNetwork];
Wink Savillee70c6f52010-12-03 12:01:38 -08001327 if (DBG) {
1328 log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
Robert Greenwalt2034b912009-08-12 16:08:25 -07001329 " teardown");
Wink Savillee70c6f52010-12-03 12:01:38 -08001330 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001331 if (!teardown(otherNet)) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001332 loge("Network declined teardown request");
Robert Greenwalt99910172011-03-29 11:36:28 -07001333 teardown(thisNet);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001334 return;
1335 }
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001336 }
1337 }
1338 synchronized (ConnectivityService.this) {
1339 // have a new default network, release the transition wakelock in a second
1340 // if it's held. The second pause is to allow apps to reconnect over the
1341 // new network
1342 if (mNetTransitionWakeLock.isHeld()) {
1343 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltccb36f92010-09-24 14:32:21 -07001344 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001345 mNetTransitionWakeLockSerialNumber, 0),
1346 1000);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001347 }
1348 }
1349 mActiveDefaultNetwork = type;
Robert Greenwalt986c7412010-09-08 15:24:47 -07001350 // this will cause us to come up initially as unconnected and switching
1351 // to connected after our normal pause unless somebody reports us as reall
1352 // disconnected
1353 mDefaultInetConditionPublished = 0;
1354 mDefaultConnectionSequence++;
1355 mInetConditionChangeInFlight = false;
1356 // Don't do this - if we never sign in stay, grey
1357 //reportNetworkCondition(mActiveDefaultNetwork, 100);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001358 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001359 thisNet.setTeardownRequested(false);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001360 updateNetworkSettings(thisNet);
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001361 handleConnectivityChange(type);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001362 sendConnectedBroadcast(info);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001363 }
1364
The Android Open Source Project28527d22009-03-03 19:31:44 -08001365 /**
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001366 * After a change in the connectivity state of a network. We're mainly
1367 * concerned with making sure that the list of DNS servers is set up
1368 * according to which networks are connected, and ensuring that the
1369 * right routing table entries exist.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001370 */
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001371 private void handleConnectivityChange(int netType) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001372 /*
Robert Greenwalt2034b912009-08-12 16:08:25 -07001373 * If a non-default network is enabled, add the host routes that
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001374 * will allow it's DNS servers to be accessed.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001375 */
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001376 handleDnsConfigurationChange(netType);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001377
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001378 if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
Robert Greenwalt34848c02011-03-25 13:09:25 -07001379 if (mNetConfigs[netType].isDefault()) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07001380 handleApplyDefaultProxy(netType);
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001381 addDefaultRoute(mNetTrackers[netType]);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001382 } else {
Robert Greenwalta71471b2011-03-24 21:41:41 -07001383 // many radios add a default route even when we don't want one.
1384 // remove the default interface unless we need it for our active network
1385 if (mActiveDefaultNetwork != -1) {
Robert Greenwalt3a378b92011-03-30 15:03:13 -07001386 LinkProperties linkProperties =
1387 mNetTrackers[mActiveDefaultNetwork].getLinkProperties();
1388 LinkProperties newLinkProperties =
1389 mNetTrackers[netType].getLinkProperties();
1390 String defaultIface = linkProperties.getInterfaceName();
Robert Greenwalta71471b2011-03-24 21:41:41 -07001391 if (defaultIface != null &&
Robert Greenwalt3a378b92011-03-30 15:03:13 -07001392 !defaultIface.equals(newLinkProperties.getInterfaceName())) {
Robert Greenwaltf7dae302011-03-31 10:44:47 -07001393 removeDefaultRoute(mNetTrackers[netType]);
Robert Greenwalta71471b2011-03-24 21:41:41 -07001394 }
1395 }
Robert Greenwaltf7dae302011-03-31 10:44:47 -07001396 addPrivateDnsRoutes(mNetTrackers[netType]);
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001397 }
Kazuhiro Ondo3a340412011-04-30 20:10:57 -05001398
1399 /** Notify TetheringService if interface name has been changed. */
1400 if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
1401 Phone.REASON_LINK_PROPERTIES_CHANGED)) {
1402 handleTetherIfaceChange(netType);
1403 }
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001404 } else {
Robert Greenwalt34848c02011-03-25 13:09:25 -07001405 if (mNetConfigs[netType].isDefault()) {
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001406 removeDefaultRoute(mNetTrackers[netType]);
1407 } else {
1408 removePrivateDnsRoutes(mNetTrackers[netType]);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001409 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001410 }
1411 }
1412
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001413 private void addPrivateDnsRoutes(NetworkStateTracker nt) {
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001414 boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet();
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001415 LinkProperties p = nt.getLinkProperties();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001416 if (p == null) return;
1417 String interfaceName = p.getInterfaceName();
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001418
1419 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001420 log("addPrivateDnsRoutes for " + nt +
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001421 "(" + interfaceName + ") - mPrivateDnsRouteSet = " + privateDnsRouteSet);
1422 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001423 if (interfaceName != null && !privateDnsRouteSet) {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001424 Collection<InetAddress> dnsList = p.getDnses();
1425 for (InetAddress dns : dnsList) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001426 if (DBG) log(" adding " + dns);
Robert Greenwaltbd492212011-05-06 17:10:53 -07001427 addHostRoute(nt, dns, 0);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001428 }
1429 nt.privateDnsRouteSet(true);
1430 }
1431 }
1432
1433 private void removePrivateDnsRoutes(NetworkStateTracker nt) {
1434 // TODO - we should do this explicitly but the NetUtils api doesnt
1435 // support this yet - must remove all. No worse than before
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001436 LinkProperties p = nt.getLinkProperties();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001437 if (p == null) return;
1438 String interfaceName = p.getInterfaceName();
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001439 boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet();
1440 if (interfaceName != null && privateDnsRouteSet) {
1441 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001442 log("removePrivateDnsRoutes for " + nt.getNetworkInfo().getTypeName() +
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001443 " (" + interfaceName + ")");
1444 }
1445 NetworkUtils.removeHostRoutes(interfaceName);
1446 nt.privateDnsRouteSet(false);
1447 }
1448 }
1449
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001450
1451 private void addDefaultRoute(NetworkStateTracker nt) {
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001452 LinkProperties p = nt.getLinkProperties();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001453 if (p == null) return;
1454 String interfaceName = p.getInterfaceName();
Robert Greenwalt5c733972011-02-09 13:56:06 -08001455 if (TextUtils.isEmpty(interfaceName)) return;
Robert Greenwalt5a901292011-04-28 14:28:50 -07001456 for (RouteInfo route : p.getRoutes()) {
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001457
Robert Greenwalt5a901292011-04-28 14:28:50 -07001458 //TODO - handle non-default routes
1459 if (route.isDefaultRoute()) {
1460 InetAddress gateway = route.getGateway();
Robert Greenwaltbd492212011-05-06 17:10:53 -07001461 if (addHostRoute(nt, gateway, 0) &&
Robert Greenwalt5a901292011-04-28 14:28:50 -07001462 NetworkUtils.addDefaultRoute(interfaceName, gateway)) {
1463 if (DBG) {
1464 NetworkInfo networkInfo = nt.getNetworkInfo();
1465 log("addDefaultRoute for " + networkInfo.getTypeName() +
1466 " (" + interfaceName + "), GatewayAddr=" +
1467 gateway.getHostAddress());
1468 }
Robert Greenwalt03d53da2011-03-22 18:47:42 -07001469 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001470 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001471 }
1472 }
1473
1474
1475 public void removeDefaultRoute(NetworkStateTracker nt) {
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001476 LinkProperties p = nt.getLinkProperties();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001477 if (p == null) return;
1478 String interfaceName = p.getInterfaceName();
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001479
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001480 if (interfaceName != null) {
Robert Greenwalt03d53da2011-03-22 18:47:42 -07001481 if (NetworkUtils.removeDefaultRoute(interfaceName) >= 0) {
1482 if (DBG) {
1483 NetworkInfo networkInfo = nt.getNetworkInfo();
1484 log("removeDefaultRoute for " + networkInfo.getTypeName() + " (" +
1485 interfaceName + ")");
1486 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001487 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001488 }
1489 }
1490
1491 /**
1492 * Reads the network specific TCP buffer sizes from SystemProperties
1493 * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
1494 * wide use
1495 */
1496 public void updateNetworkSettings(NetworkStateTracker nt) {
1497 String key = nt.getTcpBufferSizesPropName();
1498 String bufferSizes = SystemProperties.get(key);
1499
1500 if (bufferSizes.length() == 0) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001501 loge(key + " not found in system properties. Using defaults");
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001502
1503 // Setting to default values so we won't be stuck to previous values
1504 key = "net.tcp.buffersize.default";
1505 bufferSizes = SystemProperties.get(key);
1506 }
1507
1508 // Set values in kernel
1509 if (bufferSizes.length() != 0) {
1510 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001511 log("Setting TCP values: [" + bufferSizes
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001512 + "] which comes from [" + key + "]");
1513 }
1514 setBufferSize(bufferSizes);
1515 }
1516 }
1517
1518 /**
1519 * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max]
1520 * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem
1521 *
1522 * @param bufferSizes in the format of "readMin, readInitial, readMax,
1523 * writeMin, writeInitial, writeMax"
1524 */
1525 private void setBufferSize(String bufferSizes) {
1526 try {
1527 String[] values = bufferSizes.split(",");
1528
1529 if (values.length == 6) {
1530 final String prefix = "/sys/kernel/ipv4/tcp_";
1531 stringToFile(prefix + "rmem_min", values[0]);
1532 stringToFile(prefix + "rmem_def", values[1]);
1533 stringToFile(prefix + "rmem_max", values[2]);
1534 stringToFile(prefix + "wmem_min", values[3]);
1535 stringToFile(prefix + "wmem_def", values[4]);
1536 stringToFile(prefix + "wmem_max", values[5]);
1537 } else {
Wink Savillee70c6f52010-12-03 12:01:38 -08001538 loge("Invalid buffersize string: " + bufferSizes);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001539 }
1540 } catch (IOException e) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001541 loge("Can't set tcp buffer sizes:" + e);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001542 }
1543 }
1544
1545 /**
1546 * Writes string to file. Basically same as "echo -n $string > $filename"
1547 *
1548 * @param filename
1549 * @param string
1550 * @throws IOException
1551 */
1552 private void stringToFile(String filename, String string) throws IOException {
1553 FileWriter out = new FileWriter(filename);
1554 try {
1555 out.write(string);
1556 } finally {
1557 out.close();
1558 }
1559 }
1560
1561
Robert Greenwalt2034b912009-08-12 16:08:25 -07001562 /**
1563 * Adjust the per-process dns entries (net.dns<x>.<pid>) based
1564 * on the highest priority active net which this process requested.
1565 * If there aren't any, clear it out
1566 */
1567 private void reassessPidDns(int myPid, boolean doBump)
1568 {
Wink Savillee70c6f52010-12-03 12:01:38 -08001569 if (DBG) log("reassessPidDns for pid " + myPid);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001570 for(int i : mPriorityList) {
Robert Greenwalt34848c02011-03-25 13:09:25 -07001571 if (mNetConfigs[i].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001572 continue;
1573 }
1574 NetworkStateTracker nt = mNetTrackers[i];
Robert Greenwalt0659da32009-07-16 17:21:39 -07001575 if (nt.getNetworkInfo().isConnected() &&
1576 !nt.isTeardownRequested()) {
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001577 LinkProperties p = nt.getLinkProperties();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001578 if (p == null) continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001579 List pids = mNetRequestersPids[i];
1580 for (int j=0; j<pids.size(); j++) {
1581 Integer pid = (Integer)pids.get(j);
1582 if (pid.intValue() == myPid) {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001583 Collection<InetAddress> dnses = p.getDnses();
1584 writePidDns(dnses, myPid);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001585 if (doBump) {
1586 bumpDns();
1587 }
1588 return;
1589 }
1590 }
1591 }
1592 }
1593 // nothing found - delete
1594 for (int i = 1; ; i++) {
1595 String prop = "net.dns" + i + "." + myPid;
1596 if (SystemProperties.get(prop).length() == 0) {
1597 if (doBump) {
1598 bumpDns();
1599 }
1600 return;
1601 }
1602 SystemProperties.set(prop, "");
1603 }
1604 }
1605
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001606 // return true if results in a change
1607 private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001608 int j = 1;
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001609 boolean changed = false;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001610 for (InetAddress dns : dnses) {
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001611 String dnsString = dns.getHostAddress();
1612 if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
1613 changed = true;
1614 SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
1615 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001616 }
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001617 return changed;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001618 }
1619
1620 private void bumpDns() {
1621 /*
1622 * Bump the property that tells the name resolver library to reread
1623 * the DNS server list from the properties.
1624 */
1625 String propVal = SystemProperties.get("net.dnschange");
1626 int n = 0;
1627 if (propVal.length() != 0) {
1628 try {
1629 n = Integer.parseInt(propVal);
1630 } catch (NumberFormatException e) {}
1631 }
1632 SystemProperties.set("net.dnschange", "" + (n+1));
Robert Greenwalt051642b2010-11-02 14:08:23 -07001633 /*
1634 * Tell the VMs to toss their DNS caches
1635 */
1636 Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
1637 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Stan Chesnuttf444f502011-01-05 17:14:03 -08001638 /*
1639 * Connectivity events can happen before boot has completed ...
1640 */
1641 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt051642b2010-11-02 14:08:23 -07001642 mContext.sendBroadcast(intent);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001643 }
1644
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001645 private void handleDnsConfigurationChange(int netType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001646 // add default net's dns entries
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001647 NetworkStateTracker nt = mNetTrackers[netType];
1648 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001649 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001650 if (p == null) return;
1651 Collection<InetAddress> dnses = p.getDnses();
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001652 boolean changed = false;
Robert Greenwalt34848c02011-03-25 13:09:25 -07001653 if (mNetConfigs[netType].isDefault()) {
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001654 int j = 1;
Robert Greenwalt94daa182010-09-01 11:34:05 -07001655 if (dnses.size() == 0 && mDefaultDns != null) {
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001656 String dnsString = mDefaultDns.getHostAddress();
1657 if (!dnsString.equals(SystemProperties.get("net.dns1"))) {
1658 if (DBG) {
1659 log("no dns provided - using " + dnsString);
1660 }
1661 changed = true;
1662 SystemProperties.set("net.dns1", dnsString);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001663 }
Robert Greenwalt94daa182010-09-01 11:34:05 -07001664 j++;
1665 } else {
1666 for (InetAddress dns : dnses) {
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001667 String dnsString = dns.getHostAddress();
1668 if (!changed && dnsString.equals(SystemProperties.get("net.dns" + j))) {
1669 j++;
1670 continue;
1671 }
Robert Greenwalt94daa182010-09-01 11:34:05 -07001672 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001673 log("adding dns " + dns + " for " +
Robert Greenwalt94daa182010-09-01 11:34:05 -07001674 nt.getNetworkInfo().getTypeName());
1675 }
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001676 changed = true;
1677 SystemProperties.set("net.dns" + j++, dnsString);
Robert Greenwalt94daa182010-09-01 11:34:05 -07001678 }
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001679 }
1680 for (int k=j ; k<mNumDnsEntries; k++) {
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001681 if (changed || !TextUtils.isEmpty(SystemProperties.get("net.dns" + k))) {
1682 if (DBG) log("erasing net.dns" + k);
1683 changed = true;
1684 SystemProperties.set("net.dns" + k, "");
1685 }
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001686 }
1687 mNumDnsEntries = j;
1688 } else {
1689 // set per-pid dns for attached secondary nets
1690 List pids = mNetRequestersPids[netType];
1691 for (int y=0; y< pids.size(); y++) {
1692 Integer pid = (Integer)pids.get(y);
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001693 changed = writePidDns(dnses, pid.intValue());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001694 }
1695 }
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001696 if (changed) bumpDns();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001697 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001698 }
1699
Robert Greenwalt20f819c2011-05-03 19:02:44 -07001700 private int getRestoreDefaultNetworkDelay(int networkType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001701 String restoreDefaultNetworkDelayStr = SystemProperties.get(
1702 NETWORK_RESTORE_DELAY_PROP_NAME);
1703 if(restoreDefaultNetworkDelayStr != null &&
1704 restoreDefaultNetworkDelayStr.length() != 0) {
1705 try {
1706 return Integer.valueOf(restoreDefaultNetworkDelayStr);
1707 } catch (NumberFormatException e) {
1708 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001709 }
Robert Greenwalt20f819c2011-05-03 19:02:44 -07001710 // if the system property isn't set, use the value for the apn type
1711 int ret = RESTORE_DEFAULT_NETWORK_DELAY;
1712
1713 if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
1714 (mNetConfigs[networkType] != null)) {
1715 ret = mNetConfigs[networkType].restoreTime;
1716 }
1717 return ret;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001718 }
1719
1720 @Override
1721 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001722 if (mContext.checkCallingOrSelfPermission(
1723 android.Manifest.permission.DUMP)
The Android Open Source Project28527d22009-03-03 19:31:44 -08001724 != PackageManager.PERMISSION_GRANTED) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001725 pw.println("Permission Denial: can't dump ConnectivityService " +
1726 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1727 Binder.getCallingUid());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001728 return;
1729 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001730 pw.println();
1731 for (NetworkStateTracker nst : mNetTrackers) {
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08001732 if (nst != null) {
1733 if (nst.getNetworkInfo().isConnected()) {
1734 pw.println("Active network: " + nst.getNetworkInfo().
1735 getTypeName());
1736 }
1737 pw.println(nst.getNetworkInfo());
1738 pw.println(nst);
1739 pw.println();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001740 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001741 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08001742
1743 pw.println("Network Requester Pids:");
1744 for (int net : mPriorityList) {
1745 String pidString = net + ": ";
1746 for (Object pid : mNetRequestersPids[net]) {
1747 pidString = pidString + pid.toString() + ", ";
1748 }
1749 pw.println(pidString);
1750 }
1751 pw.println();
1752
1753 pw.println("FeatureUsers:");
1754 for (Object requester : mFeatureUsers) {
1755 pw.println(requester.toString());
1756 }
1757 pw.println();
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001758
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001759 synchronized (this) {
1760 pw.println("NetworkTranstionWakeLock is currently " +
1761 (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held.");
1762 pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy);
1763 }
1764 pw.println();
1765
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001766 mTethering.dump(fd, pw, args);
Robert Greenwalt0e80be12010-09-20 14:35:25 -07001767
1768 if (mInetLog != null) {
1769 pw.println();
1770 pw.println("Inet condition reports:");
1771 for(int i = 0; i < mInetLog.size(); i++) {
1772 pw.println(mInetLog.get(i));
1773 }
1774 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001775 }
1776
Robert Greenwalt2034b912009-08-12 16:08:25 -07001777 // must be stateless - things change under us.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001778 private class MyHandler extends Handler {
Wink Saville775aad62010-09-02 19:23:52 -07001779 public MyHandler(Looper looper) {
1780 super(looper);
1781 }
1782
The Android Open Source Project28527d22009-03-03 19:31:44 -08001783 @Override
1784 public void handleMessage(Message msg) {
1785 NetworkInfo info;
1786 switch (msg.what) {
1787 case NetworkStateTracker.EVENT_STATE_CHANGED:
1788 info = (NetworkInfo) msg.obj;
Robert Greenwalt12c44552009-12-07 11:33:18 -08001789 int type = info.getType();
1790 NetworkInfo.State state = info.getState();
Robert Greenwalt12c44552009-12-07 11:33:18 -08001791
Wink Savillee70c6f52010-12-03 12:01:38 -08001792 if (DBG) log("ConnectivityChange for " +
Robert Greenwalt0659da32009-07-16 17:21:39 -07001793 info.getTypeName() + ": " +
Robert Greenwalt12c44552009-12-07 11:33:18 -08001794 state + "/" + info.getDetailedState());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001795
1796 // Connectivity state changed:
1797 // [31-13] Reserved for future use
Robert Greenwalt0659da32009-07-16 17:21:39 -07001798 // [12-9] Network subtype (for mobile network, as defined
1799 // by TelephonyManager)
1800 // [8-3] Detailed state ordinal (as defined by
1801 // NetworkInfo.DetailedState)
The Android Open Source Project28527d22009-03-03 19:31:44 -08001802 // [2-0] Network type (as defined by ConnectivityManager)
1803 int eventLogParam = (info.getType() & 0x7) |
1804 ((info.getDetailedState().ordinal() & 0x3f) << 3) |
1805 (info.getSubtype() << 9);
Doug Zongker2fc96232009-12-04 10:31:43 -08001806 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
Robert Greenwalt0659da32009-07-16 17:21:39 -07001807 eventLogParam);
1808
1809 if (info.getDetailedState() ==
1810 NetworkInfo.DetailedState.FAILED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001811 handleConnectionFailure(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08001812 } else if (state == NetworkInfo.State.DISCONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001813 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08001814 } else if (state == NetworkInfo.State.SUSPENDED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001815 // TODO: need to think this over.
Robert Greenwalt0659da32009-07-16 17:21:39 -07001816 // the logic here is, handle SUSPENDED the same as
1817 // DISCONNECTED. The only difference being we are
1818 // broadcasting an intent with NetworkInfo that's
1819 // suspended. This allows the applications an
1820 // opportunity to handle DISCONNECTED and SUSPENDED
1821 // differently, or not.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001822 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08001823 } else if (state == NetworkInfo.State.CONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001824 handleConnect(info);
1825 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001826 break;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001827 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001828 info = (NetworkInfo) msg.obj;
Robert Greenwalt34848c02011-03-25 13:09:25 -07001829 handleConnectivityChange(info.getType());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001830 break;
Robert Greenwaltccb36f92010-09-24 14:32:21 -07001831 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001832 String causedBy = null;
1833 synchronized (ConnectivityService.this) {
1834 if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
1835 mNetTransitionWakeLock.isHeld()) {
1836 mNetTransitionWakeLock.release();
1837 causedBy = mNetTransitionWakeLockCausedBy;
1838 }
1839 }
1840 if (causedBy != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001841 log("NetTransition Wakelock for " + causedBy + " released by timeout");
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001842 }
Robert Greenwaltcf1a56c2010-09-09 14:05:10 -07001843 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001844 case EVENT_RESTORE_DEFAULT_NETWORK:
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001845 FeatureUser u = (FeatureUser)msg.obj;
1846 u.expire();
Robert Greenwalt986c7412010-09-08 15:24:47 -07001847 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001848 case EVENT_INET_CONDITION_CHANGE:
1849 {
1850 int netType = msg.arg1;
1851 int condition = msg.arg2;
1852 handleInetConditionChange(netType, condition);
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001853 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001854 }
1855 case EVENT_INET_CONDITION_HOLD_END:
1856 {
1857 int netType = msg.arg1;
1858 int sequence = msg.arg2;
1859 handleInetConditionHoldEnd(netType, sequence);
Robert Greenwalt986c7412010-09-08 15:24:47 -07001860 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001861 }
1862 case EVENT_SET_NETWORK_PREFERENCE:
1863 {
1864 int preference = msg.arg1;
1865 handleSetNetworkPreference(preference);
1866 break;
1867 }
1868 case EVENT_SET_BACKGROUND_DATA:
1869 {
1870 boolean enabled = (msg.arg1 == ENABLED);
1871 handleSetBackgroundData(enabled);
1872 break;
1873 }
1874 case EVENT_SET_MOBILE_DATA:
1875 {
1876 boolean enabled = (msg.arg1 == ENABLED);
1877 handleSetMobileData(enabled);
1878 break;
1879 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07001880 case EVENT_APPLY_GLOBAL_HTTP_PROXY:
1881 {
1882 handleDeprecatedGlobalHttpProxy();
Robert Greenwalt34848c02011-03-25 13:09:25 -07001883 break;
1884 }
1885 case EVENT_SET_DEPENDENCY_MET:
1886 {
1887 boolean met = (msg.arg1 == ENABLED);
1888 handleSetDependencyMet(msg.arg2, met);
1889 break;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07001890 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001891 }
1892 }
1893 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001894
1895 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001896 public int tether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001897 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001898
1899 if (isTetheringSupported()) {
1900 return mTethering.tether(iface);
1901 } else {
1902 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1903 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001904 }
1905
1906 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001907 public int untether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001908 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001909
1910 if (isTetheringSupported()) {
1911 return mTethering.untether(iface);
1912 } else {
1913 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1914 }
1915 }
1916
1917 // javadoc from interface
1918 public int getLastTetherError(String iface) {
1919 enforceTetherAccessPermission();
1920
1921 if (isTetheringSupported()) {
1922 return mTethering.getLastTetherError(iface);
1923 } else {
1924 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1925 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001926 }
1927
1928 // TODO - proper iface API for selection by property, inspection, etc
1929 public String[] getTetherableUsbRegexs() {
1930 enforceTetherAccessPermission();
1931 if (isTetheringSupported()) {
1932 return mTethering.getTetherableUsbRegexs();
1933 } else {
1934 return new String[0];
1935 }
1936 }
1937
1938 public String[] getTetherableWifiRegexs() {
1939 enforceTetherAccessPermission();
1940 if (isTetheringSupported()) {
1941 return mTethering.getTetherableWifiRegexs();
1942 } else {
1943 return new String[0];
1944 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001945 }
1946
Danica Chang96567052010-08-11 14:54:43 -07001947 public String[] getTetherableBluetoothRegexs() {
1948 enforceTetherAccessPermission();
1949 if (isTetheringSupported()) {
1950 return mTethering.getTetherableBluetoothRegexs();
1951 } else {
1952 return new String[0];
1953 }
1954 }
1955
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001956 // TODO - move iface listing, queries, etc to new module
1957 // javadoc from interface
1958 public String[] getTetherableIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001959 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001960 return mTethering.getTetherableIfaces();
1961 }
1962
1963 public String[] getTetheredIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001964 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001965 return mTethering.getTetheredIfaces();
1966 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001967
Robert Greenwalt4283ded2010-03-02 17:25:02 -08001968 public String[] getTetheringErroredIfaces() {
1969 enforceTetherAccessPermission();
1970 return mTethering.getErroredIfaces();
1971 }
1972
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001973 // if ro.tether.denied = true we default to no tethering
1974 // gservices could set the secure setting to 1 though to enable it on a build where it
1975 // had previously been turned off.
1976 public boolean isTetheringSupported() {
1977 enforceTetherAccessPermission();
1978 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
Robert Greenwaltf1b66e12010-02-25 12:29:30 -08001979 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
1980 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
1981 return tetherEnabledInSettings && mTetheringConfigValid;
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001982 }
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001983
1984 // An API NetworkStateTrackers can call when they lose their network.
1985 // This will automatically be cleared after X seconds or a network becomes CONNECTED,
1986 // whichever happens first. The timer is started by the first caller and not
1987 // restarted by subsequent callers.
1988 public void requestNetworkTransitionWakelock(String forWhom) {
1989 enforceConnectivityInternalPermission();
1990 synchronized (this) {
1991 if (mNetTransitionWakeLock.isHeld()) return;
1992 mNetTransitionWakeLockSerialNumber++;
1993 mNetTransitionWakeLock.acquire();
1994 mNetTransitionWakeLockCausedBy = forWhom;
1995 }
1996 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltccb36f92010-09-24 14:32:21 -07001997 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001998 mNetTransitionWakeLockSerialNumber, 0),
1999 mNetTransitionWakeLockTimeout);
2000 return;
2001 }
Robert Greenwalt24118e82010-09-09 13:15:32 -07002002
Robert Greenwalt986c7412010-09-08 15:24:47 -07002003 // 100 percent is full good, 0 is full bad.
2004 public void reportInetCondition(int networkType, int percentage) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002005 if (DBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")");
Robert Greenwalt986c7412010-09-08 15:24:47 -07002006 mContext.enforceCallingOrSelfPermission(
2007 android.Manifest.permission.STATUS_BAR,
2008 "ConnectivityService");
2009
Robert Greenwalt0e80be12010-09-20 14:35:25 -07002010 if (DBG) {
2011 int pid = getCallingPid();
2012 int uid = getCallingUid();
2013 String s = pid + "(" + uid + ") reports inet is " +
2014 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
2015 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
2016 mInetLog.add(s);
2017 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
2018 mInetLog.remove(0);
2019 }
2020 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07002021 mHandler.sendMessage(mHandler.obtainMessage(
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002022 EVENT_INET_CONDITION_CHANGE, networkType, percentage));
2023 }
2024
2025 private void handleInetConditionChange(int netType, int condition) {
2026 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002027 log("Inet connectivity change, net=" +
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002028 netType + ", condition=" + condition +
2029 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
2030 }
2031 if (mActiveDefaultNetwork == -1) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002032 if (DBG) log("no active default network - aborting");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002033 return;
2034 }
2035 if (mActiveDefaultNetwork != netType) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002036 if (DBG) log("given net not default - aborting");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002037 return;
2038 }
2039 mDefaultInetCondition = condition;
2040 int delay;
2041 if (mInetConditionChangeInFlight == false) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002042 if (DBG) log("starting a change hold");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002043 // setup a new hold to debounce this
2044 if (mDefaultInetCondition > 50) {
2045 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2046 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
2047 } else {
2048 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2049 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
2050 }
2051 mInetConditionChangeInFlight = true;
2052 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
2053 mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
2054 } else {
2055 // we've set the new condition, when this hold ends that will get
2056 // picked up
Wink Savillee70c6f52010-12-03 12:01:38 -08002057 if (DBG) log("currently in hold - not setting new end evt");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002058 }
2059 }
2060
2061 private void handleInetConditionHoldEnd(int netType, int sequence) {
2062 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002063 log("Inet hold end, net=" + netType +
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002064 ", condition =" + mDefaultInetCondition +
2065 ", published condition =" + mDefaultInetConditionPublished);
2066 }
2067 mInetConditionChangeInFlight = false;
2068
2069 if (mActiveDefaultNetwork == -1) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002070 if (DBG) log("no active default network - aborting");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002071 return;
2072 }
2073 if (mDefaultConnectionSequence != sequence) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002074 if (DBG) log("event hold for obsolete network - aborting");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002075 return;
2076 }
2077 if (mDefaultInetConditionPublished == mDefaultInetCondition) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002078 if (DBG) log("no change in condition - aborting");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002079 return;
2080 }
2081 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
2082 if (networkInfo.isConnected() == false) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002083 if (DBG) log("default network not connected - aborting");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002084 return;
2085 }
2086 mDefaultInetConditionPublished = mDefaultInetCondition;
2087 sendInetConditionBroadcast(networkInfo);
2088 return;
Robert Greenwalt986c7412010-09-08 15:24:47 -07002089 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002090
2091 public synchronized ProxyProperties getProxy() {
2092 if (mGlobalProxy != null) return mGlobalProxy;
2093 if (mDefaultProxy != null) return mDefaultProxy;
2094 return null;
2095 }
2096
2097 public void setGlobalProxy(ProxyProperties proxyProperties) {
2098 enforceChangePermission();
2099 synchronized (mGlobalProxyLock) {
2100 if (proxyProperties == mGlobalProxy) return;
2101 if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
2102 if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
2103
2104 String host = "";
2105 int port = 0;
2106 String exclList = "";
2107 if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) {
2108 mGlobalProxy = new ProxyProperties(proxyProperties);
2109 host = mGlobalProxy.getHost();
2110 port = mGlobalProxy.getPort();
2111 exclList = mGlobalProxy.getExclusionList();
2112 } else {
2113 mGlobalProxy = null;
2114 }
2115 ContentResolver res = mContext.getContentResolver();
2116 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host);
2117 Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port);
Robert Greenwalt6f7c6092010-12-02 11:31:00 -08002118 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002119 exclList);
2120 }
2121
2122 if (mGlobalProxy == null) {
2123 proxyProperties = mDefaultProxy;
2124 }
2125 sendProxyBroadcast(proxyProperties);
2126 }
2127
Robert Greenwalt6f7c6092010-12-02 11:31:00 -08002128 private void loadGlobalProxy() {
2129 ContentResolver res = mContext.getContentResolver();
2130 String host = Settings.Secure.getString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST);
2131 int port = Settings.Secure.getInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, 0);
2132 String exclList = Settings.Secure.getString(res,
2133 Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
2134 if (!TextUtils.isEmpty(host)) {
2135 ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList);
2136 synchronized (mGlobalProxyLock) {
2137 mGlobalProxy = proxyProperties;
2138 }
2139 }
2140 }
2141
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002142 public ProxyProperties getGlobalProxy() {
2143 synchronized (mGlobalProxyLock) {
2144 return mGlobalProxy;
2145 }
2146 }
2147
2148 private void handleApplyDefaultProxy(int type) {
2149 // check if new default - push it out to all VM if so
2150 ProxyProperties proxy = mNetTrackers[type].getLinkProperties().getHttpProxy();
2151 synchronized (this) {
2152 if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
2153 if (mDefaultProxy == proxy) return;
2154 if (!TextUtils.isEmpty(proxy.getHost())) {
2155 mDefaultProxy = proxy;
2156 } else {
2157 mDefaultProxy = null;
2158 }
2159 }
Wink Savillee70c6f52010-12-03 12:01:38 -08002160 if (DBG) log("changing default proxy to " + proxy);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002161 if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return;
2162 if (mGlobalProxy != null) return;
2163 sendProxyBroadcast(proxy);
2164 }
2165
2166 private void handleDeprecatedGlobalHttpProxy() {
2167 String proxy = Settings.Secure.getString(mContext.getContentResolver(),
2168 Settings.Secure.HTTP_PROXY);
2169 if (!TextUtils.isEmpty(proxy)) {
2170 String data[] = proxy.split(":");
2171 String proxyHost = data[0];
2172 int proxyPort = 8080;
2173 if (data.length > 1) {
2174 try {
2175 proxyPort = Integer.parseInt(data[1]);
2176 } catch (NumberFormatException e) {
2177 return;
2178 }
2179 }
2180 ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
2181 setGlobalProxy(p);
2182 }
2183 }
2184
2185 private void sendProxyBroadcast(ProxyProperties proxy) {
Robert Greenwalt611291c2010-12-23 15:51:10 -08002186 if (proxy == null) proxy = new ProxyProperties("", 0, "");
Wink Savillee70c6f52010-12-03 12:01:38 -08002187 log("sending Proxy Broadcast for " + proxy);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002188 Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
Stan Chesnutt1f2a2ac2011-01-06 11:00:19 -08002189 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
2190 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002191 intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
Robert Greenwaltd93dc8f2010-12-06 11:29:17 -08002192 mContext.sendStickyBroadcast(intent);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002193 }
2194
2195 private static class SettingsObserver extends ContentObserver {
2196 private int mWhat;
2197 private Handler mHandler;
2198 SettingsObserver(Handler handler, int what) {
2199 super(handler);
2200 mHandler = handler;
2201 mWhat = what;
2202 }
2203
2204 void observe(Context context) {
2205 ContentResolver resolver = context.getContentResolver();
2206 resolver.registerContentObserver(Settings.Secure.getUriFor(
2207 Settings.Secure.HTTP_PROXY), false, this);
2208 }
2209
2210 @Override
2211 public void onChange(boolean selfChange) {
2212 mHandler.obtainMessage(mWhat).sendToTarget();
2213 }
2214 }
Wink Savillee70c6f52010-12-03 12:01:38 -08002215
Kazuhiro Ondo3a340412011-04-30 20:10:57 -05002216 private void handleTetherIfaceChange(int type) {
2217 String iface = mNetTrackers[type].getLinkProperties().getInterfaceName();
2218
2219 if (isTetheringSupported()) {
2220 mTethering.handleTetherIfaceChange(iface);
2221 }
2222 }
2223
Wink Savillee70c6f52010-12-03 12:01:38 -08002224 private void log(String s) {
2225 Slog.d(TAG, s);
2226 }
2227
2228 private void loge(String s) {
2229 Slog.e(TAG, s);
2230 }
Wink Savilleb7c92c72011-03-12 14:52:01 -08002231 int convertFeatureToNetworkType(String feature){
2232 int networkType = -1;
2233 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
2234 networkType = ConnectivityManager.TYPE_MOBILE_MMS;
2235 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
2236 networkType = ConnectivityManager.TYPE_MOBILE_SUPL;
2237 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
2238 TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
2239 networkType = ConnectivityManager.TYPE_MOBILE_DUN;
2240 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
2241 networkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
2242 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
2243 networkType = ConnectivityManager.TYPE_MOBILE_FOTA;
2244 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
2245 networkType = ConnectivityManager.TYPE_MOBILE_IMS;
2246 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
2247 networkType = ConnectivityManager.TYPE_MOBILE_CBS;
2248 }
2249 return networkType;
2250 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002251}