blob: 6780b03e38f9b276d72a215e36119eaa99c81ff3 [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 Greenwalt7cf5b412011-03-24 21:41:41 -0700539 if (mActiveDefaultNetwork != -1) {
540 return mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800541 }
542 return null;
543 }
544
545 public NetworkInfo getNetworkInfo(int networkType) {
546 enforceAccessPermission();
547 if (ConnectivityManager.isNetworkTypeValid(networkType)) {
548 NetworkStateTracker t = mNetTrackers[networkType];
549 if (t != null)
550 return t.getNetworkInfo();
551 }
552 return null;
553 }
554
555 public NetworkInfo[] getAllNetworkInfo() {
556 enforceAccessPermission();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700557 NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 int i = 0;
559 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700560 if(t != null) result[i++] = t.getNetworkInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 }
562 return result;
563 }
564
Robert Greenwaltd192dad2010-09-14 09:18:02 -0700565 /**
566 * Return LinkProperties for the active (i.e., connected) default
567 * network interface. It is assumed that at most one default network
568 * is active at a time. If more than one is active, it is indeterminate
569 * which will be returned.
570 * @return the ip properties for the active network, or {@code null} if
571 * none is active
572 */
573 public LinkProperties getActiveLinkProperties() {
574 enforceAccessPermission();
575 for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700576 if (mNetConfigs[type] == null || !mNetConfigs[type].isDefault()) {
Robert Greenwaltd192dad2010-09-14 09:18:02 -0700577 continue;
578 }
579 NetworkStateTracker t = mNetTrackers[type];
580 NetworkInfo info = t.getNetworkInfo();
581 if (info.isConnected()) {
582 return t.getLinkProperties();
583 }
584 }
585 return null;
586 }
587
588 public LinkProperties getLinkProperties(int networkType) {
589 enforceAccessPermission();
590 if (ConnectivityManager.isNetworkTypeValid(networkType)) {
591 NetworkStateTracker t = mNetTrackers[networkType];
592 if (t != null) return t.getLinkProperties();
593 }
594 return null;
595 }
596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 public boolean setRadios(boolean turnOn) {
598 boolean result = true;
599 enforceChangePermission();
600 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700601 if (t != null) result = t.setRadio(turnOn) && result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 }
603 return result;
604 }
605
606 public boolean setRadio(int netType, boolean turnOn) {
607 enforceChangePermission();
608 if (!ConnectivityManager.isNetworkTypeValid(netType)) {
609 return false;
610 }
611 NetworkStateTracker tracker = mNetTrackers[netType];
612 return tracker != null && tracker.setRadio(turnOn);
613 }
614
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700615 /**
616 * Used to notice when the calling process dies so we can self-expire
617 *
618 * Also used to know if the process has cleaned up after itself when
619 * our auto-expire timer goes off. The timer has a link to an object.
620 *
621 */
Robert Greenwalt42acef32009-08-12 16:08:25 -0700622 private class FeatureUser implements IBinder.DeathRecipient {
623 int mNetworkType;
624 String mFeature;
625 IBinder mBinder;
626 int mPid;
627 int mUid;
Robert Greenwaltb9285352009-12-21 18:24:07 -0800628 long mCreateTime;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700629
630 FeatureUser(int type, String feature, IBinder binder) {
631 super();
632 mNetworkType = type;
633 mFeature = feature;
634 mBinder = binder;
635 mPid = getCallingPid();
636 mUid = getCallingUid();
Robert Greenwaltb9285352009-12-21 18:24:07 -0800637 mCreateTime = System.currentTimeMillis();
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700638
Robert Greenwalt42acef32009-08-12 16:08:25 -0700639 try {
640 mBinder.linkToDeath(this, 0);
641 } catch (RemoteException e) {
642 binderDied();
643 }
644 }
645
646 void unlinkDeathRecipient() {
647 mBinder.unlinkToDeath(this, 0);
648 }
649
650 public void binderDied() {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800651 log("ConnectivityService FeatureUser binderDied(" +
Robert Greenwaltb9285352009-12-21 18:24:07 -0800652 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
653 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700654 stopUsingNetworkFeature(this, false);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700655 }
656
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700657 public void expire() {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800658 log("ConnectivityService FeatureUser expire(" +
Robert Greenwaltb9285352009-12-21 18:24:07 -0800659 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
660 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700661 stopUsingNetworkFeature(this, false);
662 }
Robert Greenwaltb9285352009-12-21 18:24:07 -0800663
664 public String toString() {
665 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
666 (System.currentTimeMillis() - mCreateTime) + " mSec ago";
667 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700668 }
669
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700670 // javadoc from interface
Robert Greenwalt42acef32009-08-12 16:08:25 -0700671 public int startUsingNetworkFeature(int networkType, String feature,
672 IBinder binder) {
673 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800674 log("startUsingNetworkFeature for net " + networkType + ": " + feature);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 enforceChangePermission();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700677 if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700678 mNetConfigs[networkType] == null) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700679 return Phone.APN_REQUEST_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700681
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700682 FeatureUser f = new FeatureUser(networkType, feature, binder);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700683
684 // TODO - move this into the MobileDataStateTracker
685 int usedNetworkType = networkType;
686 if(networkType == ConnectivityManager.TYPE_MOBILE) {
Wink Saville9d7d6282011-03-12 14:52:01 -0800687 usedNetworkType = convertFeatureToNetworkType(feature);
688 if (usedNetworkType < 0) {
689 Slog.e(TAG, "Can't match any netTracker!");
690 usedNetworkType = networkType;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700691 }
692 }
693 NetworkStateTracker network = mNetTrackers[usedNetworkType];
694 if (network != null) {
Robert Greenwalt0be1e982010-12-15 13:26:33 -0800695 Integer currentPid = new Integer(getCallingPid());
Robert Greenwalt42acef32009-08-12 16:08:25 -0700696 if (usedNetworkType != networkType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700697 NetworkStateTracker radio = mNetTrackers[networkType];
698 NetworkInfo ni = network.getNetworkInfo();
699
700 if (ni.isAvailable() == false) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800701 if (DBG) log("special network not available");
Robert Greenwalte32e8122010-12-29 14:35:21 -0800702 if (!TextUtils.equals(feature,Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
703 return Phone.APN_TYPE_NOT_AVAILABLE;
704 } else {
705 // else make the attempt anyway - probably giving REQUEST_STARTED below
706 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700707 }
708
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700709 synchronized(this) {
710 mFeatureUsers.add(f);
711 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
712 // this gets used for per-pid dns when connected
713 mNetRequestersPids[usedNetworkType].add(currentPid);
714 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700715 }
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700716
Robert Greenwaltf2102f72011-05-03 19:02:44 -0700717 int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
718
719 if (restoreTimer >= 0) {
720 mHandler.sendMessageDelayed(
721 mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer);
722 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700723
Robert Greenwalta64bf832009-08-19 20:19:33 -0700724 if ((ni.isConnectedOrConnecting() == true) &&
725 !network.isTeardownRequested()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700726 if (ni.isConnected() == true) {
727 // add the pid-specific dns
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -0700728 handleDnsConfigurationChange(networkType);
Wink Savilleed9c02b2010-12-03 12:01:38 -0800729 if (DBG) log("special network already active");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700730 return Phone.APN_ALREADY_ACTIVE;
731 }
Wink Savilleed9c02b2010-12-03 12:01:38 -0800732 if (DBG) log("special network already connecting");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700733 return Phone.APN_REQUEST_STARTED;
734 }
735
736 // check if the radio in play can make another contact
737 // assume if cannot for now
738
Wink Savilleed9c02b2010-12-03 12:01:38 -0800739 if (DBG) log("reconnecting to special network");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700740 network.reconnect();
741 return Phone.APN_REQUEST_STARTED;
742 } else {
Robert Greenwalt0be1e982010-12-15 13:26:33 -0800743 // need to remember this unsupported request so we respond appropriately on stop
744 synchronized(this) {
745 mFeatureUsers.add(f);
746 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
747 // this gets used for per-pid dns when connected
748 mNetRequestersPids[usedNetworkType].add(currentPid);
749 }
750 }
Robert Greenwalt02648a42010-05-18 10:52:51 -0700751 return -1;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700752 }
753 }
754 return Phone.APN_TYPE_NOT_AVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 }
756
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700757 // javadoc from interface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 public int stopUsingNetworkFeature(int networkType, String feature) {
Robert Greenwaltb8f16342009-10-06 17:52:40 -0700759 enforceChangePermission();
760
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700761 int pid = getCallingPid();
762 int uid = getCallingUid();
763
764 FeatureUser u = null;
765 boolean found = false;
766
767 synchronized(this) {
768 for (int i = 0; i < mFeatureUsers.size() ; i++) {
769 u = (FeatureUser)mFeatureUsers.get(i);
770 if (uid == u.mUid && pid == u.mPid &&
771 networkType == u.mNetworkType &&
772 TextUtils.equals(feature, u.mFeature)) {
773 found = true;
774 break;
775 }
776 }
777 }
778 if (found && u != null) {
779 // stop regardless of how many other time this proc had called start
780 return stopUsingNetworkFeature(u, true);
781 } else {
782 // none found!
Wink Savilleed9c02b2010-12-03 12:01:38 -0800783 if (DBG) log("ignoring stopUsingNetworkFeature - not a live request");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700784 return 1;
785 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700786 }
787
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700788 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
789 int networkType = u.mNetworkType;
790 String feature = u.mFeature;
791 int pid = u.mPid;
792 int uid = u.mUid;
793
794 NetworkStateTracker tracker = null;
795 boolean callTeardown = false; // used to carry our decision outside of sync block
796
Robert Greenwalt42acef32009-08-12 16:08:25 -0700797 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800798 log("stopUsingNetworkFeature for net " + networkType +
Robert Greenwalt42acef32009-08-12 16:08:25 -0700799 ": " + feature);
800 }
Robert Greenwaltb8f16342009-10-06 17:52:40 -0700801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
803 return -1;
804 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700805
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700806 // need to link the mFeatureUsers list with the mNetRequestersPids state in this
807 // sync block
808 synchronized(this) {
809 // check if this process still has an outstanding start request
810 if (!mFeatureUsers.contains(u)) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800811 if (DBG) log("ignoring - this process has no outstanding requests");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700812 return 1;
813 }
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700814 u.unlinkDeathRecipient();
815 mFeatureUsers.remove(mFeatureUsers.indexOf(u));
816 // If we care about duplicate requests, check for that here.
817 //
818 // This is done to support the extension of a request - the app
819 // can request we start the network feature again and renew the
820 // auto-shutoff delay. Normal "stop" calls from the app though
821 // do not pay attention to duplicate requests - in effect the
822 // API does not refcount and a single stop will counter multiple starts.
823 if (ignoreDups == false) {
824 for (int i = 0; i < mFeatureUsers.size() ; i++) {
825 FeatureUser x = (FeatureUser)mFeatureUsers.get(i);
826 if (x.mUid == u.mUid && x.mPid == u.mPid &&
827 x.mNetworkType == u.mNetworkType &&
828 TextUtils.equals(x.mFeature, u.mFeature)) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800829 if (DBG) log("ignoring stopUsingNetworkFeature as dup is found");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700830 return 1;
831 }
832 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700833 }
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700834
835 // TODO - move to MobileDataStateTracker
836 int usedNetworkType = networkType;
837 if (networkType == ConnectivityManager.TYPE_MOBILE) {
Wink Saville9d7d6282011-03-12 14:52:01 -0800838 usedNetworkType = convertFeatureToNetworkType(feature);
839 if (usedNetworkType < 0) {
840 usedNetworkType = networkType;
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700841 }
842 }
843 tracker = mNetTrackers[usedNetworkType];
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700844 if (tracker == null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800845 if (DBG) log("ignoring - no known tracker for net type " + usedNetworkType);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700846 return -1;
847 }
848 if (usedNetworkType != networkType) {
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700849 Integer currentPid = new Integer(pid);
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700850 mNetRequestersPids[usedNetworkType].remove(currentPid);
Robert Greenwalt421c72b2009-12-17 14:54:59 -0800851 reassessPidDns(pid, true);
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700852 if (mNetRequestersPids[usedNetworkType].size() != 0) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800853 if (DBG) log("not tearing down special network - " +
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700854 "others still using it");
855 return 1;
856 }
857 callTeardown = true;
Robert Greenwalt19b9ab42011-01-10 11:58:31 -0800858 } else {
859 if (DBG) log("not a known feature - dropping");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700860 }
861 }
Wink Savilleed9c02b2010-12-03 12:01:38 -0800862 if (DBG) log("Doing network teardown");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700863 if (callTeardown) {
864 tracker.teardown();
Robert Greenwalt42acef32009-08-12 16:08:25 -0700865 return 1;
866 } else {
Robert Greenwalt02648a42010-05-18 10:52:51 -0700867 return -1;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 }
870
871 /**
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700872 * @deprecated use requestRouteToHostAddress instead
873 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 * Ensure that a network route exists to deliver traffic to the specified
875 * host via the specified network interface.
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700876 * @param networkType the type of the network over which traffic to the
877 * specified host is to be routed
878 * @param hostAddress the IP address of the host to which the route is
879 * desired
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 * @return {@code true} on success, {@code false} on failure
881 */
882 public boolean requestRouteToHost(int networkType, int hostAddress) {
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700883 InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
884
885 if (inetAddress == null) {
886 return false;
887 }
888
889 return requestRouteToHostAddress(networkType, inetAddress.getAddress());
890 }
891
892 /**
893 * Ensure that a network route exists to deliver traffic to the specified
894 * host via the specified network interface.
895 * @param networkType the type of the network over which traffic to the
896 * specified host is to be routed
897 * @param hostAddress the IP address of the host to which the route is
898 * desired
899 * @return {@code true} on success, {@code false} on failure
900 */
901 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 enforceChangePermission();
903 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
904 return false;
905 }
906 NetworkStateTracker tracker = mNetTrackers[networkType];
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700907
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700908 if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
909 tracker.isTeardownRequested()) {
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700910 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800911 log("requestRouteToHostAddress on down network " +
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700912 "(" + networkType + ") - dropped");
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700913 }
914 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 }
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700916 try {
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700917 InetAddress addr = InetAddress.getByAddress(hostAddress);
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700918 return addHostRoute(tracker, addr, 0);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700919 } catch (UnknownHostException e) {}
920 return false;
Irfan Sheriffd649c122010-06-09 15:39:36 -0700921 }
922
923 /**
924 * Ensure that a network route exists to deliver traffic to the specified
925 * host via the mobile data network.
926 * @param hostAddress the IP address of the host to which the route is desired,
927 * in network byte order.
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700928 * TODO - deprecate
Irfan Sheriffd649c122010-06-09 15:39:36 -0700929 * @return {@code true} on success, {@code false} on failure
930 */
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700931 private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress, int cycleCount) {
Irfan Sheriffd649c122010-06-09 15:39:36 -0700932 if (nt.getNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI) {
933 return false;
934 }
935
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700936 LinkProperties lp = nt.getLinkProperties();
937 if ((lp == null) || (hostAddress == null)) return false;
Irfan Sheriffd649c122010-06-09 15:39:36 -0700938
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700939 String interfaceName = lp.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -0700940 if (DBG) {
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700941 log("Requested host route to " + hostAddress + "(" + interfaceName + "), cycleCount=" +
942 cycleCount);
Irfan Sheriffd649c122010-06-09 15:39:36 -0700943 }
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700944 if (interfaceName == null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800945 if (DBG) loge("addHostRoute failed due to null interface name");
Irfan Sheriffd649c122010-06-09 15:39:36 -0700946 return false;
947 }
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700948
949 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), hostAddress);
950 InetAddress gateway = null;
951 if (bestRoute != null) {
952 gateway = bestRoute.getGateway();
953 // if the best route is ourself, don't relf-reference, just add the host route
954 if (hostAddress.equals(gateway)) gateway = null;
955 }
956 if (gateway != null) {
957 if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
958 loge("Error adding hostroute - too much recursion");
959 return false;
960 }
961 if (!addHostRoute(nt, gateway, cycleCount+1)) return false;
962 }
963 return NetworkUtils.addHostRoute(interfaceName, hostAddress, gateway);
964 }
965
966 // TODO support the removal of single host routes. Keep a ref count of them so we
967 // aren't over-zealous
968 private boolean removeHostRoute(NetworkStateTracker nt, InetAddress hostAddress) {
969 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 }
971
972 /**
973 * @see ConnectivityManager#getBackgroundDataSetting()
974 */
975 public boolean getBackgroundDataSetting() {
Robert Greenwaltd825ea42010-12-29 16:15:02 -0800976 return mBackgroundDataEnabled.get();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 /**
980 * @see ConnectivityManager#setBackgroundDataSetting(boolean)
981 */
982 public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) {
983 mContext.enforceCallingOrSelfPermission(
984 android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
985 "ConnectivityService");
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700986
Robert Greenwaltd825ea42010-12-29 16:15:02 -0800987 mBackgroundDataEnabled.set(allowBackgroundDataUsage);
988
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700989 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA,
990 (allowBackgroundDataUsage ? ENABLED : DISABLED), 0));
991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700993 private void handleSetBackgroundData(boolean enabled) {
Robert Greenwaltdb4afae2011-02-25 13:44:09 -0800994 Settings.Secure.putInt(mContext.getContentResolver(),
995 Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0);
996 Intent broadcast = new Intent(
997 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
998 mContext.sendBroadcast(broadcast);
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700999 }
1000
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001001 /**
1002 * @see ConnectivityManager#getMobileDataEnabled()
1003 */
1004 public boolean getMobileDataEnabled() {
Wink Savillee7982682010-12-07 10:31:02 -08001005 // TODO: This detail should probably be in DataConnectionTracker's
1006 // which is where we store the value and maybe make this
1007 // asynchronous.
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001008 enforceAccessPermission();
1009 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
1010 Settings.Secure.MOBILE_DATA, 1) == 1;
Wink Savilleed9c02b2010-12-03 12:01:38 -08001011 if (DBG) log("getMobileDataEnabled returning " + retVal);
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001012 return retVal;
1013 }
1014
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001015 public void setDataDependency(int networkType, boolean met) {
1016 enforceChangePermission();
1017 if (DBG) {
1018 log("setDataDependency(" + networkType + ", " + met + ")");
1019 }
1020 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
1021 (met ? ENABLED : DISABLED), networkType));
1022 }
1023
1024 private void handleSetDependencyMet(int networkType, boolean met) {
1025 if (mNetTrackers[networkType] != null) {
1026 if (DBG) {
1027 log("handleSetDependencyMet(" + networkType + ", " + met + ")");
1028 }
1029 mNetTrackers[networkType].setDependencyMet(met);
1030 }
1031 }
1032
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001033 /**
1034 * @see ConnectivityManager#setMobileDataEnabled(boolean)
1035 */
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001036 public void setMobileDataEnabled(boolean enabled) {
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001037 enforceChangePermission();
Wink Savilleed9c02b2010-12-03 12:01:38 -08001038 if (DBG) log("setMobileDataEnabled(" + enabled + ")");
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001039
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001040 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001041 (enabled ? ENABLED : DISABLED), 0));
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001042 }
1043
1044 private void handleSetMobileData(boolean enabled) {
Wink Savillee7982682010-12-07 10:31:02 -08001045 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
1046 if (DBG) {
1047 Slog.d(TAG, mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001048 }
Wink Savillee7982682010-12-07 10:31:02 -08001049 mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled);
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001050 }
1051 }
1052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 private void enforceAccessPermission() {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001054 mContext.enforceCallingOrSelfPermission(
1055 android.Manifest.permission.ACCESS_NETWORK_STATE,
1056 "ConnectivityService");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 }
1058
1059 private void enforceChangePermission() {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001060 mContext.enforceCallingOrSelfPermission(
1061 android.Manifest.permission.CHANGE_NETWORK_STATE,
1062 "ConnectivityService");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 }
1064
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001065 // TODO Make this a special check when it goes public
1066 private void enforceTetherChangePermission() {
1067 mContext.enforceCallingOrSelfPermission(
1068 android.Manifest.permission.CHANGE_NETWORK_STATE,
1069 "ConnectivityService");
1070 }
1071
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001072 private void enforceTetherAccessPermission() {
1073 mContext.enforceCallingOrSelfPermission(
1074 android.Manifest.permission.ACCESS_NETWORK_STATE,
1075 "ConnectivityService");
1076 }
1077
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001078 private void enforceConnectivityInternalPermission() {
1079 mContext.enforceCallingOrSelfPermission(
1080 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1081 "ConnectivityService");
1082 }
1083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 /**
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001085 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
1086 * network, we ignore it. If it is for the active network, we send out a
1087 * broadcast. But first, we check whether it might be possible to connect
1088 * to a different network.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 * @param info the {@code NetworkInfo} for the network
1090 */
1091 private void handleDisconnect(NetworkInfo info) {
1092
Robert Greenwalt42acef32009-08-12 16:08:25 -07001093 int prevNetType = info.getType();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094
Robert Greenwalt42acef32009-08-12 16:08:25 -07001095 mNetTrackers[prevNetType].setTeardownRequested(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 /*
1097 * If the disconnected network is not the active one, then don't report
1098 * this as a loss of connectivity. What probably happened is that we're
1099 * getting the disconnect for a network that we explicitly disabled
1100 * in accordance with network preference policies.
1101 */
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001102 if (!mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001103 List pids = mNetRequestersPids[prevNetType];
1104 for (int i = 0; i<pids.size(); i++) {
1105 Integer pid = (Integer)pids.get(i);
1106 // will remove them because the net's no longer connected
1107 // need to do this now as only now do we know the pids and
1108 // can properly null things that are no longer referenced.
1109 reassessPidDns(pid.intValue(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 }
1112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1114 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1115 if (info.isFailover()) {
1116 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1117 info.setFailover(false);
1118 }
1119 if (info.getReason() != null) {
1120 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1121 }
1122 if (info.getExtraInfo() != null) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001123 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1124 info.getExtraInfo());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001126
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001127 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001128 tryFailover(prevNetType);
1129 if (mActiveDefaultNetwork != -1) {
1130 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001131 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1132 } else {
Robert Greenwalt029be812010-09-20 18:01:43 -07001133 mDefaultInetConditionPublished = 0; // we're not connected anymore
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001134 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1135 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001136 }
Robert Greenwalt029be812010-09-20 18:01:43 -07001137 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001138 // do this before we broadcast the change
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001139 handleConnectivityChange(prevNetType);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001140
1141 sendStickyBroadcast(intent);
1142 /*
1143 * If the failover network is already connected, then immediately send
1144 * out a followup broadcast indicating successful failover
1145 */
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001146 if (mActiveDefaultNetwork != -1) {
1147 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001148 }
1149 }
1150
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001151 private void tryFailover(int prevNetType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001152 /*
Robert Greenwaltbff90182011-01-06 15:41:07 -08001153 * If this is a default network, check if other defaults are available.
1154 * Try to reconnect on all available and let them hash it out when
1155 * more than one connects.
Robert Greenwalt42acef32009-08-12 16:08:25 -07001156 */
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001157 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001158 if (mActiveDefaultNetwork == prevNetType) {
1159 mActiveDefaultNetwork = -1;
1160 }
1161
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001162 // don't signal a reconnect for anything lower or equal priority than our
1163 // current connected default
1164 // TODO - don't filter by priority now - nice optimization but risky
1165// int currentPriority = -1;
1166// if (mActiveDefaultNetwork != -1) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001167// currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority;
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001168// }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001169 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -07001170 if (checkType == prevNetType) continue;
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001171 if (mNetConfigs[checkType] == null) continue;
1172 if (!mNetConfigs[checkType].isDefault()) continue;
Wink Saville9f7a0b22011-01-26 15:43:49 -08001173
1174// Enabling the isAvailable() optimization caused mobile to not get
1175// selected if it was in the middle of error handling. Specifically
1176// a moble connection that took 30 seconds to complete the DEACTIVATE_DATA_CALL
1177// would not be available and we wouldn't get connected to anything.
1178// So removing the isAvailable() optimization below for now. TODO: This
1179// optimization should work and we need to investigate why it doesn't work.
1180// This could be related to how DEACTIVATE_DATA_CALL is reporting its
1181// complete before it is really complete.
1182// if (!mNetTrackers[checkType].isAvailable()) continue;
1183
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001184// if (currentPriority >= mNetConfigs[checkType].mPriority) continue;
Robert Greenwalt42acef32009-08-12 16:08:25 -07001185
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001186 NetworkStateTracker checkTracker = mNetTrackers[checkType];
1187 NetworkInfo checkInfo = checkTracker.getNetworkInfo();
1188 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
1189 checkInfo.setFailover(true);
1190 checkTracker.reconnect();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001191 }
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001192 if (DBG) log("Attempting to switch to " + checkInfo.getTypeName());
Robert Greenwalt42acef32009-08-12 16:08:25 -07001193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195 }
1196
1197 private void sendConnectedBroadcast(NetworkInfo info) {
Robert Greenwalt1e9aac22010-09-15 17:36:33 -07001198 sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION);
1199 }
1200
1201 private void sendInetConditionBroadcast(NetworkInfo info) {
1202 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1203 }
1204
1205 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1206 Intent intent = new Intent(bcastType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1208 if (info.isFailover()) {
1209 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1210 info.setFailover(false);
1211 }
1212 if (info.getReason() != null) {
1213 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1214 }
1215 if (info.getExtraInfo() != null) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001216 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1217 info.getExtraInfo());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 }
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001219 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001220 sendStickyBroadcast(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 }
1222
1223 /**
1224 * Called when an attempt to fail over to another network has failed.
1225 * @param info the {@link NetworkInfo} for the failed network
1226 */
1227 private void handleConnectionFailure(NetworkInfo info) {
1228 mNetTrackers[info.getType()].setTeardownRequested(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229
Robert Greenwalt42acef32009-08-12 16:08:25 -07001230 String reason = info.getReason();
1231 String extraInfo = info.getExtraInfo();
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001232
Robert Greenwalt572172b2010-10-08 16:35:52 -07001233 String reasonText;
1234 if (reason == null) {
1235 reasonText = ".";
1236 } else {
1237 reasonText = " (" + reason + ").";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 }
Wink Savilleed9c02b2010-12-03 12:01:38 -08001239 loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001240
1241 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1242 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1243 if (getActiveNetworkInfo() == null) {
1244 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1245 }
1246 if (reason != null) {
1247 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
1248 }
1249 if (extraInfo != null) {
1250 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
1251 }
1252 if (info.isFailover()) {
1253 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1254 info.setFailover(false);
1255 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001256
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001257 if (mNetConfigs[info.getType()].isDefault()) {
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001258 tryFailover(info.getType());
1259 if (mActiveDefaultNetwork != -1) {
1260 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001261 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1262 } else {
Robert Greenwalt029be812010-09-20 18:01:43 -07001263 mDefaultInetConditionPublished = 0;
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001264 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1265 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001266 }
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001267
Robert Greenwalt029be812010-09-20 18:01:43 -07001268 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001269 sendStickyBroadcast(intent);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001270 /*
1271 * If the failover network is already connected, then immediately send
1272 * out a followup broadcast indicating successful failover
1273 */
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001274 if (mActiveDefaultNetwork != -1) {
1275 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001276 }
Mike Lockwood0f79b542009-08-14 14:18:49 -04001277 }
1278
1279 private void sendStickyBroadcast(Intent intent) {
1280 synchronized(this) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001281 if (!mSystemReady) {
1282 mInitialBroadcast = new Intent(intent);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001283 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001284 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1285 mContext.sendStickyBroadcast(intent);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001286 }
1287 }
1288
1289 void systemReady() {
1290 synchronized(this) {
1291 mSystemReady = true;
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001292 if (mInitialBroadcast != null) {
1293 mContext.sendStickyBroadcast(mInitialBroadcast);
1294 mInitialBroadcast = null;
Mike Lockwood0f79b542009-08-14 14:18:49 -04001295 }
1296 }
Robert Greenwalt434203a2010-10-11 16:00:27 -07001297 // load the global proxy at startup
1298 mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 }
1300
1301 private void handleConnect(NetworkInfo info) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001302 int type = info.getType();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303
1304 // snapshot isFailover, because sendConnectedBroadcast() resets it
1305 boolean isFailover = info.isFailover();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001306 NetworkStateTracker thisNet = mNetTrackers[type];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001307
Robert Greenwalt42acef32009-08-12 16:08:25 -07001308 // if this is a default net and other default is running
1309 // kill the one not preferred
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001310 if (mNetConfigs[type].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001311 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
1312 if ((type != mNetworkPreference &&
Wink Saville975c8482011-04-07 14:23:45 -07001313 mNetConfigs[mActiveDefaultNetwork].priority >
1314 mNetConfigs[type].priority) ||
Robert Greenwalt42acef32009-08-12 16:08:25 -07001315 mNetworkPreference == mActiveDefaultNetwork) {
1316 // don't accept this one
Wink Savilleed9c02b2010-12-03 12:01:38 -08001317 if (DBG) {
1318 log("Not broadcasting CONNECT_ACTION " +
Robert Greenwalt42acef32009-08-12 16:08:25 -07001319 "to torn down network " + info.getTypeName());
Wink Savilleed9c02b2010-12-03 12:01:38 -08001320 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001321 teardown(thisNet);
1322 return;
1323 } else {
1324 // tear down the other
1325 NetworkStateTracker otherNet =
1326 mNetTrackers[mActiveDefaultNetwork];
Wink Savilleed9c02b2010-12-03 12:01:38 -08001327 if (DBG) {
1328 log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
Robert Greenwalt42acef32009-08-12 16:08:25 -07001329 " teardown");
Wink Savilleed9c02b2010-12-03 12:01:38 -08001330 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001331 if (!teardown(otherNet)) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001332 loge("Network declined teardown request");
Robert Greenwalt27725e82011-03-29 11:36:28 -07001333 teardown(thisNet);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001334 return;
1335 }
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001336 }
1337 }
1338 synchronized (ConnectivityService.this) {
1339 // have a new default network, release the transition wakelock in a second
1340 // if it's held. The second pause is to allow apps to reconnect over the
1341 // new network
1342 if (mNetTransitionWakeLock.isHeld()) {
1343 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltf3331232010-09-24 14:32:21 -07001344 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001345 mNetTransitionWakeLockSerialNumber, 0),
1346 1000);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001347 }
1348 }
1349 mActiveDefaultNetwork = type;
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001350 // this will cause us to come up initially as unconnected and switching
1351 // to connected after our normal pause unless somebody reports us as reall
1352 // disconnected
1353 mDefaultInetConditionPublished = 0;
1354 mDefaultConnectionSequence++;
1355 mInetConditionChangeInFlight = false;
1356 // Don't do this - if we never sign in stay, grey
1357 //reportNetworkCondition(mActiveDefaultNetwork, 100);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001359 thisNet.setTeardownRequested(false);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001360 updateNetworkSettings(thisNet);
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001361 handleConnectivityChange(type);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001362 sendConnectedBroadcast(info);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 }
1364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 /**
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001366 * After a change in the connectivity state of a network. We're mainly
1367 * concerned with making sure that the list of DNS servers is set up
1368 * according to which networks are connected, and ensuring that the
1369 * right routing table entries exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370 */
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001371 private void handleConnectivityChange(int netType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 /*
Robert Greenwalt42acef32009-08-12 16:08:25 -07001373 * If a non-default network is enabled, add the host routes that
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001374 * will allow it's DNS servers to be accessed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 */
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001376 handleDnsConfigurationChange(netType);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001377
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001378 if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001379 if (mNetConfigs[netType].isDefault()) {
Robert Greenwalt434203a2010-10-11 16:00:27 -07001380 handleApplyDefaultProxy(netType);
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001381 addDefaultRoute(mNetTrackers[netType]);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001382 } else {
Robert Greenwalt7cf5b412011-03-24 21:41:41 -07001383 // many radios add a default route even when we don't want one.
1384 // remove the default interface unless we need it for our active network
1385 if (mActiveDefaultNetwork != -1) {
Robert Greenwalt6244f0fc2011-03-30 15:03:13 -07001386 LinkProperties linkProperties =
1387 mNetTrackers[mActiveDefaultNetwork].getLinkProperties();
1388 LinkProperties newLinkProperties =
1389 mNetTrackers[netType].getLinkProperties();
1390 String defaultIface = linkProperties.getInterfaceName();
Robert Greenwalt7cf5b412011-03-24 21:41:41 -07001391 if (defaultIface != null &&
Robert Greenwalt6244f0fc2011-03-30 15:03:13 -07001392 !defaultIface.equals(newLinkProperties.getInterfaceName())) {
Robert Greenwaltb1c6b0f2011-03-31 10:44:47 -07001393 removeDefaultRoute(mNetTrackers[netType]);
Robert Greenwalt7cf5b412011-03-24 21:41:41 -07001394 }
1395 }
Robert Greenwaltb1c6b0f2011-03-31 10:44:47 -07001396 addPrivateDnsRoutes(mNetTrackers[netType]);
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001397 }
1398 } else {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001399 if (mNetConfigs[netType].isDefault()) {
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001400 removeDefaultRoute(mNetTrackers[netType]);
1401 } else {
1402 removePrivateDnsRoutes(mNetTrackers[netType]);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 }
1405 }
1406
Irfan Sheriffd649c122010-06-09 15:39:36 -07001407 private void addPrivateDnsRoutes(NetworkStateTracker nt) {
Irfan Sheriffd649c122010-06-09 15:39:36 -07001408 boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet();
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001409 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001410 if (p == null) return;
1411 String interfaceName = p.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -07001412
1413 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001414 log("addPrivateDnsRoutes for " + nt +
Irfan Sheriffd649c122010-06-09 15:39:36 -07001415 "(" + interfaceName + ") - mPrivateDnsRouteSet = " + privateDnsRouteSet);
1416 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001417 if (interfaceName != null && !privateDnsRouteSet) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001418 Collection<InetAddress> dnsList = p.getDnses();
1419 for (InetAddress dns : dnsList) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001420 if (DBG) log(" adding " + dns);
Robert Greenwaltf43396c2011-05-06 17:10:53 -07001421 addHostRoute(nt, dns, 0);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001422 }
1423 nt.privateDnsRouteSet(true);
1424 }
1425 }
1426
1427 private void removePrivateDnsRoutes(NetworkStateTracker nt) {
1428 // TODO - we should do this explicitly but the NetUtils api doesnt
1429 // support this yet - must remove all. No worse than before
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001430 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001431 if (p == null) return;
1432 String interfaceName = p.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -07001433 boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet();
1434 if (interfaceName != null && privateDnsRouteSet) {
1435 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001436 log("removePrivateDnsRoutes for " + nt.getNetworkInfo().getTypeName() +
Irfan Sheriffd649c122010-06-09 15:39:36 -07001437 " (" + interfaceName + ")");
1438 }
1439 NetworkUtils.removeHostRoutes(interfaceName);
1440 nt.privateDnsRouteSet(false);
1441 }
1442 }
1443
Irfan Sheriffd649c122010-06-09 15:39:36 -07001444
1445 private void addDefaultRoute(NetworkStateTracker nt) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001446 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001447 if (p == null) return;
1448 String interfaceName = p.getInterfaceName();
Robert Greenwalt992564e2011-02-09 13:56:06 -08001449 if (TextUtils.isEmpty(interfaceName)) return;
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001450 for (RouteInfo route : p.getRoutes()) {
Irfan Sheriffd649c122010-06-09 15:39:36 -07001451
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001452 //TODO - handle non-default routes
1453 if (route.isDefaultRoute()) {
1454 InetAddress gateway = route.getGateway();
Robert Greenwaltf43396c2011-05-06 17:10:53 -07001455 if (addHostRoute(nt, gateway, 0) &&
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001456 NetworkUtils.addDefaultRoute(interfaceName, gateway)) {
1457 if (DBG) {
1458 NetworkInfo networkInfo = nt.getNetworkInfo();
1459 log("addDefaultRoute for " + networkInfo.getTypeName() +
1460 " (" + interfaceName + "), GatewayAddr=" +
1461 gateway.getHostAddress());
1462 }
Robert Greenwaltedcb4f92011-03-22 18:47:42 -07001463 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001464 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001465 }
1466 }
1467
1468
1469 public void removeDefaultRoute(NetworkStateTracker nt) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001470 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001471 if (p == null) return;
1472 String interfaceName = p.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -07001473
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001474 if (interfaceName != null) {
Robert Greenwaltedcb4f92011-03-22 18:47:42 -07001475 if (NetworkUtils.removeDefaultRoute(interfaceName) >= 0) {
1476 if (DBG) {
1477 NetworkInfo networkInfo = nt.getNetworkInfo();
1478 log("removeDefaultRoute for " + networkInfo.getTypeName() + " (" +
1479 interfaceName + ")");
1480 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001481 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001482 }
1483 }
1484
1485 /**
1486 * Reads the network specific TCP buffer sizes from SystemProperties
1487 * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
1488 * wide use
1489 */
1490 public void updateNetworkSettings(NetworkStateTracker nt) {
1491 String key = nt.getTcpBufferSizesPropName();
1492 String bufferSizes = SystemProperties.get(key);
1493
1494 if (bufferSizes.length() == 0) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001495 loge(key + " not found in system properties. Using defaults");
Irfan Sheriffd649c122010-06-09 15:39:36 -07001496
1497 // Setting to default values so we won't be stuck to previous values
1498 key = "net.tcp.buffersize.default";
1499 bufferSizes = SystemProperties.get(key);
1500 }
1501
1502 // Set values in kernel
1503 if (bufferSizes.length() != 0) {
1504 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001505 log("Setting TCP values: [" + bufferSizes
Irfan Sheriffd649c122010-06-09 15:39:36 -07001506 + "] which comes from [" + key + "]");
1507 }
1508 setBufferSize(bufferSizes);
1509 }
1510 }
1511
1512 /**
1513 * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max]
1514 * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem
1515 *
1516 * @param bufferSizes in the format of "readMin, readInitial, readMax,
1517 * writeMin, writeInitial, writeMax"
1518 */
1519 private void setBufferSize(String bufferSizes) {
1520 try {
1521 String[] values = bufferSizes.split(",");
1522
1523 if (values.length == 6) {
1524 final String prefix = "/sys/kernel/ipv4/tcp_";
1525 stringToFile(prefix + "rmem_min", values[0]);
1526 stringToFile(prefix + "rmem_def", values[1]);
1527 stringToFile(prefix + "rmem_max", values[2]);
1528 stringToFile(prefix + "wmem_min", values[3]);
1529 stringToFile(prefix + "wmem_def", values[4]);
1530 stringToFile(prefix + "wmem_max", values[5]);
1531 } else {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001532 loge("Invalid buffersize string: " + bufferSizes);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001533 }
1534 } catch (IOException e) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001535 loge("Can't set tcp buffer sizes:" + e);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001536 }
1537 }
1538
1539 /**
1540 * Writes string to file. Basically same as "echo -n $string > $filename"
1541 *
1542 * @param filename
1543 * @param string
1544 * @throws IOException
1545 */
1546 private void stringToFile(String filename, String string) throws IOException {
1547 FileWriter out = new FileWriter(filename);
1548 try {
1549 out.write(string);
1550 } finally {
1551 out.close();
1552 }
1553 }
1554
1555
Robert Greenwalt42acef32009-08-12 16:08:25 -07001556 /**
1557 * Adjust the per-process dns entries (net.dns<x>.<pid>) based
1558 * on the highest priority active net which this process requested.
1559 * If there aren't any, clear it out
1560 */
1561 private void reassessPidDns(int myPid, boolean doBump)
1562 {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001563 if (DBG) log("reassessPidDns for pid " + myPid);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001564 for(int i : mPriorityList) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001565 if (mNetConfigs[i].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001566 continue;
1567 }
1568 NetworkStateTracker nt = mNetTrackers[i];
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001569 if (nt.getNetworkInfo().isConnected() &&
1570 !nt.isTeardownRequested()) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001571 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001572 if (p == null) continue;
Robert Greenwalt42acef32009-08-12 16:08:25 -07001573 List pids = mNetRequestersPids[i];
1574 for (int j=0; j<pids.size(); j++) {
1575 Integer pid = (Integer)pids.get(j);
1576 if (pid.intValue() == myPid) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001577 Collection<InetAddress> dnses = p.getDnses();
1578 writePidDns(dnses, myPid);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001579 if (doBump) {
1580 bumpDns();
1581 }
1582 return;
1583 }
1584 }
1585 }
1586 }
1587 // nothing found - delete
1588 for (int i = 1; ; i++) {
1589 String prop = "net.dns" + i + "." + myPid;
1590 if (SystemProperties.get(prop).length() == 0) {
1591 if (doBump) {
1592 bumpDns();
1593 }
1594 return;
1595 }
1596 SystemProperties.set(prop, "");
1597 }
1598 }
1599
Robert Greenwalt10398722010-12-17 15:20:36 -08001600 // return true if results in a change
1601 private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001602 int j = 1;
Robert Greenwalt10398722010-12-17 15:20:36 -08001603 boolean changed = false;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001604 for (InetAddress dns : dnses) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001605 String dnsString = dns.getHostAddress();
1606 if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
1607 changed = true;
1608 SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
1609 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001610 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001611 return changed;
Robert Greenwalt42acef32009-08-12 16:08:25 -07001612 }
1613
1614 private void bumpDns() {
1615 /*
1616 * Bump the property that tells the name resolver library to reread
1617 * the DNS server list from the properties.
1618 */
1619 String propVal = SystemProperties.get("net.dnschange");
1620 int n = 0;
1621 if (propVal.length() != 0) {
1622 try {
1623 n = Integer.parseInt(propVal);
1624 } catch (NumberFormatException e) {}
1625 }
1626 SystemProperties.set("net.dnschange", "" + (n+1));
Robert Greenwalt03595d02010-11-02 14:08:23 -07001627 /*
1628 * Tell the VMs to toss their DNS caches
1629 */
1630 Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
1631 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Stan Chesnutt3d1db862011-01-05 17:14:03 -08001632 /*
1633 * Connectivity events can happen before boot has completed ...
1634 */
1635 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt03595d02010-11-02 14:08:23 -07001636 mContext.sendBroadcast(intent);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001637 }
1638
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001639 private void handleDnsConfigurationChange(int netType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001640 // add default net's dns entries
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001641 NetworkStateTracker nt = mNetTrackers[netType];
1642 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001643 LinkProperties p = nt.getLinkProperties();
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001644 if (p == null) return;
1645 Collection<InetAddress> dnses = p.getDnses();
Robert Greenwalt10398722010-12-17 15:20:36 -08001646 boolean changed = false;
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001647 if (mNetConfigs[netType].isDefault()) {
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001648 int j = 1;
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001649 if (dnses.size() == 0 && mDefaultDns != null) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001650 String dnsString = mDefaultDns.getHostAddress();
1651 if (!dnsString.equals(SystemProperties.get("net.dns1"))) {
1652 if (DBG) {
1653 log("no dns provided - using " + dnsString);
1654 }
1655 changed = true;
1656 SystemProperties.set("net.dns1", dnsString);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001657 }
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001658 j++;
1659 } else {
1660 for (InetAddress dns : dnses) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001661 String dnsString = dns.getHostAddress();
1662 if (!changed && dnsString.equals(SystemProperties.get("net.dns" + j))) {
1663 j++;
1664 continue;
1665 }
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001666 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001667 log("adding dns " + dns + " for " +
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001668 nt.getNetworkInfo().getTypeName());
1669 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001670 changed = true;
1671 SystemProperties.set("net.dns" + j++, dnsString);
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001672 }
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001673 }
1674 for (int k=j ; k<mNumDnsEntries; k++) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001675 if (changed || !TextUtils.isEmpty(SystemProperties.get("net.dns" + k))) {
1676 if (DBG) log("erasing net.dns" + k);
1677 changed = true;
1678 SystemProperties.set("net.dns" + k, "");
1679 }
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001680 }
1681 mNumDnsEntries = j;
1682 } else {
1683 // set per-pid dns for attached secondary nets
1684 List pids = mNetRequestersPids[netType];
1685 for (int y=0; y< pids.size(); y++) {
1686 Integer pid = (Integer)pids.get(y);
Robert Greenwalt10398722010-12-17 15:20:36 -08001687 changed = writePidDns(dnses, pid.intValue());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 }
1689 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001690 if (changed) bumpDns();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001692 }
1693
Robert Greenwaltf2102f72011-05-03 19:02:44 -07001694 private int getRestoreDefaultNetworkDelay(int networkType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001695 String restoreDefaultNetworkDelayStr = SystemProperties.get(
1696 NETWORK_RESTORE_DELAY_PROP_NAME);
1697 if(restoreDefaultNetworkDelayStr != null &&
1698 restoreDefaultNetworkDelayStr.length() != 0) {
1699 try {
1700 return Integer.valueOf(restoreDefaultNetworkDelayStr);
1701 } catch (NumberFormatException e) {
1702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001703 }
Robert Greenwaltf2102f72011-05-03 19:02:44 -07001704 // if the system property isn't set, use the value for the apn type
1705 int ret = RESTORE_DEFAULT_NETWORK_DELAY;
1706
1707 if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
1708 (mNetConfigs[networkType] != null)) {
1709 ret = mNetConfigs[networkType].restoreTime;
1710 }
1711 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 }
1713
1714 @Override
1715 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001716 if (mContext.checkCallingOrSelfPermission(
1717 android.Manifest.permission.DUMP)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 != PackageManager.PERMISSION_GRANTED) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001719 pw.println("Permission Denial: can't dump ConnectivityService " +
1720 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1721 Binder.getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001722 return;
1723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 pw.println();
1725 for (NetworkStateTracker nst : mNetTrackers) {
Robert Greenwaltb9285352009-12-21 18:24:07 -08001726 if (nst != null) {
1727 if (nst.getNetworkInfo().isConnected()) {
1728 pw.println("Active network: " + nst.getNetworkInfo().
1729 getTypeName());
1730 }
1731 pw.println(nst.getNetworkInfo());
1732 pw.println(nst);
1733 pw.println();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001734 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 }
Robert Greenwaltb9285352009-12-21 18:24:07 -08001736
1737 pw.println("Network Requester Pids:");
1738 for (int net : mPriorityList) {
1739 String pidString = net + ": ";
1740 for (Object pid : mNetRequestersPids[net]) {
1741 pidString = pidString + pid.toString() + ", ";
1742 }
1743 pw.println(pidString);
1744 }
1745 pw.println();
1746
1747 pw.println("FeatureUsers:");
1748 for (Object requester : mFeatureUsers) {
1749 pw.println(requester.toString());
1750 }
1751 pw.println();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001752
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001753 synchronized (this) {
1754 pw.println("NetworkTranstionWakeLock is currently " +
1755 (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held.");
1756 pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy);
1757 }
1758 pw.println();
1759
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001760 mTethering.dump(fd, pw, args);
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -07001761
1762 if (mInetLog != null) {
1763 pw.println();
1764 pw.println("Inet condition reports:");
1765 for(int i = 0; i < mInetLog.size(); i++) {
1766 pw.println(mInetLog.get(i));
1767 }
1768 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 }
1770
Robert Greenwalt42acef32009-08-12 16:08:25 -07001771 // must be stateless - things change under us.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 private class MyHandler extends Handler {
Wink Savillebb08caf2010-09-02 19:23:52 -07001773 public MyHandler(Looper looper) {
1774 super(looper);
1775 }
1776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 @Override
1778 public void handleMessage(Message msg) {
1779 NetworkInfo info;
1780 switch (msg.what) {
1781 case NetworkStateTracker.EVENT_STATE_CHANGED:
1782 info = (NetworkInfo) msg.obj;
Robert Greenwalt511288a2009-12-07 11:33:18 -08001783 int type = info.getType();
1784 NetworkInfo.State state = info.getState();
Robert Greenwalt511288a2009-12-07 11:33:18 -08001785
Wink Savilleed9c02b2010-12-03 12:01:38 -08001786 if (DBG) log("ConnectivityChange for " +
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001787 info.getTypeName() + ": " +
Robert Greenwalt511288a2009-12-07 11:33:18 -08001788 state + "/" + info.getDetailedState());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789
1790 // Connectivity state changed:
1791 // [31-13] Reserved for future use
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001792 // [12-9] Network subtype (for mobile network, as defined
1793 // by TelephonyManager)
1794 // [8-3] Detailed state ordinal (as defined by
1795 // NetworkInfo.DetailedState)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001796 // [2-0] Network type (as defined by ConnectivityManager)
1797 int eventLogParam = (info.getType() & 0x7) |
1798 ((info.getDetailedState().ordinal() & 0x3f) << 3) |
1799 (info.getSubtype() << 9);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001800 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001801 eventLogParam);
1802
1803 if (info.getDetailedState() ==
1804 NetworkInfo.DetailedState.FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 handleConnectionFailure(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001806 } else if (state == NetworkInfo.State.DISCONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001807 handleDisconnect(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001808 } else if (state == NetworkInfo.State.SUSPENDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 // TODO: need to think this over.
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001810 // the logic here is, handle SUSPENDED the same as
1811 // DISCONNECTED. The only difference being we are
1812 // broadcasting an intent with NetworkInfo that's
1813 // suspended. This allows the applications an
1814 // opportunity to handle DISCONNECTED and SUSPENDED
1815 // differently, or not.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816 handleDisconnect(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001817 } else if (state == NetworkInfo.State.CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 handleConnect(info);
1819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001821 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001822 info = (NetworkInfo) msg.obj;
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001823 handleConnectivityChange(info.getType());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001824 break;
Robert Greenwaltf3331232010-09-24 14:32:21 -07001825 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001826 String causedBy = null;
1827 synchronized (ConnectivityService.this) {
1828 if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
1829 mNetTransitionWakeLock.isHeld()) {
1830 mNetTransitionWakeLock.release();
1831 causedBy = mNetTransitionWakeLockCausedBy;
1832 }
1833 }
1834 if (causedBy != null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001835 log("NetTransition Wakelock for " + causedBy + " released by timeout");
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001836 }
Robert Greenwalt057d5e92010-09-09 14:05:10 -07001837 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001838 case EVENT_RESTORE_DEFAULT_NETWORK:
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -07001839 FeatureUser u = (FeatureUser)msg.obj;
1840 u.expire();
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001841 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001842 case EVENT_INET_CONDITION_CHANGE:
1843 {
1844 int netType = msg.arg1;
1845 int condition = msg.arg2;
1846 handleInetConditionChange(netType, condition);
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001847 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001848 }
1849 case EVENT_INET_CONDITION_HOLD_END:
1850 {
1851 int netType = msg.arg1;
1852 int sequence = msg.arg2;
1853 handleInetConditionHoldEnd(netType, sequence);
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001854 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001855 }
1856 case EVENT_SET_NETWORK_PREFERENCE:
1857 {
1858 int preference = msg.arg1;
1859 handleSetNetworkPreference(preference);
1860 break;
1861 }
1862 case EVENT_SET_BACKGROUND_DATA:
1863 {
1864 boolean enabled = (msg.arg1 == ENABLED);
1865 handleSetBackgroundData(enabled);
1866 break;
1867 }
1868 case EVENT_SET_MOBILE_DATA:
1869 {
1870 boolean enabled = (msg.arg1 == ENABLED);
1871 handleSetMobileData(enabled);
1872 break;
1873 }
Robert Greenwalt434203a2010-10-11 16:00:27 -07001874 case EVENT_APPLY_GLOBAL_HTTP_PROXY:
1875 {
1876 handleDeprecatedGlobalHttpProxy();
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001877 break;
1878 }
1879 case EVENT_SET_DEPENDENCY_MET:
1880 {
1881 boolean met = (msg.arg1 == ENABLED);
1882 handleSetDependencyMet(msg.arg2, met);
1883 break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 }
1886 }
1887 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001888
1889 // javadoc from interface
Robert Greenwalt5a735062010-03-02 17:25:02 -08001890 public int tether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001891 enforceTetherChangePermission();
Robert Greenwalt5a735062010-03-02 17:25:02 -08001892
1893 if (isTetheringSupported()) {
1894 return mTethering.tether(iface);
1895 } else {
1896 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1897 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001898 }
1899
1900 // javadoc from interface
Robert Greenwalt5a735062010-03-02 17:25:02 -08001901 public int untether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001902 enforceTetherChangePermission();
Robert Greenwalt5a735062010-03-02 17:25:02 -08001903
1904 if (isTetheringSupported()) {
1905 return mTethering.untether(iface);
1906 } else {
1907 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1908 }
1909 }
1910
1911 // javadoc from interface
1912 public int getLastTetherError(String iface) {
1913 enforceTetherAccessPermission();
1914
1915 if (isTetheringSupported()) {
1916 return mTethering.getLastTetherError(iface);
1917 } else {
1918 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1919 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001920 }
1921
1922 // TODO - proper iface API for selection by property, inspection, etc
1923 public String[] getTetherableUsbRegexs() {
1924 enforceTetherAccessPermission();
1925 if (isTetheringSupported()) {
1926 return mTethering.getTetherableUsbRegexs();
1927 } else {
1928 return new String[0];
1929 }
1930 }
1931
1932 public String[] getTetherableWifiRegexs() {
1933 enforceTetherAccessPermission();
1934 if (isTetheringSupported()) {
1935 return mTethering.getTetherableWifiRegexs();
1936 } else {
1937 return new String[0];
1938 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001939 }
1940
Danica Chang6fdd0c62010-08-11 14:54:43 -07001941 public String[] getTetherableBluetoothRegexs() {
1942 enforceTetherAccessPermission();
1943 if (isTetheringSupported()) {
1944 return mTethering.getTetherableBluetoothRegexs();
1945 } else {
1946 return new String[0];
1947 }
1948 }
1949
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001950 // TODO - move iface listing, queries, etc to new module
1951 // javadoc from interface
1952 public String[] getTetherableIfaces() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001953 enforceTetherAccessPermission();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001954 return mTethering.getTetherableIfaces();
1955 }
1956
1957 public String[] getTetheredIfaces() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001958 enforceTetherAccessPermission();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001959 return mTethering.getTetheredIfaces();
1960 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001961
Robert Greenwalt5a735062010-03-02 17:25:02 -08001962 public String[] getTetheringErroredIfaces() {
1963 enforceTetherAccessPermission();
1964 return mTethering.getErroredIfaces();
1965 }
1966
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001967 // if ro.tether.denied = true we default to no tethering
1968 // gservices could set the secure setting to 1 though to enable it on a build where it
1969 // had previously been turned off.
1970 public boolean isTetheringSupported() {
1971 enforceTetherAccessPermission();
1972 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001973 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
1974 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
1975 return tetherEnabledInSettings && mTetheringConfigValid;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001976 }
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001977
1978 // An API NetworkStateTrackers can call when they lose their network.
1979 // This will automatically be cleared after X seconds or a network becomes CONNECTED,
1980 // whichever happens first. The timer is started by the first caller and not
1981 // restarted by subsequent callers.
1982 public void requestNetworkTransitionWakelock(String forWhom) {
1983 enforceConnectivityInternalPermission();
1984 synchronized (this) {
1985 if (mNetTransitionWakeLock.isHeld()) return;
1986 mNetTransitionWakeLockSerialNumber++;
1987 mNetTransitionWakeLock.acquire();
1988 mNetTransitionWakeLockCausedBy = forWhom;
1989 }
1990 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltf3331232010-09-24 14:32:21 -07001991 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001992 mNetTransitionWakeLockSerialNumber, 0),
1993 mNetTransitionWakeLockTimeout);
1994 return;
1995 }
Robert Greenwaltca4306c2010-09-09 13:15:32 -07001996
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001997 // 100 percent is full good, 0 is full bad.
1998 public void reportInetCondition(int networkType, int percentage) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001999 if (DBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")");
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07002000 mContext.enforceCallingOrSelfPermission(
2001 android.Manifest.permission.STATUS_BAR,
2002 "ConnectivityService");
2003
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -07002004 if (DBG) {
2005 int pid = getCallingPid();
2006 int uid = getCallingUid();
2007 String s = pid + "(" + uid + ") reports inet is " +
2008 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
2009 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
2010 mInetLog.add(s);
2011 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
2012 mInetLog.remove(0);
2013 }
2014 }
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07002015 mHandler.sendMessage(mHandler.obtainMessage(
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002016 EVENT_INET_CONDITION_CHANGE, networkType, percentage));
2017 }
2018
2019 private void handleInetConditionChange(int netType, int condition) {
2020 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002021 log("Inet connectivity change, net=" +
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002022 netType + ", condition=" + condition +
2023 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
2024 }
2025 if (mActiveDefaultNetwork == -1) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002026 if (DBG) log("no active default network - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002027 return;
2028 }
2029 if (mActiveDefaultNetwork != netType) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002030 if (DBG) log("given net not default - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002031 return;
2032 }
2033 mDefaultInetCondition = condition;
2034 int delay;
2035 if (mInetConditionChangeInFlight == false) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002036 if (DBG) log("starting a change hold");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002037 // setup a new hold to debounce this
2038 if (mDefaultInetCondition > 50) {
2039 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2040 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
2041 } else {
2042 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2043 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
2044 }
2045 mInetConditionChangeInFlight = true;
2046 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
2047 mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
2048 } else {
2049 // we've set the new condition, when this hold ends that will get
2050 // picked up
Wink Savilleed9c02b2010-12-03 12:01:38 -08002051 if (DBG) log("currently in hold - not setting new end evt");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002052 }
2053 }
2054
2055 private void handleInetConditionHoldEnd(int netType, int sequence) {
2056 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002057 log("Inet hold end, net=" + netType +
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002058 ", condition =" + mDefaultInetCondition +
2059 ", published condition =" + mDefaultInetConditionPublished);
2060 }
2061 mInetConditionChangeInFlight = false;
2062
2063 if (mActiveDefaultNetwork == -1) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002064 if (DBG) log("no active default network - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002065 return;
2066 }
2067 if (mDefaultConnectionSequence != sequence) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002068 if (DBG) log("event hold for obsolete network - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002069 return;
2070 }
2071 if (mDefaultInetConditionPublished == mDefaultInetCondition) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002072 if (DBG) log("no change in condition - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002073 return;
2074 }
2075 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
2076 if (networkInfo.isConnected() == false) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002077 if (DBG) log("default network not connected - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002078 return;
2079 }
2080 mDefaultInetConditionPublished = mDefaultInetCondition;
2081 sendInetConditionBroadcast(networkInfo);
2082 return;
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07002083 }
Robert Greenwalt434203a2010-10-11 16:00:27 -07002084
2085 public synchronized ProxyProperties getProxy() {
2086 if (mGlobalProxy != null) return mGlobalProxy;
2087 if (mDefaultProxy != null) return mDefaultProxy;
2088 return null;
2089 }
2090
2091 public void setGlobalProxy(ProxyProperties proxyProperties) {
2092 enforceChangePermission();
2093 synchronized (mGlobalProxyLock) {
2094 if (proxyProperties == mGlobalProxy) return;
2095 if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
2096 if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
2097
2098 String host = "";
2099 int port = 0;
2100 String exclList = "";
2101 if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) {
2102 mGlobalProxy = new ProxyProperties(proxyProperties);
2103 host = mGlobalProxy.getHost();
2104 port = mGlobalProxy.getPort();
2105 exclList = mGlobalProxy.getExclusionList();
2106 } else {
2107 mGlobalProxy = null;
2108 }
2109 ContentResolver res = mContext.getContentResolver();
2110 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host);
2111 Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port);
Robert Greenwaltb7090d62010-12-02 11:31:00 -08002112 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
Robert Greenwalt434203a2010-10-11 16:00:27 -07002113 exclList);
2114 }
2115
2116 if (mGlobalProxy == null) {
2117 proxyProperties = mDefaultProxy;
2118 }
2119 sendProxyBroadcast(proxyProperties);
2120 }
2121
Robert Greenwaltb7090d62010-12-02 11:31:00 -08002122 private void loadGlobalProxy() {
2123 ContentResolver res = mContext.getContentResolver();
2124 String host = Settings.Secure.getString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST);
2125 int port = Settings.Secure.getInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, 0);
2126 String exclList = Settings.Secure.getString(res,
2127 Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
2128 if (!TextUtils.isEmpty(host)) {
2129 ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList);
2130 synchronized (mGlobalProxyLock) {
2131 mGlobalProxy = proxyProperties;
2132 }
2133 }
2134 }
2135
Robert Greenwalt434203a2010-10-11 16:00:27 -07002136 public ProxyProperties getGlobalProxy() {
2137 synchronized (mGlobalProxyLock) {
2138 return mGlobalProxy;
2139 }
2140 }
2141
2142 private void handleApplyDefaultProxy(int type) {
2143 // check if new default - push it out to all VM if so
2144 ProxyProperties proxy = mNetTrackers[type].getLinkProperties().getHttpProxy();
2145 synchronized (this) {
2146 if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
2147 if (mDefaultProxy == proxy) return;
2148 if (!TextUtils.isEmpty(proxy.getHost())) {
2149 mDefaultProxy = proxy;
2150 } else {
2151 mDefaultProxy = null;
2152 }
2153 }
Wink Savilleed9c02b2010-12-03 12:01:38 -08002154 if (DBG) log("changing default proxy to " + proxy);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002155 if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return;
2156 if (mGlobalProxy != null) return;
2157 sendProxyBroadcast(proxy);
2158 }
2159
2160 private void handleDeprecatedGlobalHttpProxy() {
2161 String proxy = Settings.Secure.getString(mContext.getContentResolver(),
2162 Settings.Secure.HTTP_PROXY);
2163 if (!TextUtils.isEmpty(proxy)) {
2164 String data[] = proxy.split(":");
2165 String proxyHost = data[0];
2166 int proxyPort = 8080;
2167 if (data.length > 1) {
2168 try {
2169 proxyPort = Integer.parseInt(data[1]);
2170 } catch (NumberFormatException e) {
2171 return;
2172 }
2173 }
2174 ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
2175 setGlobalProxy(p);
2176 }
2177 }
2178
2179 private void sendProxyBroadcast(ProxyProperties proxy) {
Robert Greenwalt55985be2010-12-23 15:51:10 -08002180 if (proxy == null) proxy = new ProxyProperties("", 0, "");
Wink Savilleed9c02b2010-12-03 12:01:38 -08002181 log("sending Proxy Broadcast for " + proxy);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002182 Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
Stan Chesnuttb35d67a2011-01-06 11:00:19 -08002183 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
2184 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002185 intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
Robert Greenwalta2e13392010-12-06 11:29:17 -08002186 mContext.sendStickyBroadcast(intent);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002187 }
2188
2189 private static class SettingsObserver extends ContentObserver {
2190 private int mWhat;
2191 private Handler mHandler;
2192 SettingsObserver(Handler handler, int what) {
2193 super(handler);
2194 mHandler = handler;
2195 mWhat = what;
2196 }
2197
2198 void observe(Context context) {
2199 ContentResolver resolver = context.getContentResolver();
2200 resolver.registerContentObserver(Settings.Secure.getUriFor(
2201 Settings.Secure.HTTP_PROXY), false, this);
2202 }
2203
2204 @Override
2205 public void onChange(boolean selfChange) {
2206 mHandler.obtainMessage(mWhat).sendToTarget();
2207 }
2208 }
Wink Savilleed9c02b2010-12-03 12:01:38 -08002209
2210 private void log(String s) {
2211 Slog.d(TAG, s);
2212 }
2213
2214 private void loge(String s) {
2215 Slog.e(TAG, s);
2216 }
Wink Saville9d7d6282011-03-12 14:52:01 -08002217 int convertFeatureToNetworkType(String feature){
2218 int networkType = -1;
2219 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
2220 networkType = ConnectivityManager.TYPE_MOBILE_MMS;
2221 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
2222 networkType = ConnectivityManager.TYPE_MOBILE_SUPL;
2223 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
2224 TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
2225 networkType = ConnectivityManager.TYPE_MOBILE_DUN;
2226 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
2227 networkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
2228 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
2229 networkType = ConnectivityManager.TYPE_MOBILE_FOTA;
2230 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
2231 networkType = ConnectivityManager.TYPE_MOBILE_IMS;
2232 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
2233 networkType = ConnectivityManager.TYPE_MOBILE_CBS;
2234 }
2235 return networkType;
2236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237}