blob: 9bc7a9f5683dc750fae956d69aaba5ab248277cc [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Jaikumar Ganesh15c74392010-12-21 22:31:44 -080019import android.bluetooth.BluetoothTetheringDataTracker;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.content.ContentResolver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.pm.PackageManager;
Robert Greenwalt434203a2010-10-11 16:00:27 -070024import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.net.ConnectivityManager;
Robert Greenwaltda3d5e62010-12-06 13:56:24 -080026import android.net.DummyDataStateTracker;
Benoit Goby08c39c62010-12-22 14:29:40 -080027import android.net.EthernetDataTracker;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.net.IConnectivityManager;
Jaikumar Ganesh15c74392010-12-21 22:31:44 -080029import android.net.LinkProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.net.MobileDataStateTracker;
Robert Greenwaltd55a6b42011-03-25 13:09:25 -070031import android.net.NetworkConfig;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.net.NetworkInfo;
33import android.net.NetworkStateTracker;
Robert Greenwalt585ac0f2010-08-27 09:24:29 -070034import android.net.NetworkUtils;
Robert Greenwalt434203a2010-10-11 16:00:27 -070035import android.net.Proxy;
36import android.net.ProxyProperties;
Robert Greenwaltaa70f102011-04-28 14:28:50 -070037import android.net.RouteInfo;
Hung-ying Tyan6b818de2011-01-19 16:48:38 +080038import android.net.vpn.VpnManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.net.wifi.WifiStateTracker;
40import android.os.Binder;
41import android.os.Handler;
Wink Savillebb08caf2010-09-02 19:23:52 -070042import android.os.HandlerThread;
Robert Greenwalt42acef32009-08-12 16:08:25 -070043import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.os.Looper;
45import android.os.Message;
Robert Greenwalt14f2ef42010-06-15 12:19:37 -070046import android.os.PowerManager;
Robert Greenwalt42acef32009-08-12 16:08:25 -070047import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.os.ServiceManager;
49import android.os.SystemProperties;
50import android.provider.Settings;
Robert Greenwalt42acef32009-08-12 16:08:25 -070051import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -080053import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054
Robert Greenwalt42acef32009-08-12 16:08:25 -070055import com.android.internal.telephony.Phone;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080056import com.android.server.connectivity.Tethering;
57
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import java.io.FileDescriptor;
Irfan Sheriffd649c122010-06-09 15:39:36 -070059import java.io.FileWriter;
60import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import java.io.PrintWriter;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070062import java.net.InetAddress;
63import java.net.UnknownHostException;
Robert Greenwalt42acef32009-08-12 16:08:25 -070064import java.util.ArrayList;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070065import java.util.Collection;
Robert Greenwaltd825ea42010-12-29 16:15:02 -080066import java.util.concurrent.atomic.AtomicBoolean;
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -070067import java.util.GregorianCalendar;
Robert Greenwalt42acef32009-08-12 16:08:25 -070068import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069
70/**
71 * @hide
72 */
73public class ConnectivityService extends IConnectivityManager.Stub {
74
Robert Greenwaltba175a52010-10-05 19:12:26 -070075 private static final boolean DBG = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 private static final String TAG = "ConnectivityService";
77
Robert Greenwalt42acef32009-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 Greenwaltf43396c2011-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 Greenwaltd0e18ff2010-01-26 11:40:34 -080088 private Tethering mTethering;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -080089 private boolean mTetheringConfigValid = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080090
The Android Open Source Project9066cfe2009-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 Greenwalt42acef32009-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 Sheriffa2a1b912010-06-07 09:03:04 -0700104 private WifiWatchdogService mWifiWatchdogService;
105
Robert Greenwalt42acef32009-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 Project9066cfe2009-03-03 19:31:44 -0800111 private Context mContext;
112 private int mNetworkPreference;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700113 private int mActiveDefaultNetwork = -1;
Robert Greenwaltd7085fc2010-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 Project9066cfe2009-03-03 19:31:44 -0800119
120 private int mNumDnsEntries;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121
122 private boolean mTestMode;
Joe Onorato00092872010-09-01 21:18:22 -0700123 private static ConnectivityService sServiceInstance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124
Robert Greenwaltd825ea42010-12-29 16:15:02 -0800125 private AtomicBoolean mBackgroundDataEnabled = new AtomicBoolean(true);
126
Robert Greenwalt8dcc28b2010-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 Greenwaltf3331232010-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 Greenwalt434203a2010-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 Greenwaltd55a6b42011-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 Greenwalt42acef32009-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 Lockwood0f79b542009-08-14 14:18:49 -0400212 private boolean mSystemReady;
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800213 private Intent mInitialBroadcast;
Mike Lockwood0f79b542009-08-14 14:18:49 -0400214
Robert Greenwalt14f2ef42010-06-15 12:19:37 -0700215 private PowerManager.WakeLock mNetTransitionWakeLock;
216 private String mNetTransitionWakeLockCausedBy = "";
217 private int mNetTransitionWakeLockSerialNumber;
218 private int mNetTransitionWakeLockTimeout;
219
Robert Greenwalte90aa5e2010-09-01 11:34:05 -0700220 private InetAddress mDefaultDns;
221
Robert Greenwalt4e8dfef2010-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 Greenwalt434203a2010-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 Greenwaltd55a6b42011-03-25 13:09:25 -0700234 NetworkConfig[] mNetConfigs;
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700235 int mNetworksDefined;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700236
Robert Greenwalt511288a2009-12-07 11:33:18 -0800237 private static class RadioAttributes {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700238 public int mSimultaneity;
239 public int mType;
240 public RadioAttributes(String init) {
241 String fragments[] = init.split(",");
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700242 mType = Integer.parseInt(fragments[0]);
243 mSimultaneity = Integer.parseInt(fragments[1]);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700244 }
245 }
246 RadioAttributes[] mRadioAttributes;
247
Wink Savillebb08caf2010-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 Project9066cfe2009-03-03 19:31:44 -0800251 }
Wink Savillebb08caf2010-09-02 19:23:52 -0700252 return sServiceInstance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 private ConnectivityService(Context context) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800256 if (DBG) log("ConnectivityService starting up");
Robert Greenwaltde8383c2010-01-14 17:47:58 -0800257
Wink Savillebb08caf2010-09-02 19:23:52 -0700258 HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
259 handlerThread.start();
260 mHandler = new MyHandler(handlerThread.getLooper());
261
Robert Greenwaltd825ea42010-12-29 16:15:02 -0800262 mBackgroundDataEnabled.set(Settings.Secure.getInt(context.getContentResolver(),
263 Settings.Secure.BACKGROUND_DATA, 1) == 1);
264
Robert Greenwaltde8383c2010-01-14 17:47:58 -0800265 // setup our unique device name
Robert Greenwalt733c6292010-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 Greenwaltde8383c2010-01-14 17:47:58 -0800273 }
274
Robert Greenwalte90aa5e2010-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 Greenwalte5903732011-02-22 16:00:42 -0800283 mDefaultDns = NetworkUtils.numericToInetAddress(dns);
284 } catch (IllegalArgumentException e) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800285 loge("Error setting defaultDns using " + dns);
Robert Greenwalte90aa5e2010-09-01 11:34:05 -0700286 }
287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 mContext = context;
Robert Greenwalt14f2ef42010-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 Greenwalt42acef32009-08-12 16:08:25 -0700295 mNetTrackers = new NetworkStateTracker[
296 ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 mNetworkPreference = getPersistedNetworkPreference();
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700299
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700300 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700301 mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700302
Robert Greenwalt42acef32009-08-12 16:08:25 -0700303 // Load device network attributes from resources
Robert Greenwalt42acef32009-08-12 16:08:25 -0700304 String[] raStrings = context.getResources().getStringArray(
305 com.android.internal.R.array.radioAttributes);
Robert Greenwalt5154ae762009-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 Savilleed9c02b2010-12-03 12:01:38 -0800309 loge("Error in radioAttributes - ignoring attempt to define type " + r.mType);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700310 continue;
311 }
312 if (mRadioAttributes[r.mType] != null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800313 loge("Error in radioAttributes - ignoring attempt to redefine type " +
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700314 r.mType);
315 continue;
316 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700317 mRadioAttributes[r.mType] = r;
318 }
319
Robert Greenwalt5154ae762009-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 Greenwaltd55a6b42011-03-25 13:09:25 -0700324 NetworkConfig n = new NetworkConfig(naString);
Wink Saville975c8482011-04-07 14:23:45 -0700325 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800326 loge("Error in networkAttributes - ignoring attempt to define type " +
Wink Saville975c8482011-04-07 14:23:45 -0700327 n.type);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700328 continue;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700329 }
Wink Saville975c8482011-04-07 14:23:45 -0700330 if (mNetConfigs[n.type] != null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800331 loge("Error in networkAttributes - ignoring attempt to redefine type " +
Wink Saville975c8482011-04-07 14:23:45 -0700332 n.type);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700333 continue;
334 }
Wink Saville975c8482011-04-07 14:23:45 -0700335 if (mRadioAttributes[n.radio] == null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800336 loge("Error in networkAttributes - ignoring attempt to use undefined " +
Wink Saville975c8482011-04-07 14:23:45 -0700337 "radio " + n.radio + " in network type " + n.type);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700338 continue;
339 }
Wink Saville975c8482011-04-07 14:23:45 -0700340 mNetConfigs[n.type] = n;
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700341 mNetworksDefined++;
342 } catch(Exception e) {
343 // ignore it - leave the entry null
Robert Greenwalt42acef32009-08-12 16:08:25 -0700344 }
345 }
346
Robert Greenwalt5154ae762009-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 Greenwaltd55a6b42011-03-25 13:09:25 -0700354 for (NetworkConfig na : mNetConfigs) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700355 if (na == null) continue;
Wink Saville975c8482011-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 Greenwalt5154ae762009-10-30 14:17:42 -0700360 }
361 continue;
362 }
Wink Saville975c8482011-04-07 14:23:45 -0700363 mPriorityList[insertionPoint--] = na.type;
Robert Greenwalt5154ae762009-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 Greenwalt42acef32009-08-12 16:08:25 -0700372 mNetRequestersPids[i] = new ArrayList();
373 }
374
375 mFeatureUsers = new ArrayList();
376
Robert Greenwalt5154ae762009-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 Project9066cfe2009-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 Greenwalt5154ae762009-10-30 14:17:42 -0700388 for (int netType : mPriorityList) {
Wink Saville975c8482011-04-07 14:23:45 -0700389 switch (mNetConfigs[netType].radio) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700390 case ConnectivityManager.TYPE_WIFI:
Wink Savilleed9c02b2010-12-03 12:01:38 -0800391 if (DBG) log("Starting Wifi Service.");
Wink Savillec7a98342010-08-13 16:11:42 -0700392 WifiStateTracker wst = new WifiStateTracker();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700393 WifiService wifiService = new WifiService(context);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700394 ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700395 wifiService.checkAndStartWifi();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700396 mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
Wink Savillec7a98342010-08-13 16:11:42 -0700397 wst.startMonitoring(context, mHandler);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700399 //TODO: as part of WWS refactor, create only when needed
Irfan Sheriff0d255342010-07-28 09:35:20 -0700400 mWifiWatchdogService = new WifiWatchdogService(context);
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700401
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700402 break;
403 case ConnectivityManager.TYPE_MOBILE:
Wink Savillec7a98342010-08-13 16:11:42 -0700404 mNetTrackers[netType] = new MobileDataStateTracker(netType,
Wink Saville975c8482011-04-07 14:23:45 -0700405 mNetConfigs[netType].name);
Wink Savillec7a98342010-08-13 16:11:42 -0700406 mNetTrackers[netType].startMonitoring(context, mHandler);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700407 break;
Robert Greenwaltda3d5e62010-12-06 13:56:24 -0800408 case ConnectivityManager.TYPE_DUMMY:
409 mNetTrackers[netType] = new DummyDataStateTracker(netType,
Wink Saville975c8482011-04-07 14:23:45 -0700410 mNetConfigs[netType].name);
Robert Greenwaltda3d5e62010-12-06 13:56:24 -0800411 mNetTrackers[netType].startMonitoring(context, mHandler);
412 break;
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800413 case ConnectivityManager.TYPE_BLUETOOTH:
414 mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
415 mNetTrackers[netType].startMonitoring(context, mHandler);
416 break;
Benoit Goby08c39c62010-12-22 14:29:40 -0800417 case ConnectivityManager.TYPE_ETHERNET:
418 mNetTrackers[netType] = EthernetDataTracker.getInstance();
419 mNetTrackers[netType].startMonitoring(context, mHandler);
420 break;
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700421 default:
Wink Savilleed9c02b2010-12-03 12:01:38 -0800422 loge("Trying to create a DataStateTracker for an unknown radio type " +
Wink Saville975c8482011-04-07 14:23:45 -0700423 mNetConfigs[netType].radio);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700424 continue;
425 }
426 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800427
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800428 mTethering = new Tethering(mContext, mHandler.getLooper());
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800429 mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) ||
430 !mTethering.isDunRequired()) &&
431 (mTethering.getTetherableUsbRegexs().length != 0 ||
Danica Chang6fdd0c62010-08-11 14:54:43 -0700432 mTethering.getTetherableWifiRegexs().length != 0 ||
433 mTethering.getTetherableBluetoothRegexs().length != 0) &&
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800434 mTethering.getUpstreamIfaceRegexs().length != 0);
435
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -0700436 if (DBG) {
437 mInetLog = new ArrayList();
438 }
Robert Greenwalt434203a2010-10-11 16:00:27 -0700439
440 mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
441 mSettingsObserver.observe(mContext);
Robert Greenwaltb7090d62010-12-02 11:31:00 -0800442
443 loadGlobalProxy();
Hung-ying Tyan6b818de2011-01-19 16:48:38 +0800444
445 VpnManager.startVpnService(context);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 }
447
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700448
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 /**
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700450 * Sets the preferred network.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 * @param preference the new preference
452 */
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700453 public void setNetworkPreference(int preference) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 enforceChangePermission();
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700455
456 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 }
458
459 public int getNetworkPreference() {
460 enforceAccessPermission();
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700461 int preference;
462 synchronized(this) {
463 preference = mNetworkPreference;
464 }
465 return preference;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 }
467
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700468 private void handleSetNetworkPreference(int preference) {
469 if (ConnectivityManager.isNetworkTypeValid(preference) &&
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700470 mNetConfigs[preference] != null &&
471 mNetConfigs[preference].isDefault()) {
Robert Greenwalt8dcc28b2010-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 Project9066cfe2009-03-03 19:31:44 -0800481 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700482
The Android Open Source Project9066cfe2009-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 Greenwalt86e9e552009-07-16 17:21:39 -0700494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 /**
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700496 * Make the state of network connectivity conform to the preference settings
The Android Open Source Project9066cfe2009-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 Greenwalt42acef32009-08-12 16:08:25 -0700503 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 return;
505
Robert Greenwalt42acef32009-08-12 16:08:25 -0700506 if (!mNetTrackers[mNetworkPreference].isAvailable())
507 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508
Robert Greenwalt42acef32009-08-12 16:08:25 -0700509 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700510 if (t != mNetworkPreference && mNetTrackers[t] != null &&
Robert Greenwalt42acef32009-08-12 16:08:25 -0700511 mNetTrackers[t].getNetworkInfo().isConnected()) {
Robert Greenwaltec9fe462009-08-20 15:25:14 -0700512 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800513 log("tearing down " + mNetTrackers[t].getNetworkInfo() +
Robert Greenwaltec9fe462009-08-20 15:25:14 -0700514 " in enforcePreference");
515 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700516 teardown(mNetTrackers[t]);
The Android Open Source Project9066cfe2009-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 Greenwalt86e9e552009-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 Project9066cfe2009-03-03 19:31:44 -0800536 */
537 public NetworkInfo getActiveNetworkInfo() {
538 enforceAccessPermission();
Robert Greenwalt42acef32009-08-12 16:08:25 -0700539 for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700540 if (mNetConfigs[type] == null || !mNetConfigs[type].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700541 continue;
542 }
543 NetworkStateTracker t = mNetTrackers[type];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544 NetworkInfo info = t.getNetworkInfo();
545 if (info.isConnected()) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800546 if (DBG && type != mActiveDefaultNetwork) {
547 loge("connected default network is not mActiveDefaultNetwork!");
548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 return info;
550 }
551 }
552 return null;
553 }
554
555 public NetworkInfo getNetworkInfo(int networkType) {
556 enforceAccessPermission();
557 if (ConnectivityManager.isNetworkTypeValid(networkType)) {
558 NetworkStateTracker t = mNetTrackers[networkType];
559 if (t != null)
560 return t.getNetworkInfo();
561 }
562 return null;
563 }
564
565 public NetworkInfo[] getAllNetworkInfo() {
566 enforceAccessPermission();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700567 NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800568 int i = 0;
569 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700570 if(t != null) result[i++] = t.getNetworkInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 }
572 return result;
573 }
574
Robert Greenwaltd192dad2010-09-14 09:18:02 -0700575 /**
576 * Return LinkProperties for the active (i.e., connected) default
577 * network interface. It is assumed that at most one default network
578 * is active at a time. If more than one is active, it is indeterminate
579 * which will be returned.
580 * @return the ip properties for the active network, or {@code null} if
581 * none is active
582 */
583 public LinkProperties getActiveLinkProperties() {
584 enforceAccessPermission();
585 for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700586 if (mNetConfigs[type] == null || !mNetConfigs[type].isDefault()) {
Robert Greenwaltd192dad2010-09-14 09:18:02 -0700587 continue;
588 }
589 NetworkStateTracker t = mNetTrackers[type];
590 NetworkInfo info = t.getNetworkInfo();
591 if (info.isConnected()) {
592 return t.getLinkProperties();
593 }
594 }
595 return null;
596 }
597
598 public LinkProperties getLinkProperties(int networkType) {
599 enforceAccessPermission();
600 if (ConnectivityManager.isNetworkTypeValid(networkType)) {
601 NetworkStateTracker t = mNetTrackers[networkType];
602 if (t != null) return t.getLinkProperties();
603 }
604 return null;
605 }
606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607 public boolean setRadios(boolean turnOn) {
608 boolean result = true;
609 enforceChangePermission();
610 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700611 if (t != null) result = t.setRadio(turnOn) && result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 }
613 return result;
614 }
615
616 public boolean setRadio(int netType, boolean turnOn) {
617 enforceChangePermission();
618 if (!ConnectivityManager.isNetworkTypeValid(netType)) {
619 return false;
620 }
621 NetworkStateTracker tracker = mNetTrackers[netType];
622 return tracker != null && tracker.setRadio(turnOn);
623 }
624
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700625 /**
626 * Used to notice when the calling process dies so we can self-expire
627 *
628 * Also used to know if the process has cleaned up after itself when
629 * our auto-expire timer goes off. The timer has a link to an object.
630 *
631 */
Robert Greenwalt42acef32009-08-12 16:08:25 -0700632 private class FeatureUser implements IBinder.DeathRecipient {
633 int mNetworkType;
634 String mFeature;
635 IBinder mBinder;
636 int mPid;
637 int mUid;
Robert Greenwaltb9285352009-12-21 18:24:07 -0800638 long mCreateTime;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700639
640 FeatureUser(int type, String feature, IBinder binder) {
641 super();
642 mNetworkType = type;
643 mFeature = feature;
644 mBinder = binder;
645 mPid = getCallingPid();
646 mUid = getCallingUid();
Robert Greenwaltb9285352009-12-21 18:24:07 -0800647 mCreateTime = System.currentTimeMillis();
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700648
Robert Greenwalt42acef32009-08-12 16:08:25 -0700649 try {
650 mBinder.linkToDeath(this, 0);
651 } catch (RemoteException e) {
652 binderDied();
653 }
654 }
655
656 void unlinkDeathRecipient() {
657 mBinder.unlinkToDeath(this, 0);
658 }
659
660 public void binderDied() {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800661 log("ConnectivityService FeatureUser binderDied(" +
Robert Greenwaltb9285352009-12-21 18:24:07 -0800662 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
663 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700664 stopUsingNetworkFeature(this, false);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700665 }
666
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700667 public void expire() {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800668 log("ConnectivityService FeatureUser expire(" +
Robert Greenwaltb9285352009-12-21 18:24:07 -0800669 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
670 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700671 stopUsingNetworkFeature(this, false);
672 }
Robert Greenwaltb9285352009-12-21 18:24:07 -0800673
674 public String toString() {
675 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
676 (System.currentTimeMillis() - mCreateTime) + " mSec ago";
677 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700678 }
679
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700680 // javadoc from interface
Robert Greenwalt42acef32009-08-12 16:08:25 -0700681 public int startUsingNetworkFeature(int networkType, String feature,
682 IBinder binder) {
683 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800684 log("startUsingNetworkFeature for net " + networkType + ": " + feature);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 enforceChangePermission();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700687 if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700688 mNetConfigs[networkType] == null) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700689 return Phone.APN_REQUEST_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700691
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700692 FeatureUser f = new FeatureUser(networkType, feature, binder);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700693
694 // TODO - move this into the MobileDataStateTracker
695 int usedNetworkType = networkType;
696 if(networkType == ConnectivityManager.TYPE_MOBILE) {
Wink Saville9d7d6282011-03-12 14:52:01 -0800697 usedNetworkType = convertFeatureToNetworkType(feature);
698 if (usedNetworkType < 0) {
699 Slog.e(TAG, "Can't match any netTracker!");
700 usedNetworkType = networkType;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700701 }
702 }
703 NetworkStateTracker network = mNetTrackers[usedNetworkType];
704 if (network != null) {
Robert Greenwalt0be1e982010-12-15 13:26:33 -0800705 Integer currentPid = new Integer(getCallingPid());
Robert Greenwalt42acef32009-08-12 16:08:25 -0700706 if (usedNetworkType != networkType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700707 NetworkStateTracker radio = mNetTrackers[networkType];
708 NetworkInfo ni = network.getNetworkInfo();
709
710 if (ni.isAvailable() == false) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800711 if (DBG) log("special network not available");
Robert Greenwalte32e8122010-12-29 14:35:21 -0800712 if (!TextUtils.equals(feature,Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
713 return Phone.APN_TYPE_NOT_AVAILABLE;
714 } else {
715 // else make the attempt anyway - probably giving REQUEST_STARTED below
716 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700717 }
718
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700719 synchronized(this) {
720 mFeatureUsers.add(f);
721 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
722 // this gets used for per-pid dns when connected
723 mNetRequestersPids[usedNetworkType].add(currentPid);
724 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700725 }
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700726
Robert Greenwaltf2102f72011-05-03 19:02:44 -0700727 int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
728
729 if (restoreTimer >= 0) {
730 mHandler.sendMessageDelayed(
731 mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer);
732 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700733
Robert Greenwalta64bf832009-08-19 20:19:33 -0700734 if ((ni.isConnectedOrConnecting() == true) &&
735 !network.isTeardownRequested()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700736 if (ni.isConnected() == true) {
737 // add the pid-specific dns
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -0700738 handleDnsConfigurationChange(networkType);
Wink Savilleed9c02b2010-12-03 12:01:38 -0800739 if (DBG) log("special network already active");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700740 return Phone.APN_ALREADY_ACTIVE;
741 }
Wink Savilleed9c02b2010-12-03 12:01:38 -0800742 if (DBG) log("special network already connecting");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700743 return Phone.APN_REQUEST_STARTED;
744 }
745
746 // check if the radio in play can make another contact
747 // assume if cannot for now
748
Wink Savilleed9c02b2010-12-03 12:01:38 -0800749 if (DBG) log("reconnecting to special network");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700750 network.reconnect();
751 return Phone.APN_REQUEST_STARTED;
752 } else {
Robert Greenwalt0be1e982010-12-15 13:26:33 -0800753 // need to remember this unsupported request so we respond appropriately on stop
754 synchronized(this) {
755 mFeatureUsers.add(f);
756 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
757 // this gets used for per-pid dns when connected
758 mNetRequestersPids[usedNetworkType].add(currentPid);
759 }
760 }
Robert Greenwalt02648a42010-05-18 10:52:51 -0700761 return -1;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700762 }
763 }
764 return Phone.APN_TYPE_NOT_AVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 }
766
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700767 // javadoc from interface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 public int stopUsingNetworkFeature(int networkType, String feature) {
Robert Greenwaltb8f16342009-10-06 17:52:40 -0700769 enforceChangePermission();
770
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700771 int pid = getCallingPid();
772 int uid = getCallingUid();
773
774 FeatureUser u = null;
775 boolean found = false;
776
777 synchronized(this) {
778 for (int i = 0; i < mFeatureUsers.size() ; i++) {
779 u = (FeatureUser)mFeatureUsers.get(i);
780 if (uid == u.mUid && pid == u.mPid &&
781 networkType == u.mNetworkType &&
782 TextUtils.equals(feature, u.mFeature)) {
783 found = true;
784 break;
785 }
786 }
787 }
788 if (found && u != null) {
789 // stop regardless of how many other time this proc had called start
790 return stopUsingNetworkFeature(u, true);
791 } else {
792 // none found!
Wink Savilleed9c02b2010-12-03 12:01:38 -0800793 if (DBG) log("ignoring stopUsingNetworkFeature - not a live request");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700794 return 1;
795 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700796 }
797
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700798 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
799 int networkType = u.mNetworkType;
800 String feature = u.mFeature;
801 int pid = u.mPid;
802 int uid = u.mUid;
803
804 NetworkStateTracker tracker = null;
805 boolean callTeardown = false; // used to carry our decision outside of sync block
806
Robert Greenwalt42acef32009-08-12 16:08:25 -0700807 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800808 log("stopUsingNetworkFeature for net " + networkType +
Robert Greenwalt42acef32009-08-12 16:08:25 -0700809 ": " + feature);
810 }
Robert Greenwaltb8f16342009-10-06 17:52:40 -0700811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
813 return -1;
814 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700815
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700816 // need to link the mFeatureUsers list with the mNetRequestersPids state in this
817 // sync block
818 synchronized(this) {
819 // check if this process still has an outstanding start request
820 if (!mFeatureUsers.contains(u)) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800821 if (DBG) log("ignoring - this process has no outstanding requests");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700822 return 1;
823 }
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700824 u.unlinkDeathRecipient();
825 mFeatureUsers.remove(mFeatureUsers.indexOf(u));
826 // If we care about duplicate requests, check for that here.
827 //
828 // This is done to support the extension of a request - the app
829 // can request we start the network feature again and renew the
830 // auto-shutoff delay. Normal "stop" calls from the app though
831 // do not pay attention to duplicate requests - in effect the
832 // API does not refcount and a single stop will counter multiple starts.
833 if (ignoreDups == false) {
834 for (int i = 0; i < mFeatureUsers.size() ; i++) {
835 FeatureUser x = (FeatureUser)mFeatureUsers.get(i);
836 if (x.mUid == u.mUid && x.mPid == u.mPid &&
837 x.mNetworkType == u.mNetworkType &&
838 TextUtils.equals(x.mFeature, u.mFeature)) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800839 if (DBG) log("ignoring stopUsingNetworkFeature as dup is found");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700840 return 1;
841 }
842 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700843 }
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700844
845 // TODO - move to MobileDataStateTracker
846 int usedNetworkType = networkType;
847 if (networkType == ConnectivityManager.TYPE_MOBILE) {
Wink Saville9d7d6282011-03-12 14:52:01 -0800848 usedNetworkType = convertFeatureToNetworkType(feature);
849 if (usedNetworkType < 0) {
850 usedNetworkType = networkType;
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700851 }
852 }
853 tracker = mNetTrackers[usedNetworkType];
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700854 if (tracker == null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800855 if (DBG) log("ignoring - no known tracker for net type " + usedNetworkType);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700856 return -1;
857 }
858 if (usedNetworkType != networkType) {
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700859 Integer currentPid = new Integer(pid);
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700860 mNetRequestersPids[usedNetworkType].remove(currentPid);
Robert Greenwalt421c72b2009-12-17 14:54:59 -0800861 reassessPidDns(pid, true);
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700862 if (mNetRequestersPids[usedNetworkType].size() != 0) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800863 if (DBG) log("not tearing down special network - " +
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700864 "others still using it");
865 return 1;
866 }
867 callTeardown = true;
Robert Greenwalt19b9ab42011-01-10 11:58:31 -0800868 } else {
869 if (DBG) log("not a known feature - dropping");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700870 }
871 }
Wink Savilleed9c02b2010-12-03 12:01:38 -0800872 if (DBG) log("Doing network teardown");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700873 if (callTeardown) {
874 tracker.teardown();
Robert Greenwalt42acef32009-08-12 16:08:25 -0700875 return 1;
876 } else {
Robert Greenwalt02648a42010-05-18 10:52:51 -0700877 return -1;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 }
880
881 /**
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700882 * @deprecated use requestRouteToHostAddress instead
883 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 * Ensure that a network route exists to deliver traffic to the specified
885 * host via the specified network interface.
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700886 * @param networkType the type of the network over which traffic to the
887 * specified host is to be routed
888 * @param hostAddress the IP address of the host to which the route is
889 * desired
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 * @return {@code true} on success, {@code false} on failure
891 */
892 public boolean requestRouteToHost(int networkType, int hostAddress) {
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700893 InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
894
895 if (inetAddress == null) {
896 return false;
897 }
898
899 return requestRouteToHostAddress(networkType, inetAddress.getAddress());
900 }
901
902 /**
903 * Ensure that a network route exists to deliver traffic to the specified
904 * host via the specified network interface.
905 * @param networkType the type of the network over which traffic to the
906 * specified host is to be routed
907 * @param hostAddress the IP address of the host to which the route is
908 * desired
909 * @return {@code true} on success, {@code false} on failure
910 */
911 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 enforceChangePermission();
913 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
914 return false;
915 }
916 NetworkStateTracker tracker = mNetTrackers[networkType];
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700917
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700918 if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
919 tracker.isTeardownRequested()) {
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700920 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800921 log("requestRouteToHostAddress on down network " +
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700922 "(" + networkType + ") - dropped");
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700923 }
924 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 }
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700926 try {
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700927 InetAddress addr = InetAddress.getByAddress(hostAddress);
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700928 return addHostRoute(tracker, addr, 0);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700929 } catch (UnknownHostException e) {}
930 return false;
Irfan Sheriffd649c122010-06-09 15:39:36 -0700931 }
932
933 /**
934 * Ensure that a network route exists to deliver traffic to the specified
935 * host via the mobile data network.
936 * @param hostAddress the IP address of the host to which the route is desired,
937 * in network byte order.
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700938 * TODO - deprecate
Irfan Sheriffd649c122010-06-09 15:39:36 -0700939 * @return {@code true} on success, {@code false} on failure
940 */
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700941 private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress, int cycleCount) {
Irfan Sheriffd649c122010-06-09 15:39:36 -0700942 if (nt.getNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI) {
943 return false;
944 }
945
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700946 LinkProperties lp = nt.getLinkProperties();
947 if ((lp == null) || (hostAddress == null)) return false;
Irfan Sheriffd649c122010-06-09 15:39:36 -0700948
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700949 String interfaceName = lp.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -0700950 if (DBG) {
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700951 log("Requested host route to " + hostAddress + "(" + interfaceName + "), cycleCount=" +
952 cycleCount);
Irfan Sheriffd649c122010-06-09 15:39:36 -0700953 }
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700954 if (interfaceName == null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800955 if (DBG) loge("addHostRoute failed due to null interface name");
Irfan Sheriffd649c122010-06-09 15:39:36 -0700956 return false;
957 }
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700958
959 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), hostAddress);
960 InetAddress gateway = null;
961 if (bestRoute != null) {
962 gateway = bestRoute.getGateway();
963 // if the best route is ourself, don't relf-reference, just add the host route
964 if (hostAddress.equals(gateway)) gateway = null;
965 }
966 if (gateway != null) {
967 if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
968 loge("Error adding hostroute - too much recursion");
969 return false;
970 }
971 if (!addHostRoute(nt, gateway, cycleCount+1)) return false;
972 }
973 return NetworkUtils.addHostRoute(interfaceName, hostAddress, gateway);
974 }
975
976 // TODO support the removal of single host routes. Keep a ref count of them so we
977 // aren't over-zealous
978 private boolean removeHostRoute(NetworkStateTracker nt, InetAddress hostAddress) {
979 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 }
981
982 /**
983 * @see ConnectivityManager#getBackgroundDataSetting()
984 */
985 public boolean getBackgroundDataSetting() {
Robert Greenwaltd825ea42010-12-29 16:15:02 -0800986 return mBackgroundDataEnabled.get();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 /**
990 * @see ConnectivityManager#setBackgroundDataSetting(boolean)
991 */
992 public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) {
993 mContext.enforceCallingOrSelfPermission(
994 android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
995 "ConnectivityService");
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700996
Robert Greenwaltd825ea42010-12-29 16:15:02 -0800997 mBackgroundDataEnabled.set(allowBackgroundDataUsage);
998
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700999 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA,
1000 (allowBackgroundDataUsage ? ENABLED : DISABLED), 0));
1001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001003 private void handleSetBackgroundData(boolean enabled) {
Robert Greenwaltdb4afae2011-02-25 13:44:09 -08001004 Settings.Secure.putInt(mContext.getContentResolver(),
1005 Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0);
1006 Intent broadcast = new Intent(
1007 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
1008 mContext.sendBroadcast(broadcast);
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001009 }
1010
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001011 /**
1012 * @see ConnectivityManager#getMobileDataEnabled()
1013 */
1014 public boolean getMobileDataEnabled() {
Wink Savillee7982682010-12-07 10:31:02 -08001015 // TODO: This detail should probably be in DataConnectionTracker's
1016 // which is where we store the value and maybe make this
1017 // asynchronous.
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001018 enforceAccessPermission();
1019 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
1020 Settings.Secure.MOBILE_DATA, 1) == 1;
Wink Savilleed9c02b2010-12-03 12:01:38 -08001021 if (DBG) log("getMobileDataEnabled returning " + retVal);
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001022 return retVal;
1023 }
1024
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001025 public void setDataDependency(int networkType, boolean met) {
1026 enforceChangePermission();
1027 if (DBG) {
1028 log("setDataDependency(" + networkType + ", " + met + ")");
1029 }
1030 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
1031 (met ? ENABLED : DISABLED), networkType));
1032 }
1033
1034 private void handleSetDependencyMet(int networkType, boolean met) {
1035 if (mNetTrackers[networkType] != null) {
1036 if (DBG) {
1037 log("handleSetDependencyMet(" + networkType + ", " + met + ")");
1038 }
1039 mNetTrackers[networkType].setDependencyMet(met);
1040 }
1041 }
1042
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001043 /**
1044 * @see ConnectivityManager#setMobileDataEnabled(boolean)
1045 */
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001046 public void setMobileDataEnabled(boolean enabled) {
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001047 enforceChangePermission();
Wink Savilleed9c02b2010-12-03 12:01:38 -08001048 if (DBG) log("setMobileDataEnabled(" + enabled + ")");
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001049
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001050 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001051 (enabled ? ENABLED : DISABLED), 0));
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001052 }
1053
1054 private void handleSetMobileData(boolean enabled) {
Wink Savillee7982682010-12-07 10:31:02 -08001055 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
1056 if (DBG) {
1057 Slog.d(TAG, mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001058 }
Wink Savillee7982682010-12-07 10:31:02 -08001059 mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled);
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001060 }
1061 }
1062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 private void enforceAccessPermission() {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001064 mContext.enforceCallingOrSelfPermission(
1065 android.Manifest.permission.ACCESS_NETWORK_STATE,
1066 "ConnectivityService");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 }
1068
1069 private void enforceChangePermission() {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001070 mContext.enforceCallingOrSelfPermission(
1071 android.Manifest.permission.CHANGE_NETWORK_STATE,
1072 "ConnectivityService");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001073 }
1074
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001075 // TODO Make this a special check when it goes public
1076 private void enforceTetherChangePermission() {
1077 mContext.enforceCallingOrSelfPermission(
1078 android.Manifest.permission.CHANGE_NETWORK_STATE,
1079 "ConnectivityService");
1080 }
1081
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001082 private void enforceTetherAccessPermission() {
1083 mContext.enforceCallingOrSelfPermission(
1084 android.Manifest.permission.ACCESS_NETWORK_STATE,
1085 "ConnectivityService");
1086 }
1087
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001088 private void enforceConnectivityInternalPermission() {
1089 mContext.enforceCallingOrSelfPermission(
1090 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1091 "ConnectivityService");
1092 }
1093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 /**
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001095 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
1096 * network, we ignore it. If it is for the active network, we send out a
1097 * broadcast. But first, we check whether it might be possible to connect
1098 * to a different network.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 * @param info the {@code NetworkInfo} for the network
1100 */
1101 private void handleDisconnect(NetworkInfo info) {
1102
Robert Greenwalt42acef32009-08-12 16:08:25 -07001103 int prevNetType = info.getType();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104
Robert Greenwalt42acef32009-08-12 16:08:25 -07001105 mNetTrackers[prevNetType].setTeardownRequested(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 /*
1107 * If the disconnected network is not the active one, then don't report
1108 * this as a loss of connectivity. What probably happened is that we're
1109 * getting the disconnect for a network that we explicitly disabled
1110 * in accordance with network preference policies.
1111 */
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001112 if (!mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001113 List pids = mNetRequestersPids[prevNetType];
1114 for (int i = 0; i<pids.size(); i++) {
1115 Integer pid = (Integer)pids.get(i);
1116 // will remove them because the net's no longer connected
1117 // need to do this now as only now do we know the pids and
1118 // can properly null things that are no longer referenced.
1119 reassessPidDns(pid.intValue(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 }
1122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1124 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1125 if (info.isFailover()) {
1126 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1127 info.setFailover(false);
1128 }
1129 if (info.getReason() != null) {
1130 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1131 }
1132 if (info.getExtraInfo() != null) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001133 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1134 info.getExtraInfo());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001136
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001137 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001138 tryFailover(prevNetType);
1139 if (mActiveDefaultNetwork != -1) {
1140 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001141 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1142 } else {
Robert Greenwalt029be812010-09-20 18:01:43 -07001143 mDefaultInetConditionPublished = 0; // we're not connected anymore
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001144 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1145 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001146 }
Robert Greenwalt029be812010-09-20 18:01:43 -07001147 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001148 // do this before we broadcast the change
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001149 handleConnectivityChange(prevNetType);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001150
1151 sendStickyBroadcast(intent);
1152 /*
1153 * If the failover network is already connected, then immediately send
1154 * out a followup broadcast indicating successful failover
1155 */
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001156 if (mActiveDefaultNetwork != -1) {
1157 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001158 }
1159 }
1160
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001161 private void tryFailover(int prevNetType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001162 /*
Robert Greenwaltbff90182011-01-06 15:41:07 -08001163 * If this is a default network, check if other defaults are available.
1164 * Try to reconnect on all available and let them hash it out when
1165 * more than one connects.
Robert Greenwalt42acef32009-08-12 16:08:25 -07001166 */
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001167 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001168 if (mActiveDefaultNetwork == prevNetType) {
1169 mActiveDefaultNetwork = -1;
1170 }
1171
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001172 // don't signal a reconnect for anything lower or equal priority than our
1173 // current connected default
1174 // TODO - don't filter by priority now - nice optimization but risky
1175// int currentPriority = -1;
1176// if (mActiveDefaultNetwork != -1) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001177// currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority;
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001178// }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001179 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -07001180 if (checkType == prevNetType) continue;
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001181 if (mNetConfigs[checkType] == null) continue;
1182 if (!mNetConfigs[checkType].isDefault()) continue;
Wink Saville9f7a0b22011-01-26 15:43:49 -08001183
1184// Enabling the isAvailable() optimization caused mobile to not get
1185// selected if it was in the middle of error handling. Specifically
1186// a moble connection that took 30 seconds to complete the DEACTIVATE_DATA_CALL
1187// would not be available and we wouldn't get connected to anything.
1188// So removing the isAvailable() optimization below for now. TODO: This
1189// optimization should work and we need to investigate why it doesn't work.
1190// This could be related to how DEACTIVATE_DATA_CALL is reporting its
1191// complete before it is really complete.
1192// if (!mNetTrackers[checkType].isAvailable()) continue;
1193
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001194// if (currentPriority >= mNetConfigs[checkType].mPriority) continue;
Robert Greenwalt42acef32009-08-12 16:08:25 -07001195
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001196 NetworkStateTracker checkTracker = mNetTrackers[checkType];
1197 NetworkInfo checkInfo = checkTracker.getNetworkInfo();
1198 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
1199 checkInfo.setFailover(true);
1200 checkTracker.reconnect();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001201 }
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001202 if (DBG) log("Attempting to switch to " + checkInfo.getTypeName());
Robert Greenwalt42acef32009-08-12 16:08:25 -07001203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 }
1206
1207 private void sendConnectedBroadcast(NetworkInfo info) {
Robert Greenwalt1e9aac22010-09-15 17:36:33 -07001208 sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION);
1209 }
1210
1211 private void sendInetConditionBroadcast(NetworkInfo info) {
1212 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1213 }
1214
1215 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1216 Intent intent = new Intent(bcastType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1218 if (info.isFailover()) {
1219 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1220 info.setFailover(false);
1221 }
1222 if (info.getReason() != null) {
1223 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1224 }
1225 if (info.getExtraInfo() != null) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001226 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1227 info.getExtraInfo());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 }
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001229 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001230 sendStickyBroadcast(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 }
1232
1233 /**
1234 * Called when an attempt to fail over to another network has failed.
1235 * @param info the {@link NetworkInfo} for the failed network
1236 */
1237 private void handleConnectionFailure(NetworkInfo info) {
1238 mNetTrackers[info.getType()].setTeardownRequested(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239
Robert Greenwalt42acef32009-08-12 16:08:25 -07001240 String reason = info.getReason();
1241 String extraInfo = info.getExtraInfo();
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001242
Robert Greenwalt572172b2010-10-08 16:35:52 -07001243 String reasonText;
1244 if (reason == null) {
1245 reasonText = ".";
1246 } else {
1247 reasonText = " (" + reason + ").";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001248 }
Wink Savilleed9c02b2010-12-03 12:01:38 -08001249 loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001250
1251 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1252 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1253 if (getActiveNetworkInfo() == null) {
1254 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1255 }
1256 if (reason != null) {
1257 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
1258 }
1259 if (extraInfo != null) {
1260 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
1261 }
1262 if (info.isFailover()) {
1263 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1264 info.setFailover(false);
1265 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001266
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001267 if (mNetConfigs[info.getType()].isDefault()) {
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001268 tryFailover(info.getType());
1269 if (mActiveDefaultNetwork != -1) {
1270 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001271 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1272 } else {
Robert Greenwalt029be812010-09-20 18:01:43 -07001273 mDefaultInetConditionPublished = 0;
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001274 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1275 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001276 }
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001277
Robert Greenwalt029be812010-09-20 18:01:43 -07001278 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001279 sendStickyBroadcast(intent);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001280 /*
1281 * If the failover network is already connected, then immediately send
1282 * out a followup broadcast indicating successful failover
1283 */
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001284 if (mActiveDefaultNetwork != -1) {
1285 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001286 }
Mike Lockwood0f79b542009-08-14 14:18:49 -04001287 }
1288
1289 private void sendStickyBroadcast(Intent intent) {
1290 synchronized(this) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001291 if (!mSystemReady) {
1292 mInitialBroadcast = new Intent(intent);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001293 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001294 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1295 mContext.sendStickyBroadcast(intent);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001296 }
1297 }
1298
1299 void systemReady() {
1300 synchronized(this) {
1301 mSystemReady = true;
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001302 if (mInitialBroadcast != null) {
1303 mContext.sendStickyBroadcast(mInitialBroadcast);
1304 mInitialBroadcast = null;
Mike Lockwood0f79b542009-08-14 14:18:49 -04001305 }
1306 }
Robert Greenwalt434203a2010-10-11 16:00:27 -07001307 // load the global proxy at startup
1308 mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001309 }
1310
1311 private void handleConnect(NetworkInfo info) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001312 int type = info.getType();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001313
1314 // snapshot isFailover, because sendConnectedBroadcast() resets it
1315 boolean isFailover = info.isFailover();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001316 NetworkStateTracker thisNet = mNetTrackers[type];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001317
Robert Greenwalt42acef32009-08-12 16:08:25 -07001318 // if this is a default net and other default is running
1319 // kill the one not preferred
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001320 if (mNetConfigs[type].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001321 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
1322 if ((type != mNetworkPreference &&
Wink Saville975c8482011-04-07 14:23:45 -07001323 mNetConfigs[mActiveDefaultNetwork].priority >
1324 mNetConfigs[type].priority) ||
Robert Greenwalt42acef32009-08-12 16:08:25 -07001325 mNetworkPreference == mActiveDefaultNetwork) {
1326 // don't accept this one
Wink Savilleed9c02b2010-12-03 12:01:38 -08001327 if (DBG) {
1328 log("Not broadcasting CONNECT_ACTION " +
Robert Greenwalt42acef32009-08-12 16:08:25 -07001329 "to torn down network " + info.getTypeName());
Wink Savilleed9c02b2010-12-03 12:01:38 -08001330 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001331 teardown(thisNet);
1332 return;
1333 } else {
1334 // tear down the other
1335 NetworkStateTracker otherNet =
1336 mNetTrackers[mActiveDefaultNetwork];
Wink Savilleed9c02b2010-12-03 12:01:38 -08001337 if (DBG) {
1338 log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
Robert Greenwalt42acef32009-08-12 16:08:25 -07001339 " teardown");
Wink Savilleed9c02b2010-12-03 12:01:38 -08001340 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001341 if (!teardown(otherNet)) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001342 loge("Network declined teardown request");
Robert Greenwalt42acef32009-08-12 16:08:25 -07001343 return;
1344 }
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001345 }
1346 }
1347 synchronized (ConnectivityService.this) {
1348 // have a new default network, release the transition wakelock in a second
1349 // if it's held. The second pause is to allow apps to reconnect over the
1350 // new network
1351 if (mNetTransitionWakeLock.isHeld()) {
1352 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltf3331232010-09-24 14:32:21 -07001353 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001354 mNetTransitionWakeLockSerialNumber, 0),
1355 1000);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001356 }
1357 }
1358 mActiveDefaultNetwork = type;
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001359 // this will cause us to come up initially as unconnected and switching
1360 // to connected after our normal pause unless somebody reports us as reall
1361 // disconnected
1362 mDefaultInetConditionPublished = 0;
1363 mDefaultConnectionSequence++;
1364 mInetConditionChangeInFlight = false;
1365 // Don't do this - if we never sign in stay, grey
1366 //reportNetworkCondition(mActiveDefaultNetwork, 100);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 thisNet.setTeardownRequested(false);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001369 updateNetworkSettings(thisNet);
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001370 handleConnectivityChange(type);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001371 sendConnectedBroadcast(info);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 }
1373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 /**
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001375 * After a change in the connectivity state of a network. We're mainly
1376 * concerned with making sure that the list of DNS servers is set up
1377 * according to which networks are connected, and ensuring that the
1378 * right routing table entries exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 */
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001380 private void handleConnectivityChange(int netType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 /*
Robert Greenwalt42acef32009-08-12 16:08:25 -07001382 * If a non-default network is enabled, add the host routes that
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001383 * will allow it's DNS servers to be accessed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 */
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001385 handleDnsConfigurationChange(netType);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001386
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001387 if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001388 if (mNetConfigs[netType].isDefault()) {
Robert Greenwalt434203a2010-10-11 16:00:27 -07001389 handleApplyDefaultProxy(netType);
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001390 addDefaultRoute(mNetTrackers[netType]);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001391 } else {
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001392 addPrivateDnsRoutes(mNetTrackers[netType]);
1393 }
1394 } else {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001395 if (mNetConfigs[netType].isDefault()) {
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001396 removeDefaultRoute(mNetTrackers[netType]);
1397 } else {
1398 removePrivateDnsRoutes(mNetTrackers[netType]);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 }
1401 }
1402
Irfan Sheriffd649c122010-06-09 15:39:36 -07001403 private void addPrivateDnsRoutes(NetworkStateTracker nt) {
Irfan Sheriffd649c122010-06-09 15:39:36 -07001404 boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet();
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001405 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001406 if (p == null) return;
1407 String interfaceName = p.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -07001408
1409 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001410 log("addPrivateDnsRoutes for " + nt +
Irfan Sheriffd649c122010-06-09 15:39:36 -07001411 "(" + interfaceName + ") - mPrivateDnsRouteSet = " + privateDnsRouteSet);
1412 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001413 if (interfaceName != null && !privateDnsRouteSet) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001414 Collection<InetAddress> dnsList = p.getDnses();
1415 for (InetAddress dns : dnsList) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001416 if (DBG) log(" adding " + dns);
Robert Greenwaltf43396c2011-05-06 17:10:53 -07001417 addHostRoute(nt, dns, 0);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001418 }
1419 nt.privateDnsRouteSet(true);
1420 }
1421 }
1422
1423 private void removePrivateDnsRoutes(NetworkStateTracker nt) {
1424 // TODO - we should do this explicitly but the NetUtils api doesnt
1425 // support this yet - must remove all. No worse than before
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001426 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001427 if (p == null) return;
1428 String interfaceName = p.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -07001429 boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet();
1430 if (interfaceName != null && privateDnsRouteSet) {
1431 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001432 log("removePrivateDnsRoutes for " + nt.getNetworkInfo().getTypeName() +
Irfan Sheriffd649c122010-06-09 15:39:36 -07001433 " (" + interfaceName + ")");
1434 }
1435 NetworkUtils.removeHostRoutes(interfaceName);
1436 nt.privateDnsRouteSet(false);
1437 }
1438 }
1439
Irfan Sheriffd649c122010-06-09 15:39:36 -07001440
1441 private void addDefaultRoute(NetworkStateTracker nt) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001442 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001443 if (p == null) return;
1444 String interfaceName = p.getInterfaceName();
Robert Greenwalt992564e2011-02-09 13:56:06 -08001445 if (TextUtils.isEmpty(interfaceName)) return;
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001446 for (RouteInfo route : p.getRoutes()) {
Irfan Sheriffd649c122010-06-09 15:39:36 -07001447
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001448 //TODO - handle non-default routes
1449 if (route.isDefaultRoute()) {
1450 InetAddress gateway = route.getGateway();
Robert Greenwaltf43396c2011-05-06 17:10:53 -07001451 if (addHostRoute(nt, gateway, 0) &&
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001452 NetworkUtils.addDefaultRoute(interfaceName, gateway)) {
1453 if (DBG) {
1454 NetworkInfo networkInfo = nt.getNetworkInfo();
1455 log("addDefaultRoute for " + networkInfo.getTypeName() +
1456 " (" + interfaceName + "), GatewayAddr=" +
1457 gateway.getHostAddress());
1458 }
Robert Greenwaltedcb4f92011-03-22 18:47:42 -07001459 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001460 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001461 }
1462 }
1463
1464
1465 public void removeDefaultRoute(NetworkStateTracker nt) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001466 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001467 if (p == null) return;
1468 String interfaceName = p.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -07001469
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001470 if (interfaceName != null) {
Robert Greenwaltedcb4f92011-03-22 18:47:42 -07001471 if (NetworkUtils.removeDefaultRoute(interfaceName) >= 0) {
1472 if (DBG) {
1473 NetworkInfo networkInfo = nt.getNetworkInfo();
1474 log("removeDefaultRoute for " + networkInfo.getTypeName() + " (" +
1475 interfaceName + ")");
1476 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001477 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001478 }
1479 }
1480
1481 /**
1482 * Reads the network specific TCP buffer sizes from SystemProperties
1483 * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
1484 * wide use
1485 */
1486 public void updateNetworkSettings(NetworkStateTracker nt) {
1487 String key = nt.getTcpBufferSizesPropName();
1488 String bufferSizes = SystemProperties.get(key);
1489
1490 if (bufferSizes.length() == 0) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001491 loge(key + " not found in system properties. Using defaults");
Irfan Sheriffd649c122010-06-09 15:39:36 -07001492
1493 // Setting to default values so we won't be stuck to previous values
1494 key = "net.tcp.buffersize.default";
1495 bufferSizes = SystemProperties.get(key);
1496 }
1497
1498 // Set values in kernel
1499 if (bufferSizes.length() != 0) {
1500 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001501 log("Setting TCP values: [" + bufferSizes
Irfan Sheriffd649c122010-06-09 15:39:36 -07001502 + "] which comes from [" + key + "]");
1503 }
1504 setBufferSize(bufferSizes);
1505 }
1506 }
1507
1508 /**
1509 * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max]
1510 * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem
1511 *
1512 * @param bufferSizes in the format of "readMin, readInitial, readMax,
1513 * writeMin, writeInitial, writeMax"
1514 */
1515 private void setBufferSize(String bufferSizes) {
1516 try {
1517 String[] values = bufferSizes.split(",");
1518
1519 if (values.length == 6) {
1520 final String prefix = "/sys/kernel/ipv4/tcp_";
1521 stringToFile(prefix + "rmem_min", values[0]);
1522 stringToFile(prefix + "rmem_def", values[1]);
1523 stringToFile(prefix + "rmem_max", values[2]);
1524 stringToFile(prefix + "wmem_min", values[3]);
1525 stringToFile(prefix + "wmem_def", values[4]);
1526 stringToFile(prefix + "wmem_max", values[5]);
1527 } else {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001528 loge("Invalid buffersize string: " + bufferSizes);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001529 }
1530 } catch (IOException e) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001531 loge("Can't set tcp buffer sizes:" + e);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001532 }
1533 }
1534
1535 /**
1536 * Writes string to file. Basically same as "echo -n $string > $filename"
1537 *
1538 * @param filename
1539 * @param string
1540 * @throws IOException
1541 */
1542 private void stringToFile(String filename, String string) throws IOException {
1543 FileWriter out = new FileWriter(filename);
1544 try {
1545 out.write(string);
1546 } finally {
1547 out.close();
1548 }
1549 }
1550
1551
Robert Greenwalt42acef32009-08-12 16:08:25 -07001552 /**
1553 * Adjust the per-process dns entries (net.dns<x>.<pid>) based
1554 * on the highest priority active net which this process requested.
1555 * If there aren't any, clear it out
1556 */
1557 private void reassessPidDns(int myPid, boolean doBump)
1558 {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001559 if (DBG) log("reassessPidDns for pid " + myPid);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001560 for(int i : mPriorityList) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001561 if (mNetConfigs[i].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001562 continue;
1563 }
1564 NetworkStateTracker nt = mNetTrackers[i];
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001565 if (nt.getNetworkInfo().isConnected() &&
1566 !nt.isTeardownRequested()) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001567 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001568 if (p == null) continue;
Robert Greenwalt42acef32009-08-12 16:08:25 -07001569 List pids = mNetRequestersPids[i];
1570 for (int j=0; j<pids.size(); j++) {
1571 Integer pid = (Integer)pids.get(j);
1572 if (pid.intValue() == myPid) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001573 Collection<InetAddress> dnses = p.getDnses();
1574 writePidDns(dnses, myPid);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001575 if (doBump) {
1576 bumpDns();
1577 }
1578 return;
1579 }
1580 }
1581 }
1582 }
1583 // nothing found - delete
1584 for (int i = 1; ; i++) {
1585 String prop = "net.dns" + i + "." + myPid;
1586 if (SystemProperties.get(prop).length() == 0) {
1587 if (doBump) {
1588 bumpDns();
1589 }
1590 return;
1591 }
1592 SystemProperties.set(prop, "");
1593 }
1594 }
1595
Robert Greenwalt10398722010-12-17 15:20:36 -08001596 // return true if results in a change
1597 private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001598 int j = 1;
Robert Greenwalt10398722010-12-17 15:20:36 -08001599 boolean changed = false;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001600 for (InetAddress dns : dnses) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001601 String dnsString = dns.getHostAddress();
1602 if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
1603 changed = true;
1604 SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
1605 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001606 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001607 return changed;
Robert Greenwalt42acef32009-08-12 16:08:25 -07001608 }
1609
1610 private void bumpDns() {
1611 /*
1612 * Bump the property that tells the name resolver library to reread
1613 * the DNS server list from the properties.
1614 */
1615 String propVal = SystemProperties.get("net.dnschange");
1616 int n = 0;
1617 if (propVal.length() != 0) {
1618 try {
1619 n = Integer.parseInt(propVal);
1620 } catch (NumberFormatException e) {}
1621 }
1622 SystemProperties.set("net.dnschange", "" + (n+1));
Robert Greenwalt03595d02010-11-02 14:08:23 -07001623 /*
1624 * Tell the VMs to toss their DNS caches
1625 */
1626 Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
1627 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Stan Chesnutt3d1db862011-01-05 17:14:03 -08001628 /*
1629 * Connectivity events can happen before boot has completed ...
1630 */
1631 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt03595d02010-11-02 14:08:23 -07001632 mContext.sendBroadcast(intent);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001633 }
1634
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001635 private void handleDnsConfigurationChange(int netType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001636 // add default net's dns entries
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001637 NetworkStateTracker nt = mNetTrackers[netType];
1638 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001639 LinkProperties p = nt.getLinkProperties();
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001640 if (p == null) return;
1641 Collection<InetAddress> dnses = p.getDnses();
Robert Greenwalt10398722010-12-17 15:20:36 -08001642 boolean changed = false;
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001643 if (mNetConfigs[netType].isDefault()) {
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001644 int j = 1;
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001645 if (dnses.size() == 0 && mDefaultDns != null) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001646 String dnsString = mDefaultDns.getHostAddress();
1647 if (!dnsString.equals(SystemProperties.get("net.dns1"))) {
1648 if (DBG) {
1649 log("no dns provided - using " + dnsString);
1650 }
1651 changed = true;
1652 SystemProperties.set("net.dns1", dnsString);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001653 }
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001654 j++;
1655 } else {
1656 for (InetAddress dns : dnses) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001657 String dnsString = dns.getHostAddress();
1658 if (!changed && dnsString.equals(SystemProperties.get("net.dns" + j))) {
1659 j++;
1660 continue;
1661 }
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001662 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001663 log("adding dns " + dns + " for " +
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001664 nt.getNetworkInfo().getTypeName());
1665 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001666 changed = true;
1667 SystemProperties.set("net.dns" + j++, dnsString);
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001668 }
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001669 }
1670 for (int k=j ; k<mNumDnsEntries; k++) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001671 if (changed || !TextUtils.isEmpty(SystemProperties.get("net.dns" + k))) {
1672 if (DBG) log("erasing net.dns" + k);
1673 changed = true;
1674 SystemProperties.set("net.dns" + k, "");
1675 }
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001676 }
1677 mNumDnsEntries = j;
1678 } else {
1679 // set per-pid dns for attached secondary nets
1680 List pids = mNetRequestersPids[netType];
1681 for (int y=0; y< pids.size(); y++) {
1682 Integer pid = (Integer)pids.get(y);
Robert Greenwalt10398722010-12-17 15:20:36 -08001683 changed = writePidDns(dnses, pid.intValue());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 }
1685 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001686 if (changed) bumpDns();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001688 }
1689
Robert Greenwaltf2102f72011-05-03 19:02:44 -07001690 private int getRestoreDefaultNetworkDelay(int networkType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001691 String restoreDefaultNetworkDelayStr = SystemProperties.get(
1692 NETWORK_RESTORE_DELAY_PROP_NAME);
1693 if(restoreDefaultNetworkDelayStr != null &&
1694 restoreDefaultNetworkDelayStr.length() != 0) {
1695 try {
1696 return Integer.valueOf(restoreDefaultNetworkDelayStr);
1697 } catch (NumberFormatException e) {
1698 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 }
Robert Greenwaltf2102f72011-05-03 19:02:44 -07001700 // if the system property isn't set, use the value for the apn type
1701 int ret = RESTORE_DEFAULT_NETWORK_DELAY;
1702
1703 if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
1704 (mNetConfigs[networkType] != null)) {
1705 ret = mNetConfigs[networkType].restoreTime;
1706 }
1707 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 }
1709
1710 @Override
1711 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001712 if (mContext.checkCallingOrSelfPermission(
1713 android.Manifest.permission.DUMP)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 != PackageManager.PERMISSION_GRANTED) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001715 pw.println("Permission Denial: can't dump ConnectivityService " +
1716 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1717 Binder.getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 return;
1719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 pw.println();
1721 for (NetworkStateTracker nst : mNetTrackers) {
Robert Greenwaltb9285352009-12-21 18:24:07 -08001722 if (nst != null) {
1723 if (nst.getNetworkInfo().isConnected()) {
1724 pw.println("Active network: " + nst.getNetworkInfo().
1725 getTypeName());
1726 }
1727 pw.println(nst.getNetworkInfo());
1728 pw.println(nst);
1729 pw.println();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 }
Robert Greenwaltb9285352009-12-21 18:24:07 -08001732
1733 pw.println("Network Requester Pids:");
1734 for (int net : mPriorityList) {
1735 String pidString = net + ": ";
1736 for (Object pid : mNetRequestersPids[net]) {
1737 pidString = pidString + pid.toString() + ", ";
1738 }
1739 pw.println(pidString);
1740 }
1741 pw.println();
1742
1743 pw.println("FeatureUsers:");
1744 for (Object requester : mFeatureUsers) {
1745 pw.println(requester.toString());
1746 }
1747 pw.println();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001748
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001749 synchronized (this) {
1750 pw.println("NetworkTranstionWakeLock is currently " +
1751 (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held.");
1752 pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy);
1753 }
1754 pw.println();
1755
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001756 mTethering.dump(fd, pw, args);
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -07001757
1758 if (mInetLog != null) {
1759 pw.println();
1760 pw.println("Inet condition reports:");
1761 for(int i = 0; i < mInetLog.size(); i++) {
1762 pw.println(mInetLog.get(i));
1763 }
1764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 }
1766
Robert Greenwalt42acef32009-08-12 16:08:25 -07001767 // must be stateless - things change under us.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 private class MyHandler extends Handler {
Wink Savillebb08caf2010-09-02 19:23:52 -07001769 public MyHandler(Looper looper) {
1770 super(looper);
1771 }
1772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 @Override
1774 public void handleMessage(Message msg) {
1775 NetworkInfo info;
1776 switch (msg.what) {
1777 case NetworkStateTracker.EVENT_STATE_CHANGED:
1778 info = (NetworkInfo) msg.obj;
Robert Greenwalt511288a2009-12-07 11:33:18 -08001779 int type = info.getType();
1780 NetworkInfo.State state = info.getState();
Robert Greenwalt511288a2009-12-07 11:33:18 -08001781
Wink Savilleed9c02b2010-12-03 12:01:38 -08001782 if (DBG) log("ConnectivityChange for " +
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001783 info.getTypeName() + ": " +
Robert Greenwalt511288a2009-12-07 11:33:18 -08001784 state + "/" + info.getDetailedState());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785
1786 // Connectivity state changed:
1787 // [31-13] Reserved for future use
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001788 // [12-9] Network subtype (for mobile network, as defined
1789 // by TelephonyManager)
1790 // [8-3] Detailed state ordinal (as defined by
1791 // NetworkInfo.DetailedState)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 // [2-0] Network type (as defined by ConnectivityManager)
1793 int eventLogParam = (info.getType() & 0x7) |
1794 ((info.getDetailedState().ordinal() & 0x3f) << 3) |
1795 (info.getSubtype() << 9);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001796 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001797 eventLogParam);
1798
1799 if (info.getDetailedState() ==
1800 NetworkInfo.DetailedState.FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 handleConnectionFailure(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001802 } else if (state == NetworkInfo.State.DISCONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 handleDisconnect(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001804 } else if (state == NetworkInfo.State.SUSPENDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 // TODO: need to think this over.
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001806 // the logic here is, handle SUSPENDED the same as
1807 // DISCONNECTED. The only difference being we are
1808 // broadcasting an intent with NetworkInfo that's
1809 // suspended. This allows the applications an
1810 // opportunity to handle DISCONNECTED and SUSPENDED
1811 // differently, or not.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 handleDisconnect(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001813 } else if (state == NetworkInfo.State.CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 handleConnect(info);
1815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001818 info = (NetworkInfo) msg.obj;
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001819 handleConnectivityChange(info.getType());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 break;
Robert Greenwaltf3331232010-09-24 14:32:21 -07001821 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001822 String causedBy = null;
1823 synchronized (ConnectivityService.this) {
1824 if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
1825 mNetTransitionWakeLock.isHeld()) {
1826 mNetTransitionWakeLock.release();
1827 causedBy = mNetTransitionWakeLockCausedBy;
1828 }
1829 }
1830 if (causedBy != null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001831 log("NetTransition Wakelock for " + causedBy + " released by timeout");
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001832 }
Robert Greenwalt057d5e92010-09-09 14:05:10 -07001833 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001834 case EVENT_RESTORE_DEFAULT_NETWORK:
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -07001835 FeatureUser u = (FeatureUser)msg.obj;
1836 u.expire();
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001837 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001838 case EVENT_INET_CONDITION_CHANGE:
1839 {
1840 int netType = msg.arg1;
1841 int condition = msg.arg2;
1842 handleInetConditionChange(netType, condition);
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001843 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001844 }
1845 case EVENT_INET_CONDITION_HOLD_END:
1846 {
1847 int netType = msg.arg1;
1848 int sequence = msg.arg2;
1849 handleInetConditionHoldEnd(netType, sequence);
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001850 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001851 }
1852 case EVENT_SET_NETWORK_PREFERENCE:
1853 {
1854 int preference = msg.arg1;
1855 handleSetNetworkPreference(preference);
1856 break;
1857 }
1858 case EVENT_SET_BACKGROUND_DATA:
1859 {
1860 boolean enabled = (msg.arg1 == ENABLED);
1861 handleSetBackgroundData(enabled);
1862 break;
1863 }
1864 case EVENT_SET_MOBILE_DATA:
1865 {
1866 boolean enabled = (msg.arg1 == ENABLED);
1867 handleSetMobileData(enabled);
1868 break;
1869 }
Robert Greenwalt434203a2010-10-11 16:00:27 -07001870 case EVENT_APPLY_GLOBAL_HTTP_PROXY:
1871 {
1872 handleDeprecatedGlobalHttpProxy();
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001873 break;
1874 }
1875 case EVENT_SET_DEPENDENCY_MET:
1876 {
1877 boolean met = (msg.arg1 == ENABLED);
1878 handleSetDependencyMet(msg.arg2, met);
1879 break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881 }
1882 }
1883 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001884
1885 // javadoc from interface
Robert Greenwalt5a735062010-03-02 17:25:02 -08001886 public int tether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001887 enforceTetherChangePermission();
Robert Greenwalt5a735062010-03-02 17:25:02 -08001888
1889 if (isTetheringSupported()) {
1890 return mTethering.tether(iface);
1891 } else {
1892 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1893 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001894 }
1895
1896 // javadoc from interface
Robert Greenwalt5a735062010-03-02 17:25:02 -08001897 public int untether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001898 enforceTetherChangePermission();
Robert Greenwalt5a735062010-03-02 17:25:02 -08001899
1900 if (isTetheringSupported()) {
1901 return mTethering.untether(iface);
1902 } else {
1903 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1904 }
1905 }
1906
1907 // javadoc from interface
1908 public int getLastTetherError(String iface) {
1909 enforceTetherAccessPermission();
1910
1911 if (isTetheringSupported()) {
1912 return mTethering.getLastTetherError(iface);
1913 } else {
1914 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1915 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001916 }
1917
1918 // TODO - proper iface API for selection by property, inspection, etc
1919 public String[] getTetherableUsbRegexs() {
1920 enforceTetherAccessPermission();
1921 if (isTetheringSupported()) {
1922 return mTethering.getTetherableUsbRegexs();
1923 } else {
1924 return new String[0];
1925 }
1926 }
1927
1928 public String[] getTetherableWifiRegexs() {
1929 enforceTetherAccessPermission();
1930 if (isTetheringSupported()) {
1931 return mTethering.getTetherableWifiRegexs();
1932 } else {
1933 return new String[0];
1934 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001935 }
1936
Danica Chang6fdd0c62010-08-11 14:54:43 -07001937 public String[] getTetherableBluetoothRegexs() {
1938 enforceTetherAccessPermission();
1939 if (isTetheringSupported()) {
1940 return mTethering.getTetherableBluetoothRegexs();
1941 } else {
1942 return new String[0];
1943 }
1944 }
1945
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001946 // TODO - move iface listing, queries, etc to new module
1947 // javadoc from interface
1948 public String[] getTetherableIfaces() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001949 enforceTetherAccessPermission();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001950 return mTethering.getTetherableIfaces();
1951 }
1952
1953 public String[] getTetheredIfaces() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001954 enforceTetherAccessPermission();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001955 return mTethering.getTetheredIfaces();
1956 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001957
Robert Greenwalt5a735062010-03-02 17:25:02 -08001958 public String[] getTetheringErroredIfaces() {
1959 enforceTetherAccessPermission();
1960 return mTethering.getErroredIfaces();
1961 }
1962
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001963 // if ro.tether.denied = true we default to no tethering
1964 // gservices could set the secure setting to 1 though to enable it on a build where it
1965 // had previously been turned off.
1966 public boolean isTetheringSupported() {
1967 enforceTetherAccessPermission();
1968 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001969 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
1970 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
1971 return tetherEnabledInSettings && mTetheringConfigValid;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001972 }
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001973
1974 // An API NetworkStateTrackers can call when they lose their network.
1975 // This will automatically be cleared after X seconds or a network becomes CONNECTED,
1976 // whichever happens first. The timer is started by the first caller and not
1977 // restarted by subsequent callers.
1978 public void requestNetworkTransitionWakelock(String forWhom) {
1979 enforceConnectivityInternalPermission();
1980 synchronized (this) {
1981 if (mNetTransitionWakeLock.isHeld()) return;
1982 mNetTransitionWakeLockSerialNumber++;
1983 mNetTransitionWakeLock.acquire();
1984 mNetTransitionWakeLockCausedBy = forWhom;
1985 }
1986 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltf3331232010-09-24 14:32:21 -07001987 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001988 mNetTransitionWakeLockSerialNumber, 0),
1989 mNetTransitionWakeLockTimeout);
1990 return;
1991 }
Robert Greenwaltca4306c2010-09-09 13:15:32 -07001992
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001993 // 100 percent is full good, 0 is full bad.
1994 public void reportInetCondition(int networkType, int percentage) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001995 if (DBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")");
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001996 mContext.enforceCallingOrSelfPermission(
1997 android.Manifest.permission.STATUS_BAR,
1998 "ConnectivityService");
1999
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -07002000 if (DBG) {
2001 int pid = getCallingPid();
2002 int uid = getCallingUid();
2003 String s = pid + "(" + uid + ") reports inet is " +
2004 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
2005 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
2006 mInetLog.add(s);
2007 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
2008 mInetLog.remove(0);
2009 }
2010 }
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07002011 mHandler.sendMessage(mHandler.obtainMessage(
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002012 EVENT_INET_CONDITION_CHANGE, networkType, percentage));
2013 }
2014
2015 private void handleInetConditionChange(int netType, int condition) {
2016 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002017 log("Inet connectivity change, net=" +
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002018 netType + ", condition=" + condition +
2019 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
2020 }
2021 if (mActiveDefaultNetwork == -1) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002022 if (DBG) log("no active default network - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002023 return;
2024 }
2025 if (mActiveDefaultNetwork != netType) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002026 if (DBG) log("given net not default - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002027 return;
2028 }
2029 mDefaultInetCondition = condition;
2030 int delay;
2031 if (mInetConditionChangeInFlight == false) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002032 if (DBG) log("starting a change hold");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002033 // setup a new hold to debounce this
2034 if (mDefaultInetCondition > 50) {
2035 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2036 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
2037 } else {
2038 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2039 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
2040 }
2041 mInetConditionChangeInFlight = true;
2042 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
2043 mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
2044 } else {
2045 // we've set the new condition, when this hold ends that will get
2046 // picked up
Wink Savilleed9c02b2010-12-03 12:01:38 -08002047 if (DBG) log("currently in hold - not setting new end evt");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002048 }
2049 }
2050
2051 private void handleInetConditionHoldEnd(int netType, int sequence) {
2052 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002053 log("Inet hold end, net=" + netType +
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002054 ", condition =" + mDefaultInetCondition +
2055 ", published condition =" + mDefaultInetConditionPublished);
2056 }
2057 mInetConditionChangeInFlight = false;
2058
2059 if (mActiveDefaultNetwork == -1) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002060 if (DBG) log("no active default network - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002061 return;
2062 }
2063 if (mDefaultConnectionSequence != sequence) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002064 if (DBG) log("event hold for obsolete network - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002065 return;
2066 }
2067 if (mDefaultInetConditionPublished == mDefaultInetCondition) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002068 if (DBG) log("no change in condition - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002069 return;
2070 }
2071 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
2072 if (networkInfo.isConnected() == false) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002073 if (DBG) log("default network not connected - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002074 return;
2075 }
2076 mDefaultInetConditionPublished = mDefaultInetCondition;
2077 sendInetConditionBroadcast(networkInfo);
2078 return;
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07002079 }
Robert Greenwalt434203a2010-10-11 16:00:27 -07002080
2081 public synchronized ProxyProperties getProxy() {
2082 if (mGlobalProxy != null) return mGlobalProxy;
2083 if (mDefaultProxy != null) return mDefaultProxy;
2084 return null;
2085 }
2086
2087 public void setGlobalProxy(ProxyProperties proxyProperties) {
2088 enforceChangePermission();
2089 synchronized (mGlobalProxyLock) {
2090 if (proxyProperties == mGlobalProxy) return;
2091 if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
2092 if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
2093
2094 String host = "";
2095 int port = 0;
2096 String exclList = "";
2097 if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) {
2098 mGlobalProxy = new ProxyProperties(proxyProperties);
2099 host = mGlobalProxy.getHost();
2100 port = mGlobalProxy.getPort();
2101 exclList = mGlobalProxy.getExclusionList();
2102 } else {
2103 mGlobalProxy = null;
2104 }
2105 ContentResolver res = mContext.getContentResolver();
2106 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host);
2107 Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port);
Robert Greenwaltb7090d62010-12-02 11:31:00 -08002108 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
Robert Greenwalt434203a2010-10-11 16:00:27 -07002109 exclList);
2110 }
2111
2112 if (mGlobalProxy == null) {
2113 proxyProperties = mDefaultProxy;
2114 }
2115 sendProxyBroadcast(proxyProperties);
2116 }
2117
Robert Greenwaltb7090d62010-12-02 11:31:00 -08002118 private void loadGlobalProxy() {
2119 ContentResolver res = mContext.getContentResolver();
2120 String host = Settings.Secure.getString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST);
2121 int port = Settings.Secure.getInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, 0);
2122 String exclList = Settings.Secure.getString(res,
2123 Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
2124 if (!TextUtils.isEmpty(host)) {
2125 ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList);
2126 synchronized (mGlobalProxyLock) {
2127 mGlobalProxy = proxyProperties;
2128 }
2129 }
2130 }
2131
Robert Greenwalt434203a2010-10-11 16:00:27 -07002132 public ProxyProperties getGlobalProxy() {
2133 synchronized (mGlobalProxyLock) {
2134 return mGlobalProxy;
2135 }
2136 }
2137
2138 private void handleApplyDefaultProxy(int type) {
2139 // check if new default - push it out to all VM if so
2140 ProxyProperties proxy = mNetTrackers[type].getLinkProperties().getHttpProxy();
2141 synchronized (this) {
2142 if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
2143 if (mDefaultProxy == proxy) return;
2144 if (!TextUtils.isEmpty(proxy.getHost())) {
2145 mDefaultProxy = proxy;
2146 } else {
2147 mDefaultProxy = null;
2148 }
2149 }
Wink Savilleed9c02b2010-12-03 12:01:38 -08002150 if (DBG) log("changing default proxy to " + proxy);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002151 if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return;
2152 if (mGlobalProxy != null) return;
2153 sendProxyBroadcast(proxy);
2154 }
2155
2156 private void handleDeprecatedGlobalHttpProxy() {
2157 String proxy = Settings.Secure.getString(mContext.getContentResolver(),
2158 Settings.Secure.HTTP_PROXY);
2159 if (!TextUtils.isEmpty(proxy)) {
2160 String data[] = proxy.split(":");
2161 String proxyHost = data[0];
2162 int proxyPort = 8080;
2163 if (data.length > 1) {
2164 try {
2165 proxyPort = Integer.parseInt(data[1]);
2166 } catch (NumberFormatException e) {
2167 return;
2168 }
2169 }
2170 ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
2171 setGlobalProxy(p);
2172 }
2173 }
2174
2175 private void sendProxyBroadcast(ProxyProperties proxy) {
Robert Greenwalt55985be2010-12-23 15:51:10 -08002176 if (proxy == null) proxy = new ProxyProperties("", 0, "");
Wink Savilleed9c02b2010-12-03 12:01:38 -08002177 log("sending Proxy Broadcast for " + proxy);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002178 Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
Stan Chesnuttb35d67a2011-01-06 11:00:19 -08002179 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
2180 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002181 intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
Robert Greenwalta2e13392010-12-06 11:29:17 -08002182 mContext.sendStickyBroadcast(intent);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002183 }
2184
2185 private static class SettingsObserver extends ContentObserver {
2186 private int mWhat;
2187 private Handler mHandler;
2188 SettingsObserver(Handler handler, int what) {
2189 super(handler);
2190 mHandler = handler;
2191 mWhat = what;
2192 }
2193
2194 void observe(Context context) {
2195 ContentResolver resolver = context.getContentResolver();
2196 resolver.registerContentObserver(Settings.Secure.getUriFor(
2197 Settings.Secure.HTTP_PROXY), false, this);
2198 }
2199
2200 @Override
2201 public void onChange(boolean selfChange) {
2202 mHandler.obtainMessage(mWhat).sendToTarget();
2203 }
2204 }
Wink Savilleed9c02b2010-12-03 12:01:38 -08002205
2206 private void log(String s) {
2207 Slog.d(TAG, s);
2208 }
2209
2210 private void loge(String s) {
2211 Slog.e(TAG, s);
2212 }
Wink Saville9d7d6282011-03-12 14:52:01 -08002213 int convertFeatureToNetworkType(String feature){
2214 int networkType = -1;
2215 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
2216 networkType = ConnectivityManager.TYPE_MOBILE_MMS;
2217 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
2218 networkType = ConnectivityManager.TYPE_MOBILE_SUPL;
2219 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
2220 TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
2221 networkType = ConnectivityManager.TYPE_MOBILE_DUN;
2222 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
2223 networkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
2224 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
2225 networkType = ConnectivityManager.TYPE_MOBILE_FOTA;
2226 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
2227 networkType = ConnectivityManager.TYPE_MOBILE_IMS;
2228 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
2229 networkType = ConnectivityManager.TYPE_MOBILE_CBS;
2230 }
2231 return networkType;
2232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233}