blob: f88b1888db1682940c8da076038b455fda0a3f4f [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Jaikumar Ganesh15c74392010-12-21 22:31:44 -080019import android.bluetooth.BluetoothTetheringDataTracker;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.content.ContentResolver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.pm.PackageManager;
Robert Greenwalt434203a2010-10-11 16:00:27 -070024import android.database.ContentObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.net.ConnectivityManager;
Robert Greenwaltda3d5e62010-12-06 13:56:24 -080026import android.net.DummyDataStateTracker;
Benoit Goby08c39c62010-12-22 14:29:40 -080027import android.net.EthernetDataTracker;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.net.IConnectivityManager;
Jaikumar Ganesh15c74392010-12-21 22:31:44 -080029import android.net.LinkProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.net.MobileDataStateTracker;
Robert Greenwaltd55a6b42011-03-25 13:09:25 -070031import android.net.NetworkConfig;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.net.NetworkInfo;
33import android.net.NetworkStateTracker;
Robert Greenwalt585ac0f2010-08-27 09:24:29 -070034import android.net.NetworkUtils;
Robert Greenwalt434203a2010-10-11 16:00:27 -070035import android.net.Proxy;
36import android.net.ProxyProperties;
Robert Greenwaltaa70f102011-04-28 14:28:50 -070037import android.net.RouteInfo;
Hung-ying Tyan6b818de2011-01-19 16:48:38 +080038import android.net.vpn.VpnManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.net.wifi.WifiStateTracker;
40import android.os.Binder;
41import android.os.Handler;
Wink Savillebb08caf2010-09-02 19:23:52 -070042import android.os.HandlerThread;
Robert Greenwalt42acef32009-08-12 16:08:25 -070043import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.os.Looper;
45import android.os.Message;
Robert Greenwalt14f2ef42010-06-15 12:19:37 -070046import android.os.PowerManager;
Robert Greenwalt42acef32009-08-12 16:08:25 -070047import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.os.ServiceManager;
49import android.os.SystemProperties;
50import android.provider.Settings;
Robert Greenwalt42acef32009-08-12 16:08:25 -070051import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -080053import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054
Robert Greenwalt42acef32009-08-12 16:08:25 -070055import com.android.internal.telephony.Phone;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080056import com.android.server.connectivity.Tethering;
57
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import java.io.FileDescriptor;
Irfan Sheriffd649c122010-06-09 15:39:36 -070059import java.io.FileWriter;
60import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import java.io.PrintWriter;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070062import java.net.InetAddress;
63import java.net.UnknownHostException;
Robert Greenwalt42acef32009-08-12 16:08:25 -070064import java.util.ArrayList;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070065import java.util.Collection;
Robert Greenwaltd825ea42010-12-29 16:15:02 -080066import java.util.concurrent.atomic.AtomicBoolean;
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -070067import java.util.GregorianCalendar;
Robert Greenwalt42acef32009-08-12 16:08:25 -070068import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069
70/**
71 * @hide
72 */
73public class ConnectivityService extends IConnectivityManager.Stub {
74
Robert Greenwaltba175a52010-10-05 19:12:26 -070075 private static final boolean DBG = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 private static final String TAG = "ConnectivityService";
77
Robert Greenwalt42acef32009-08-12 16:08:25 -070078 // how long to wait before switching back to a radio's default network
79 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
80 // system property that can override the above value
81 private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
82 "android.telephony.apn-restore";
83
Robert Greenwaltf43396c2011-05-06 17:10:53 -070084 // used in recursive route setting to add gateways for the host for which
85 // a host route was requested.
86 private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10;
87
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080088 private Tethering mTethering;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -080089 private boolean mTetheringConfigValid = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 /**
92 * Sometimes we want to refer to the individual network state
93 * trackers separately, and sometimes we just want to treat them
94 * abstractly.
95 */
96 private NetworkStateTracker mNetTrackers[];
Robert Greenwalt42acef32009-08-12 16:08:25 -070097
98 /**
99 * A per Net list of the PID's that requested access to the net
100 * used both as a refcount and for per-PID DNS selection
101 */
102 private List mNetRequestersPids[];
103
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700104 private WifiWatchdogService mWifiWatchdogService;
105
Robert Greenwalt42acef32009-08-12 16:08:25 -0700106 // priority order of the nettrackers
107 // (excluding dynamically set mNetworkPreference)
108 // TODO - move mNetworkTypePreference into this
109 private int[] mPriorityList;
110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 private Context mContext;
112 private int mNetworkPreference;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700113 private int mActiveDefaultNetwork = -1;
Robert Greenwaltd7085fc2010-09-08 15:24:47 -0700114 // 0 is full bad, 100 is full good
115 private int mDefaultInetCondition = 0;
116 private int mDefaultInetConditionPublished = 0;
117 private boolean mInetConditionChangeInFlight = false;
118 private int mDefaultConnectionSequence = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119
120 private int mNumDnsEntries;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121
122 private boolean mTestMode;
Joe Onorato00092872010-09-01 21:18:22 -0700123 private static ConnectivityService sServiceInstance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124
Robert Greenwaltd825ea42010-12-29 16:15:02 -0800125 private AtomicBoolean mBackgroundDataEnabled = new AtomicBoolean(true);
126
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700127 private static final int ENABLED = 1;
128 private static final int DISABLED = 0;
129
130 // Share the event space with NetworkStateTracker (which can't see this
131 // internal class but sends us events). If you change these, change
132 // NetworkStateTracker.java too.
133 private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1;
134 private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100;
135
136 /**
137 * used internally as a delayed event to make us switch back to the
138 * default network
139 */
140 private static final int EVENT_RESTORE_DEFAULT_NETWORK =
141 MAX_NETWORK_STATE_TRACKER_EVENT + 1;
142
143 /**
144 * used internally to change our mobile data enabled flag
145 */
146 private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED =
147 MAX_NETWORK_STATE_TRACKER_EVENT + 2;
148
149 /**
150 * used internally to change our network preference setting
151 * arg1 = networkType to prefer
152 */
153 private static final int EVENT_SET_NETWORK_PREFERENCE =
154 MAX_NETWORK_STATE_TRACKER_EVENT + 3;
155
156 /**
157 * used internally to synchronize inet condition reports
158 * arg1 = networkType
159 * arg2 = condition (0 bad, 100 good)
160 */
161 private static final int EVENT_INET_CONDITION_CHANGE =
162 MAX_NETWORK_STATE_TRACKER_EVENT + 4;
163
164 /**
165 * used internally to mark the end of inet condition hold periods
166 * arg1 = networkType
167 */
168 private static final int EVENT_INET_CONDITION_HOLD_END =
169 MAX_NETWORK_STATE_TRACKER_EVENT + 5;
170
171 /**
172 * used internally to set the background data preference
173 * arg1 = TRUE for enabled, FALSE for disabled
174 */
175 private static final int EVENT_SET_BACKGROUND_DATA =
176 MAX_NETWORK_STATE_TRACKER_EVENT + 6;
177
178 /**
179 * used internally to set enable/disable cellular data
180 * arg1 = ENBALED or DISABLED
181 */
182 private static final int EVENT_SET_MOBILE_DATA =
183 MAX_NETWORK_STATE_TRACKER_EVENT + 7;
184
Robert Greenwaltf3331232010-09-24 14:32:21 -0700185 /**
186 * used internally to clear a wakelock when transitioning
187 * from one net to another
188 */
189 private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK =
190 MAX_NETWORK_STATE_TRACKER_EVENT + 8;
191
Robert Greenwalt434203a2010-10-11 16:00:27 -0700192 /**
193 * used internally to reload global proxy settings
194 */
195 private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY =
196 MAX_NETWORK_STATE_TRACKER_EVENT + 9;
197
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700198 /**
199 * used internally to set external dependency met/unmet
200 * arg1 = ENABLED (met) or DISABLED (unmet)
201 * arg2 = NetworkType
202 */
203 private static final int EVENT_SET_DEPENDENCY_MET =
204 MAX_NETWORK_STATE_TRACKER_EVENT + 10;
205
Robert Greenwalt42acef32009-08-12 16:08:25 -0700206 private Handler mHandler;
207
208 // list of DeathRecipients used to make sure features are turned off when
209 // a process dies
210 private List mFeatureUsers;
211
Mike Lockwood0f79b542009-08-14 14:18:49 -0400212 private boolean mSystemReady;
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800213 private Intent mInitialBroadcast;
Mike Lockwood0f79b542009-08-14 14:18:49 -0400214
Robert Greenwalt14f2ef42010-06-15 12:19:37 -0700215 private PowerManager.WakeLock mNetTransitionWakeLock;
216 private String mNetTransitionWakeLockCausedBy = "";
217 private int mNetTransitionWakeLockSerialNumber;
218 private int mNetTransitionWakeLockTimeout;
219
Robert Greenwalte90aa5e2010-09-01 11:34:05 -0700220 private InetAddress mDefaultDns;
221
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -0700222 // used in DBG mode to track inet condition reports
223 private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
224 private ArrayList mInetLog;
225
Robert Greenwalt434203a2010-10-11 16:00:27 -0700226 // track the current default http proxy - tell the world if we get a new one (real change)
227 private ProxyProperties mDefaultProxy = null;
228 // track the global proxy.
229 private ProxyProperties mGlobalProxy = null;
230 private final Object mGlobalProxyLock = new Object();
231
232 private SettingsObserver mSettingsObserver;
233
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700234 NetworkConfig[] mNetConfigs;
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700235 int mNetworksDefined;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700236
Robert Greenwalt511288a2009-12-07 11:33:18 -0800237 private static class RadioAttributes {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700238 public int mSimultaneity;
239 public int mType;
240 public RadioAttributes(String init) {
241 String fragments[] = init.split(",");
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700242 mType = Integer.parseInt(fragments[0]);
243 mSimultaneity = Integer.parseInt(fragments[1]);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700244 }
245 }
246 RadioAttributes[] mRadioAttributes;
247
Wink Savillebb08caf2010-09-02 19:23:52 -0700248 public static synchronized ConnectivityService getInstance(Context context) {
249 if (sServiceInstance == null) {
250 sServiceInstance = new ConnectivityService(context);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 }
Wink Savillebb08caf2010-09-02 19:23:52 -0700252 return sServiceInstance;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 private ConnectivityService(Context context) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800256 if (DBG) log("ConnectivityService starting up");
Robert Greenwaltde8383c2010-01-14 17:47:58 -0800257
Wink Savillebb08caf2010-09-02 19:23:52 -0700258 HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
259 handlerThread.start();
260 mHandler = new MyHandler(handlerThread.getLooper());
261
Robert Greenwaltd825ea42010-12-29 16:15:02 -0800262 mBackgroundDataEnabled.set(Settings.Secure.getInt(context.getContentResolver(),
263 Settings.Secure.BACKGROUND_DATA, 1) == 1);
264
Robert Greenwaltde8383c2010-01-14 17:47:58 -0800265 // setup our unique device name
Robert Greenwalt733c6292010-12-06 09:30:17 -0800266 if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
267 String id = Settings.Secure.getString(context.getContentResolver(),
268 Settings.Secure.ANDROID_ID);
269 if (id != null && id.length() > 0) {
270 String name = new String("android_").concat(id);
271 SystemProperties.set("net.hostname", name);
272 }
Robert Greenwaltde8383c2010-01-14 17:47:58 -0800273 }
274
Robert Greenwalte90aa5e2010-09-01 11:34:05 -0700275 // read our default dns server ip
276 String dns = Settings.Secure.getString(context.getContentResolver(),
277 Settings.Secure.DEFAULT_DNS_SERVER);
278 if (dns == null || dns.length() == 0) {
279 dns = context.getResources().getString(
280 com.android.internal.R.string.config_default_dns_server);
281 }
282 try {
Robert Greenwalte5903732011-02-22 16:00:42 -0800283 mDefaultDns = NetworkUtils.numericToInetAddress(dns);
284 } catch (IllegalArgumentException e) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800285 loge("Error setting defaultDns using " + dns);
Robert Greenwalte90aa5e2010-09-01 11:34:05 -0700286 }
287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 mContext = context;
Robert Greenwalt14f2ef42010-06-15 12:19:37 -0700289
290 PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
291 mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
292 mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
293 com.android.internal.R.integer.config_networkTransitionTimeout);
294
Robert Greenwalt42acef32009-08-12 16:08:25 -0700295 mNetTrackers = new NetworkStateTracker[
296 ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 mNetworkPreference = getPersistedNetworkPreference();
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700299
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700300 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700301 mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700302
Robert Greenwalt42acef32009-08-12 16:08:25 -0700303 // Load device network attributes from resources
Robert Greenwalt42acef32009-08-12 16:08:25 -0700304 String[] raStrings = context.getResources().getStringArray(
305 com.android.internal.R.array.radioAttributes);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700306 for (String raString : raStrings) {
307 RadioAttributes r = new RadioAttributes(raString);
308 if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800309 loge("Error in radioAttributes - ignoring attempt to define type " + r.mType);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700310 continue;
311 }
312 if (mRadioAttributes[r.mType] != null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800313 loge("Error in radioAttributes - ignoring attempt to redefine type " +
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700314 r.mType);
315 continue;
316 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700317 mRadioAttributes[r.mType] = r;
318 }
319
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700320 String[] naStrings = context.getResources().getStringArray(
321 com.android.internal.R.array.networkAttributes);
322 for (String naString : naStrings) {
323 try {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700324 NetworkConfig n = new NetworkConfig(naString);
Wink Saville975c8482011-04-07 14:23:45 -0700325 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800326 loge("Error in networkAttributes - ignoring attempt to define type " +
Wink Saville975c8482011-04-07 14:23:45 -0700327 n.type);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700328 continue;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700329 }
Wink Saville975c8482011-04-07 14:23:45 -0700330 if (mNetConfigs[n.type] != null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800331 loge("Error in networkAttributes - ignoring attempt to redefine type " +
Wink Saville975c8482011-04-07 14:23:45 -0700332 n.type);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700333 continue;
334 }
Wink Saville975c8482011-04-07 14:23:45 -0700335 if (mRadioAttributes[n.radio] == null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800336 loge("Error in networkAttributes - ignoring attempt to use undefined " +
Wink Saville975c8482011-04-07 14:23:45 -0700337 "radio " + n.radio + " in network type " + n.type);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700338 continue;
339 }
Wink Saville975c8482011-04-07 14:23:45 -0700340 mNetConfigs[n.type] = n;
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700341 mNetworksDefined++;
342 } catch(Exception e) {
343 // ignore it - leave the entry null
Robert Greenwalt42acef32009-08-12 16:08:25 -0700344 }
345 }
346
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700347 // high priority first
348 mPriorityList = new int[mNetworksDefined];
349 {
350 int insertionPoint = mNetworksDefined-1;
351 int currentLowest = 0;
352 int nextLowest = 0;
353 while (insertionPoint > -1) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700354 for (NetworkConfig na : mNetConfigs) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700355 if (na == null) continue;
Wink Saville975c8482011-04-07 14:23:45 -0700356 if (na.priority < currentLowest) continue;
357 if (na.priority > currentLowest) {
358 if (na.priority < nextLowest || nextLowest == 0) {
359 nextLowest = na.priority;
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700360 }
361 continue;
362 }
Wink Saville975c8482011-04-07 14:23:45 -0700363 mPriorityList[insertionPoint--] = na.type;
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700364 }
365 currentLowest = nextLowest;
366 nextLowest = 0;
367 }
368 }
369
370 mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
371 for (int i : mPriorityList) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700372 mNetRequestersPids[i] = new ArrayList();
373 }
374
375 mFeatureUsers = new ArrayList();
376
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700377 mNumDnsEntries = 0;
378
379 mTestMode = SystemProperties.get("cm.test.mode").equals("true")
380 && SystemProperties.get("ro.build.type").equals("eng");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 /*
382 * Create the network state trackers for Wi-Fi and mobile
383 * data. Maybe this could be done with a factory class,
384 * but it's not clear that it's worth it, given that
385 * the number of different network types is not going
386 * to change very often.
387 */
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700388 for (int netType : mPriorityList) {
Wink Saville975c8482011-04-07 14:23:45 -0700389 switch (mNetConfigs[netType].radio) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700390 case ConnectivityManager.TYPE_WIFI:
Wink Savilleed9c02b2010-12-03 12:01:38 -0800391 if (DBG) log("Starting Wifi Service.");
Wink Savillec7a98342010-08-13 16:11:42 -0700392 WifiStateTracker wst = new WifiStateTracker();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700393 WifiService wifiService = new WifiService(context);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700394 ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700395 wifiService.checkAndStartWifi();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700396 mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
Wink Savillec7a98342010-08-13 16:11:42 -0700397 wst.startMonitoring(context, mHandler);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700399 //TODO: as part of WWS refactor, create only when needed
Irfan Sheriff0d255342010-07-28 09:35:20 -0700400 mWifiWatchdogService = new WifiWatchdogService(context);
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700401
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700402 break;
403 case ConnectivityManager.TYPE_MOBILE:
Wink Savillec7a98342010-08-13 16:11:42 -0700404 mNetTrackers[netType] = new MobileDataStateTracker(netType,
Wink Saville975c8482011-04-07 14:23:45 -0700405 mNetConfigs[netType].name);
Wink Savillec7a98342010-08-13 16:11:42 -0700406 mNetTrackers[netType].startMonitoring(context, mHandler);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700407 break;
Robert Greenwaltda3d5e62010-12-06 13:56:24 -0800408 case ConnectivityManager.TYPE_DUMMY:
409 mNetTrackers[netType] = new DummyDataStateTracker(netType,
Wink Saville975c8482011-04-07 14:23:45 -0700410 mNetConfigs[netType].name);
Robert Greenwaltda3d5e62010-12-06 13:56:24 -0800411 mNetTrackers[netType].startMonitoring(context, mHandler);
412 break;
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800413 case ConnectivityManager.TYPE_BLUETOOTH:
414 mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
415 mNetTrackers[netType].startMonitoring(context, mHandler);
416 break;
Benoit Goby08c39c62010-12-22 14:29:40 -0800417 case ConnectivityManager.TYPE_ETHERNET:
418 mNetTrackers[netType] = EthernetDataTracker.getInstance();
419 mNetTrackers[netType].startMonitoring(context, mHandler);
420 break;
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700421 default:
Wink Savilleed9c02b2010-12-03 12:01:38 -0800422 loge("Trying to create a DataStateTracker for an unknown radio type " +
Wink Saville975c8482011-04-07 14:23:45 -0700423 mNetConfigs[netType].radio);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700424 continue;
425 }
426 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800427
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800428 mTethering = new Tethering(mContext, mHandler.getLooper());
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800429 mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) ||
430 !mTethering.isDunRequired()) &&
431 (mTethering.getTetherableUsbRegexs().length != 0 ||
Danica Chang6fdd0c62010-08-11 14:54:43 -0700432 mTethering.getTetherableWifiRegexs().length != 0 ||
433 mTethering.getTetherableBluetoothRegexs().length != 0) &&
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800434 mTethering.getUpstreamIfaceRegexs().length != 0);
435
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -0700436 if (DBG) {
437 mInetLog = new ArrayList();
438 }
Robert Greenwalt434203a2010-10-11 16:00:27 -0700439
440 mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
441 mSettingsObserver.observe(mContext);
Robert Greenwaltb7090d62010-12-02 11:31:00 -0800442
443 loadGlobalProxy();
Hung-ying Tyan6b818de2011-01-19 16:48:38 +0800444
445 VpnManager.startVpnService(context);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 }
447
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700448
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 /**
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700450 * Sets the preferred network.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 * @param preference the new preference
452 */
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700453 public void setNetworkPreference(int preference) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 enforceChangePermission();
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700455
456 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 }
458
459 public int getNetworkPreference() {
460 enforceAccessPermission();
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700461 int preference;
462 synchronized(this) {
463 preference = mNetworkPreference;
464 }
465 return preference;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 }
467
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700468 private void handleSetNetworkPreference(int preference) {
469 if (ConnectivityManager.isNetworkTypeValid(preference) &&
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700470 mNetConfigs[preference] != null &&
471 mNetConfigs[preference].isDefault()) {
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700472 if (mNetworkPreference != preference) {
473 final ContentResolver cr = mContext.getContentResolver();
474 Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference);
475 synchronized(this) {
476 mNetworkPreference = preference;
477 }
478 enforcePreference();
479 }
480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 private int getPersistedNetworkPreference() {
484 final ContentResolver cr = mContext.getContentResolver();
485
486 final int networkPrefSetting = Settings.Secure
487 .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
488 if (networkPrefSetting != -1) {
489 return networkPrefSetting;
490 }
491
492 return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
493 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 /**
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700496 * Make the state of network connectivity conform to the preference settings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 * In this method, we only tear down a non-preferred network. Establishing
498 * a connection to the preferred network is taken care of when we handle
499 * the disconnect event from the non-preferred network
500 * (see {@link #handleDisconnect(NetworkInfo)}).
501 */
502 private void enforcePreference() {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700503 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 return;
505
Robert Greenwalt42acef32009-08-12 16:08:25 -0700506 if (!mNetTrackers[mNetworkPreference].isAvailable())
507 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508
Robert Greenwalt42acef32009-08-12 16:08:25 -0700509 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700510 if (t != mNetworkPreference && mNetTrackers[t] != null &&
Robert Greenwalt42acef32009-08-12 16:08:25 -0700511 mNetTrackers[t].getNetworkInfo().isConnected()) {
Robert Greenwaltec9fe462009-08-20 15:25:14 -0700512 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800513 log("tearing down " + mNetTrackers[t].getNetworkInfo() +
Robert Greenwaltec9fe462009-08-20 15:25:14 -0700514 " in enforcePreference");
515 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700516 teardown(mNetTrackers[t]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 }
518 }
519 }
520
521 private boolean teardown(NetworkStateTracker netTracker) {
522 if (netTracker.teardown()) {
523 netTracker.setTeardownRequested(true);
524 return true;
525 } else {
526 return false;
527 }
528 }
529
530 /**
531 * Return NetworkInfo for the active (i.e., connected) network interface.
532 * It is assumed that at most one network is active at a time. If more
533 * than one is active, it is indeterminate which will be returned.
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700534 * @return the info for the active network, or {@code null} if none is
535 * active
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 */
537 public NetworkInfo getActiveNetworkInfo() {
538 enforceAccessPermission();
Robert Greenwalt42acef32009-08-12 16:08:25 -0700539 for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700540 if (mNetConfigs[type] == null || !mNetConfigs[type].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700541 continue;
542 }
543 NetworkStateTracker t = mNetTrackers[type];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544 NetworkInfo info = t.getNetworkInfo();
545 if (info.isConnected()) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800546 if (DBG && type != mActiveDefaultNetwork) {
547 loge("connected default network is not mActiveDefaultNetwork!");
548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 return info;
550 }
551 }
552 return null;
553 }
554
555 public NetworkInfo getNetworkInfo(int networkType) {
556 enforceAccessPermission();
557 if (ConnectivityManager.isNetworkTypeValid(networkType)) {
558 NetworkStateTracker t = mNetTrackers[networkType];
559 if (t != null)
560 return t.getNetworkInfo();
561 }
562 return null;
563 }
564
565 public NetworkInfo[] getAllNetworkInfo() {
566 enforceAccessPermission();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700567 NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800568 int i = 0;
569 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700570 if(t != null) result[i++] = t.getNetworkInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 }
572 return result;
573 }
574
Robert Greenwaltd192dad2010-09-14 09:18:02 -0700575 /**
576 * Return LinkProperties for the active (i.e., connected) default
577 * network interface. It is assumed that at most one default network
578 * is active at a time. If more than one is active, it is indeterminate
579 * which will be returned.
580 * @return the ip properties for the active network, or {@code null} if
581 * none is active
582 */
583 public LinkProperties getActiveLinkProperties() {
584 enforceAccessPermission();
585 for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700586 if (mNetConfigs[type] == null || !mNetConfigs[type].isDefault()) {
Robert Greenwaltd192dad2010-09-14 09:18:02 -0700587 continue;
588 }
589 NetworkStateTracker t = mNetTrackers[type];
590 NetworkInfo info = t.getNetworkInfo();
591 if (info.isConnected()) {
592 return t.getLinkProperties();
593 }
594 }
595 return null;
596 }
597
598 public LinkProperties getLinkProperties(int networkType) {
599 enforceAccessPermission();
600 if (ConnectivityManager.isNetworkTypeValid(networkType)) {
601 NetworkStateTracker t = mNetTrackers[networkType];
602 if (t != null) return t.getLinkProperties();
603 }
604 return null;
605 }
606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607 public boolean setRadios(boolean turnOn) {
608 boolean result = true;
609 enforceChangePermission();
610 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700611 if (t != null) result = t.setRadio(turnOn) && result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 }
613 return result;
614 }
615
616 public boolean setRadio(int netType, boolean turnOn) {
617 enforceChangePermission();
618 if (!ConnectivityManager.isNetworkTypeValid(netType)) {
619 return false;
620 }
621 NetworkStateTracker tracker = mNetTrackers[netType];
622 return tracker != null && tracker.setRadio(turnOn);
623 }
624
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700625 /**
626 * Used to notice when the calling process dies so we can self-expire
627 *
628 * Also used to know if the process has cleaned up after itself when
629 * our auto-expire timer goes off. The timer has a link to an object.
630 *
631 */
Robert Greenwalt42acef32009-08-12 16:08:25 -0700632 private class FeatureUser implements IBinder.DeathRecipient {
633 int mNetworkType;
634 String mFeature;
635 IBinder mBinder;
636 int mPid;
637 int mUid;
Robert Greenwaltb9285352009-12-21 18:24:07 -0800638 long mCreateTime;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700639
640 FeatureUser(int type, String feature, IBinder binder) {
641 super();
642 mNetworkType = type;
643 mFeature = feature;
644 mBinder = binder;
645 mPid = getCallingPid();
646 mUid = getCallingUid();
Robert Greenwaltb9285352009-12-21 18:24:07 -0800647 mCreateTime = System.currentTimeMillis();
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700648
Robert Greenwalt42acef32009-08-12 16:08:25 -0700649 try {
650 mBinder.linkToDeath(this, 0);
651 } catch (RemoteException e) {
652 binderDied();
653 }
654 }
655
656 void unlinkDeathRecipient() {
657 mBinder.unlinkToDeath(this, 0);
658 }
659
660 public void binderDied() {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800661 log("ConnectivityService FeatureUser binderDied(" +
Robert Greenwaltb9285352009-12-21 18:24:07 -0800662 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
663 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700664 stopUsingNetworkFeature(this, false);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700665 }
666
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700667 public void expire() {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800668 log("ConnectivityService FeatureUser expire(" +
Robert Greenwaltb9285352009-12-21 18:24:07 -0800669 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
670 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700671 stopUsingNetworkFeature(this, false);
672 }
Robert Greenwaltb9285352009-12-21 18:24:07 -0800673
674 public String toString() {
675 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
676 (System.currentTimeMillis() - mCreateTime) + " mSec ago";
677 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700678 }
679
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700680 // javadoc from interface
Robert Greenwalt42acef32009-08-12 16:08:25 -0700681 public int startUsingNetworkFeature(int networkType, String feature,
682 IBinder binder) {
683 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800684 log("startUsingNetworkFeature for net " + networkType + ": " + feature);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 enforceChangePermission();
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700687 if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700688 mNetConfigs[networkType] == null) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700689 return Phone.APN_REQUEST_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700691
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700692 FeatureUser f = new FeatureUser(networkType, feature, binder);
Robert Greenwalt42acef32009-08-12 16:08:25 -0700693
694 // TODO - move this into the MobileDataStateTracker
695 int usedNetworkType = networkType;
696 if(networkType == ConnectivityManager.TYPE_MOBILE) {
Wink Saville9d7d6282011-03-12 14:52:01 -0800697 usedNetworkType = convertFeatureToNetworkType(feature);
698 if (usedNetworkType < 0) {
699 Slog.e(TAG, "Can't match any netTracker!");
700 usedNetworkType = networkType;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700701 }
702 }
703 NetworkStateTracker network = mNetTrackers[usedNetworkType];
704 if (network != null) {
Robert Greenwalt0be1e982010-12-15 13:26:33 -0800705 Integer currentPid = new Integer(getCallingPid());
Robert Greenwalt42acef32009-08-12 16:08:25 -0700706 if (usedNetworkType != networkType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700707 NetworkStateTracker radio = mNetTrackers[networkType];
708 NetworkInfo ni = network.getNetworkInfo();
709
710 if (ni.isAvailable() == false) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800711 if (DBG) log("special network not available");
Robert Greenwalte32e8122010-12-29 14:35:21 -0800712 if (!TextUtils.equals(feature,Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
713 return Phone.APN_TYPE_NOT_AVAILABLE;
714 } else {
715 // else make the attempt anyway - probably giving REQUEST_STARTED below
716 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700717 }
718
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700719 synchronized(this) {
720 mFeatureUsers.add(f);
721 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
722 // this gets used for per-pid dns when connected
723 mNetRequestersPids[usedNetworkType].add(currentPid);
724 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700725 }
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700726
Robert Greenwaltf2102f72011-05-03 19:02:44 -0700727 int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
728
729 if (restoreTimer >= 0) {
730 mHandler.sendMessageDelayed(
731 mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer);
732 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700733
Robert Greenwalta64bf832009-08-19 20:19:33 -0700734 if ((ni.isConnectedOrConnecting() == true) &&
735 !network.isTeardownRequested()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -0700736 if (ni.isConnected() == true) {
737 // add the pid-specific dns
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -0700738 handleDnsConfigurationChange(networkType);
Wink Savilleed9c02b2010-12-03 12:01:38 -0800739 if (DBG) log("special network already active");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700740 return Phone.APN_ALREADY_ACTIVE;
741 }
Wink Savilleed9c02b2010-12-03 12:01:38 -0800742 if (DBG) log("special network already connecting");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700743 return Phone.APN_REQUEST_STARTED;
744 }
745
746 // check if the radio in play can make another contact
747 // assume if cannot for now
748
Wink Savilleed9c02b2010-12-03 12:01:38 -0800749 if (DBG) log("reconnecting to special network");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700750 network.reconnect();
751 return Phone.APN_REQUEST_STARTED;
752 } else {
Robert Greenwalt0be1e982010-12-15 13:26:33 -0800753 // need to remember this unsupported request so we respond appropriately on stop
754 synchronized(this) {
755 mFeatureUsers.add(f);
756 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
757 // this gets used for per-pid dns when connected
758 mNetRequestersPids[usedNetworkType].add(currentPid);
759 }
760 }
Robert Greenwalt02648a42010-05-18 10:52:51 -0700761 return -1;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700762 }
763 }
764 return Phone.APN_TYPE_NOT_AVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 }
766
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700767 // javadoc from interface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 public int stopUsingNetworkFeature(int networkType, String feature) {
Robert Greenwaltb8f16342009-10-06 17:52:40 -0700769 enforceChangePermission();
770
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700771 int pid = getCallingPid();
772 int uid = getCallingUid();
773
774 FeatureUser u = null;
775 boolean found = false;
776
777 synchronized(this) {
778 for (int i = 0; i < mFeatureUsers.size() ; i++) {
779 u = (FeatureUser)mFeatureUsers.get(i);
780 if (uid == u.mUid && pid == u.mPid &&
781 networkType == u.mNetworkType &&
782 TextUtils.equals(feature, u.mFeature)) {
783 found = true;
784 break;
785 }
786 }
787 }
788 if (found && u != null) {
789 // stop regardless of how many other time this proc had called start
790 return stopUsingNetworkFeature(u, true);
791 } else {
792 // none found!
Wink Savilleed9c02b2010-12-03 12:01:38 -0800793 if (DBG) log("ignoring stopUsingNetworkFeature - not a live request");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700794 return 1;
795 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700796 }
797
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700798 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
799 int networkType = u.mNetworkType;
800 String feature = u.mFeature;
801 int pid = u.mPid;
802 int uid = u.mUid;
803
804 NetworkStateTracker tracker = null;
805 boolean callTeardown = false; // used to carry our decision outside of sync block
806
Robert Greenwalt42acef32009-08-12 16:08:25 -0700807 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800808 log("stopUsingNetworkFeature for net " + networkType +
Robert Greenwalt42acef32009-08-12 16:08:25 -0700809 ": " + feature);
810 }
Robert Greenwaltb8f16342009-10-06 17:52:40 -0700811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
813 return -1;
814 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700815
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700816 // need to link the mFeatureUsers list with the mNetRequestersPids state in this
817 // sync block
818 synchronized(this) {
819 // check if this process still has an outstanding start request
820 if (!mFeatureUsers.contains(u)) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800821 if (DBG) log("ignoring - this process has no outstanding requests");
Robert Greenwalt42acef32009-08-12 16:08:25 -0700822 return 1;
823 }
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700824 u.unlinkDeathRecipient();
825 mFeatureUsers.remove(mFeatureUsers.indexOf(u));
826 // If we care about duplicate requests, check for that here.
827 //
828 // This is done to support the extension of a request - the app
829 // can request we start the network feature again and renew the
830 // auto-shutoff delay. Normal "stop" calls from the app though
831 // do not pay attention to duplicate requests - in effect the
832 // API does not refcount and a single stop will counter multiple starts.
833 if (ignoreDups == false) {
834 for (int i = 0; i < mFeatureUsers.size() ; i++) {
835 FeatureUser x = (FeatureUser)mFeatureUsers.get(i);
836 if (x.mUid == u.mUid && x.mPid == u.mPid &&
837 x.mNetworkType == u.mNetworkType &&
838 TextUtils.equals(x.mFeature, u.mFeature)) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800839 if (DBG) log("ignoring stopUsingNetworkFeature as dup is found");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700840 return 1;
841 }
842 }
Robert Greenwalt42acef32009-08-12 16:08:25 -0700843 }
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700844
845 // TODO - move to MobileDataStateTracker
846 int usedNetworkType = networkType;
847 if (networkType == ConnectivityManager.TYPE_MOBILE) {
Wink Saville9d7d6282011-03-12 14:52:01 -0800848 usedNetworkType = convertFeatureToNetworkType(feature);
849 if (usedNetworkType < 0) {
850 usedNetworkType = networkType;
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700851 }
852 }
853 tracker = mNetTrackers[usedNetworkType];
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700854 if (tracker == null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800855 if (DBG) log("ignoring - no known tracker for net type " + usedNetworkType);
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700856 return -1;
857 }
858 if (usedNetworkType != networkType) {
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700859 Integer currentPid = new Integer(pid);
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700860 mNetRequestersPids[usedNetworkType].remove(currentPid);
Robert Greenwalt421c72b2009-12-17 14:54:59 -0800861 reassessPidDns(pid, true);
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700862 if (mNetRequestersPids[usedNetworkType].size() != 0) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800863 if (DBG) log("not tearing down special network - " +
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700864 "others still using it");
865 return 1;
866 }
867 callTeardown = true;
Robert Greenwalt19b9ab42011-01-10 11:58:31 -0800868 } else {
869 if (DBG) log("not a known feature - dropping");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700870 }
871 }
Wink Savilleed9c02b2010-12-03 12:01:38 -0800872 if (DBG) log("Doing network teardown");
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -0700873 if (callTeardown) {
874 tracker.teardown();
Robert Greenwalt42acef32009-08-12 16:08:25 -0700875 return 1;
876 } else {
Robert Greenwalt02648a42010-05-18 10:52:51 -0700877 return -1;
Robert Greenwalt42acef32009-08-12 16:08:25 -0700878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 }
880
881 /**
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700882 * @deprecated use requestRouteToHostAddress instead
883 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 * Ensure that a network route exists to deliver traffic to the specified
885 * host via the specified network interface.
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700886 * @param networkType the type of the network over which traffic to the
887 * specified host is to be routed
888 * @param hostAddress the IP address of the host to which the route is
889 * desired
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 * @return {@code true} on success, {@code false} on failure
891 */
892 public boolean requestRouteToHost(int networkType, int hostAddress) {
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700893 InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
894
895 if (inetAddress == null) {
896 return false;
897 }
898
899 return requestRouteToHostAddress(networkType, inetAddress.getAddress());
900 }
901
902 /**
903 * Ensure that a network route exists to deliver traffic to the specified
904 * host via the specified network interface.
905 * @param networkType the type of the network over which traffic to the
906 * specified host is to be routed
907 * @param hostAddress the IP address of the host to which the route is
908 * desired
909 * @return {@code true} on success, {@code false} on failure
910 */
911 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 enforceChangePermission();
913 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
914 return false;
915 }
916 NetworkStateTracker tracker = mNetTrackers[networkType];
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700917
Robert Greenwalt5154ae762009-10-30 14:17:42 -0700918 if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
919 tracker.isTeardownRequested()) {
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700920 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800921 log("requestRouteToHostAddress on down network " +
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700922 "(" + networkType + ") - dropped");
Robert Greenwalt8206ff32009-09-10 15:06:20 -0700923 }
924 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 }
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700926 try {
Robert Greenwalt585ac0f2010-08-27 09:24:29 -0700927 InetAddress addr = InetAddress.getByAddress(hostAddress);
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700928 return addHostRoute(tracker, addr, 0);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700929 } catch (UnknownHostException e) {}
930 return false;
Irfan Sheriffd649c122010-06-09 15:39:36 -0700931 }
932
933 /**
934 * Ensure that a network route exists to deliver traffic to the specified
935 * host via the mobile data network.
936 * @param hostAddress the IP address of the host to which the route is desired,
937 * in network byte order.
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700938 * TODO - deprecate
Irfan Sheriffd649c122010-06-09 15:39:36 -0700939 * @return {@code true} on success, {@code false} on failure
940 */
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700941 private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress, int cycleCount) {
Irfan Sheriffd649c122010-06-09 15:39:36 -0700942 if (nt.getNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI) {
943 return false;
944 }
945
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700946 LinkProperties lp = nt.getLinkProperties();
947 if ((lp == null) || (hostAddress == null)) return false;
Irfan Sheriffd649c122010-06-09 15:39:36 -0700948
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700949 String interfaceName = lp.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -0700950 if (DBG) {
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700951 log("Requested host route to " + hostAddress + "(" + interfaceName + "), cycleCount=" +
952 cycleCount);
Irfan Sheriffd649c122010-06-09 15:39:36 -0700953 }
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700954 if (interfaceName == null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -0800955 if (DBG) loge("addHostRoute failed due to null interface name");
Irfan Sheriffd649c122010-06-09 15:39:36 -0700956 return false;
957 }
Robert Greenwaltf43396c2011-05-06 17:10:53 -0700958
959 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), hostAddress);
960 InetAddress gateway = null;
961 if (bestRoute != null) {
962 gateway = bestRoute.getGateway();
963 // if the best route is ourself, don't relf-reference, just add the host route
964 if (hostAddress.equals(gateway)) gateway = null;
965 }
966 if (gateway != null) {
967 if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
968 loge("Error adding hostroute - too much recursion");
969 return false;
970 }
971 if (!addHostRoute(nt, gateway, cycleCount+1)) return false;
972 }
973 return NetworkUtils.addHostRoute(interfaceName, hostAddress, gateway);
974 }
975
976 // TODO support the removal of single host routes. Keep a ref count of them so we
977 // aren't over-zealous
978 private boolean removeHostRoute(NetworkStateTracker nt, InetAddress hostAddress) {
979 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 }
981
982 /**
983 * @see ConnectivityManager#getBackgroundDataSetting()
984 */
985 public boolean getBackgroundDataSetting() {
Robert Greenwaltd825ea42010-12-29 16:15:02 -0800986 return mBackgroundDataEnabled.get();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 }
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 /**
990 * @see ConnectivityManager#setBackgroundDataSetting(boolean)
991 */
992 public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) {
993 mContext.enforceCallingOrSelfPermission(
994 android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
995 "ConnectivityService");
Robert Greenwalt86e9e552009-07-16 17:21:39 -0700996
Robert Greenwaltd825ea42010-12-29 16:15:02 -0800997 mBackgroundDataEnabled.set(allowBackgroundDataUsage);
998
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -0700999 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA,
1000 (allowBackgroundDataUsage ? ENABLED : DISABLED), 0));
1001 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001003 private void handleSetBackgroundData(boolean enabled) {
Robert Greenwaltdb4afae2011-02-25 13:44:09 -08001004 Settings.Secure.putInt(mContext.getContentResolver(),
1005 Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0);
1006 Intent broadcast = new Intent(
1007 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
1008 mContext.sendBroadcast(broadcast);
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001009 }
1010
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001011 /**
1012 * @see ConnectivityManager#getMobileDataEnabled()
1013 */
1014 public boolean getMobileDataEnabled() {
Wink Savillee7982682010-12-07 10:31:02 -08001015 // TODO: This detail should probably be in DataConnectionTracker's
1016 // which is where we store the value and maybe make this
1017 // asynchronous.
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001018 enforceAccessPermission();
1019 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
1020 Settings.Secure.MOBILE_DATA, 1) == 1;
Wink Savilleed9c02b2010-12-03 12:01:38 -08001021 if (DBG) log("getMobileDataEnabled returning " + retVal);
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001022 return retVal;
1023 }
1024
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001025 public void setDataDependency(int networkType, boolean met) {
1026 enforceChangePermission();
1027 if (DBG) {
1028 log("setDataDependency(" + networkType + ", " + met + ")");
1029 }
1030 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
1031 (met ? ENABLED : DISABLED), networkType));
1032 }
1033
1034 private void handleSetDependencyMet(int networkType, boolean met) {
1035 if (mNetTrackers[networkType] != null) {
1036 if (DBG) {
1037 log("handleSetDependencyMet(" + networkType + ", " + met + ")");
1038 }
1039 mNetTrackers[networkType].setDependencyMet(met);
1040 }
1041 }
1042
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001043 /**
1044 * @see ConnectivityManager#setMobileDataEnabled(boolean)
1045 */
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001046 public void setMobileDataEnabled(boolean enabled) {
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001047 enforceChangePermission();
Wink Savilleed9c02b2010-12-03 12:01:38 -08001048 if (DBG) log("setMobileDataEnabled(" + enabled + ")");
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001049
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001050 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001051 (enabled ? ENABLED : DISABLED), 0));
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001052 }
1053
1054 private void handleSetMobileData(boolean enabled) {
Wink Savillee7982682010-12-07 10:31:02 -08001055 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
1056 if (DBG) {
1057 Slog.d(TAG, mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001058 }
Wink Savillee7982682010-12-07 10:31:02 -08001059 mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled);
Robert Greenwaltc03fa502010-02-23 18:58:05 -08001060 }
1061 }
1062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 private void enforceAccessPermission() {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001064 mContext.enforceCallingOrSelfPermission(
1065 android.Manifest.permission.ACCESS_NETWORK_STATE,
1066 "ConnectivityService");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 }
1068
1069 private void enforceChangePermission() {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001070 mContext.enforceCallingOrSelfPermission(
1071 android.Manifest.permission.CHANGE_NETWORK_STATE,
1072 "ConnectivityService");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001073 }
1074
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001075 // TODO Make this a special check when it goes public
1076 private void enforceTetherChangePermission() {
1077 mContext.enforceCallingOrSelfPermission(
1078 android.Manifest.permission.CHANGE_NETWORK_STATE,
1079 "ConnectivityService");
1080 }
1081
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001082 private void enforceTetherAccessPermission() {
1083 mContext.enforceCallingOrSelfPermission(
1084 android.Manifest.permission.ACCESS_NETWORK_STATE,
1085 "ConnectivityService");
1086 }
1087
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001088 private void enforceConnectivityInternalPermission() {
1089 mContext.enforceCallingOrSelfPermission(
1090 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1091 "ConnectivityService");
1092 }
1093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 /**
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001095 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
1096 * network, we ignore it. If it is for the active network, we send out a
1097 * broadcast. But first, we check whether it might be possible to connect
1098 * to a different network.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 * @param info the {@code NetworkInfo} for the network
1100 */
1101 private void handleDisconnect(NetworkInfo info) {
1102
Robert Greenwalt42acef32009-08-12 16:08:25 -07001103 int prevNetType = info.getType();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104
Robert Greenwalt42acef32009-08-12 16:08:25 -07001105 mNetTrackers[prevNetType].setTeardownRequested(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 /*
1107 * If the disconnected network is not the active one, then don't report
1108 * this as a loss of connectivity. What probably happened is that we're
1109 * getting the disconnect for a network that we explicitly disabled
1110 * in accordance with network preference policies.
1111 */
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001112 if (!mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001113 List pids = mNetRequestersPids[prevNetType];
1114 for (int i = 0; i<pids.size(); i++) {
1115 Integer pid = (Integer)pids.get(i);
1116 // will remove them because the net's no longer connected
1117 // need to do this now as only now do we know the pids and
1118 // can properly null things that are no longer referenced.
1119 reassessPidDns(pid.intValue(), false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 }
1122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1124 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1125 if (info.isFailover()) {
1126 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1127 info.setFailover(false);
1128 }
1129 if (info.getReason() != null) {
1130 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1131 }
1132 if (info.getExtraInfo() != null) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001133 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1134 info.getExtraInfo());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001136
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001137 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001138 tryFailover(prevNetType);
1139 if (mActiveDefaultNetwork != -1) {
1140 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001141 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1142 } else {
Robert Greenwalt029be812010-09-20 18:01:43 -07001143 mDefaultInetConditionPublished = 0; // we're not connected anymore
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001144 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1145 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001146 }
Robert Greenwalt029be812010-09-20 18:01:43 -07001147 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001148 // do this before we broadcast the change
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001149 handleConnectivityChange(prevNetType);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001150
1151 sendStickyBroadcast(intent);
1152 /*
1153 * If the failover network is already connected, then immediately send
1154 * out a followup broadcast indicating successful failover
1155 */
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001156 if (mActiveDefaultNetwork != -1) {
1157 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001158 }
1159 }
1160
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001161 private void tryFailover(int prevNetType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001162 /*
Robert Greenwaltbff90182011-01-06 15:41:07 -08001163 * If this is a default network, check if other defaults are available.
1164 * Try to reconnect on all available and let them hash it out when
1165 * more than one connects.
Robert Greenwalt42acef32009-08-12 16:08:25 -07001166 */
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001167 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001168 if (mActiveDefaultNetwork == prevNetType) {
1169 mActiveDefaultNetwork = -1;
1170 }
1171
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001172 // don't signal a reconnect for anything lower or equal priority than our
1173 // current connected default
1174 // TODO - don't filter by priority now - nice optimization but risky
1175// int currentPriority = -1;
1176// if (mActiveDefaultNetwork != -1) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001177// currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority;
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001178// }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001179 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
Robert Greenwalt5154ae762009-10-30 14:17:42 -07001180 if (checkType == prevNetType) continue;
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001181 if (mNetConfigs[checkType] == null) continue;
1182 if (!mNetConfigs[checkType].isDefault()) continue;
Wink Saville9f7a0b22011-01-26 15:43:49 -08001183
1184// Enabling the isAvailable() optimization caused mobile to not get
1185// selected if it was in the middle of error handling. Specifically
1186// a moble connection that took 30 seconds to complete the DEACTIVATE_DATA_CALL
1187// would not be available and we wouldn't get connected to anything.
1188// So removing the isAvailable() optimization below for now. TODO: This
1189// optimization should work and we need to investigate why it doesn't work.
1190// This could be related to how DEACTIVATE_DATA_CALL is reporting its
1191// complete before it is really complete.
1192// if (!mNetTrackers[checkType].isAvailable()) continue;
1193
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001194// if (currentPriority >= mNetConfigs[checkType].mPriority) continue;
Robert Greenwalt42acef32009-08-12 16:08:25 -07001195
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001196 NetworkStateTracker checkTracker = mNetTrackers[checkType];
1197 NetworkInfo checkInfo = checkTracker.getNetworkInfo();
1198 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
1199 checkInfo.setFailover(true);
1200 checkTracker.reconnect();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001201 }
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001202 if (DBG) log("Attempting to switch to " + checkInfo.getTypeName());
Robert Greenwalt42acef32009-08-12 16:08:25 -07001203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 }
1206
1207 private void sendConnectedBroadcast(NetworkInfo info) {
Robert Greenwalt1e9aac22010-09-15 17:36:33 -07001208 sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION);
1209 }
1210
1211 private void sendInetConditionBroadcast(NetworkInfo info) {
1212 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1213 }
1214
1215 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1216 Intent intent = new Intent(bcastType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1218 if (info.isFailover()) {
1219 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1220 info.setFailover(false);
1221 }
1222 if (info.getReason() != null) {
1223 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1224 }
1225 if (info.getExtraInfo() != null) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001226 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1227 info.getExtraInfo());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 }
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001229 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001230 sendStickyBroadcast(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 }
1232
1233 /**
1234 * Called when an attempt to fail over to another network has failed.
1235 * @param info the {@link NetworkInfo} for the failed network
1236 */
1237 private void handleConnectionFailure(NetworkInfo info) {
1238 mNetTrackers[info.getType()].setTeardownRequested(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239
Robert Greenwalt42acef32009-08-12 16:08:25 -07001240 String reason = info.getReason();
1241 String extraInfo = info.getExtraInfo();
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001242
Robert Greenwalt572172b2010-10-08 16:35:52 -07001243 String reasonText;
1244 if (reason == null) {
1245 reasonText = ".";
1246 } else {
1247 reasonText = " (" + reason + ").";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001248 }
Wink Savilleed9c02b2010-12-03 12:01:38 -08001249 loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001250
1251 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1252 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1253 if (getActiveNetworkInfo() == null) {
1254 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1255 }
1256 if (reason != null) {
1257 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
1258 }
1259 if (extraInfo != null) {
1260 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
1261 }
1262 if (info.isFailover()) {
1263 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1264 info.setFailover(false);
1265 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001266
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001267 if (mNetConfigs[info.getType()].isDefault()) {
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001268 tryFailover(info.getType());
1269 if (mActiveDefaultNetwork != -1) {
1270 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001271 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1272 } else {
Robert Greenwalt029be812010-09-20 18:01:43 -07001273 mDefaultInetConditionPublished = 0;
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001274 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1275 }
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001276 }
Robert Greenwaltcc4b4012010-01-25 17:54:29 -08001277
Robert Greenwalt029be812010-09-20 18:01:43 -07001278 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001279 sendStickyBroadcast(intent);
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001280 /*
1281 * If the failover network is already connected, then immediately send
1282 * out a followup broadcast indicating successful failover
1283 */
Robert Greenwaltf21ef7d2011-01-11 13:56:33 -08001284 if (mActiveDefaultNetwork != -1) {
1285 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltda03c4e2010-01-20 19:29:41 -08001286 }
Mike Lockwood0f79b542009-08-14 14:18:49 -04001287 }
1288
1289 private void sendStickyBroadcast(Intent intent) {
1290 synchronized(this) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001291 if (!mSystemReady) {
1292 mInitialBroadcast = new Intent(intent);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001293 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001294 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1295 mContext.sendStickyBroadcast(intent);
Mike Lockwood0f79b542009-08-14 14:18:49 -04001296 }
1297 }
1298
1299 void systemReady() {
1300 synchronized(this) {
1301 mSystemReady = true;
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08001302 if (mInitialBroadcast != null) {
1303 mContext.sendStickyBroadcast(mInitialBroadcast);
1304 mInitialBroadcast = null;
Mike Lockwood0f79b542009-08-14 14:18:49 -04001305 }
1306 }
Robert Greenwalt434203a2010-10-11 16:00:27 -07001307 // load the global proxy at startup
1308 mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001309 }
1310
1311 private void handleConnect(NetworkInfo info) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001312 int type = info.getType();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001313
1314 // snapshot isFailover, because sendConnectedBroadcast() resets it
1315 boolean isFailover = info.isFailover();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001316 NetworkStateTracker thisNet = mNetTrackers[type];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001317
Robert Greenwalt42acef32009-08-12 16:08:25 -07001318 // if this is a default net and other default is running
1319 // kill the one not preferred
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001320 if (mNetConfigs[type].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001321 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
1322 if ((type != mNetworkPreference &&
Wink Saville975c8482011-04-07 14:23:45 -07001323 mNetConfigs[mActiveDefaultNetwork].priority >
1324 mNetConfigs[type].priority) ||
Robert Greenwalt42acef32009-08-12 16:08:25 -07001325 mNetworkPreference == mActiveDefaultNetwork) {
1326 // don't accept this one
Wink Savilleed9c02b2010-12-03 12:01:38 -08001327 if (DBG) {
1328 log("Not broadcasting CONNECT_ACTION " +
Robert Greenwalt42acef32009-08-12 16:08:25 -07001329 "to torn down network " + info.getTypeName());
Wink Savilleed9c02b2010-12-03 12:01:38 -08001330 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001331 teardown(thisNet);
1332 return;
1333 } else {
1334 // tear down the other
1335 NetworkStateTracker otherNet =
1336 mNetTrackers[mActiveDefaultNetwork];
Wink Savilleed9c02b2010-12-03 12:01:38 -08001337 if (DBG) {
1338 log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
Robert Greenwalt42acef32009-08-12 16:08:25 -07001339 " teardown");
Wink Savilleed9c02b2010-12-03 12:01:38 -08001340 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001341 if (!teardown(otherNet)) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001342 loge("Network declined teardown request");
Robert Greenwalt42acef32009-08-12 16:08:25 -07001343 return;
1344 }
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001345 }
1346 }
1347 synchronized (ConnectivityService.this) {
1348 // have a new default network, release the transition wakelock in a second
1349 // if it's held. The second pause is to allow apps to reconnect over the
1350 // new network
1351 if (mNetTransitionWakeLock.isHeld()) {
1352 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltf3331232010-09-24 14:32:21 -07001353 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001354 mNetTransitionWakeLockSerialNumber, 0),
1355 1000);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001356 }
1357 }
1358 mActiveDefaultNetwork = type;
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001359 // this will cause us to come up initially as unconnected and switching
1360 // to connected after our normal pause unless somebody reports us as reall
1361 // disconnected
1362 mDefaultInetConditionPublished = 0;
1363 mDefaultConnectionSequence++;
1364 mInetConditionChangeInFlight = false;
1365 // Don't do this - if we never sign in stay, grey
1366 //reportNetworkCondition(mActiveDefaultNetwork, 100);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 thisNet.setTeardownRequested(false);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001369 updateNetworkSettings(thisNet);
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001370 handleConnectivityChange(type);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001371 sendConnectedBroadcast(info);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 }
1373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 /**
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001375 * After a change in the connectivity state of a network. We're mainly
1376 * concerned with making sure that the list of DNS servers is set up
1377 * according to which networks are connected, and ensuring that the
1378 * right routing table entries exist.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 */
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001380 private void handleConnectivityChange(int netType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 /*
Robert Greenwalt42acef32009-08-12 16:08:25 -07001382 * If a non-default network is enabled, add the host routes that
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001383 * will allow it's DNS servers to be accessed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 */
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001385 handleDnsConfigurationChange(netType);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001386
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001387 if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001388 if (mNetConfigs[netType].isDefault()) {
Robert Greenwalt434203a2010-10-11 16:00:27 -07001389 handleApplyDefaultProxy(netType);
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001390 addDefaultRoute(mNetTrackers[netType]);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001391 } else {
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001392 addPrivateDnsRoutes(mNetTrackers[netType]);
1393 }
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001394
1395 /** Notify TetheringService if interface name has been changed. */
1396 if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
1397 Phone.REASON_LINK_PROPERTIES_CHANGED)) {
1398 handleTetherIfaceChange(netType);
1399 }
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001400 } else {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001401 if (mNetConfigs[netType].isDefault()) {
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001402 removeDefaultRoute(mNetTrackers[netType]);
1403 } else {
1404 removePrivateDnsRoutes(mNetTrackers[netType]);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 }
1407 }
1408
Irfan Sheriffd649c122010-06-09 15:39:36 -07001409 private void addPrivateDnsRoutes(NetworkStateTracker nt) {
Irfan Sheriffd649c122010-06-09 15:39:36 -07001410 boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet();
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001411 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001412 if (p == null) return;
1413 String interfaceName = p.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -07001414
1415 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001416 log("addPrivateDnsRoutes for " + nt +
Irfan Sheriffd649c122010-06-09 15:39:36 -07001417 "(" + interfaceName + ") - mPrivateDnsRouteSet = " + privateDnsRouteSet);
1418 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001419 if (interfaceName != null && !privateDnsRouteSet) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001420 Collection<InetAddress> dnsList = p.getDnses();
1421 for (InetAddress dns : dnsList) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001422 if (DBG) log(" adding " + dns);
Robert Greenwaltf43396c2011-05-06 17:10:53 -07001423 addHostRoute(nt, dns, 0);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001424 }
1425 nt.privateDnsRouteSet(true);
1426 }
1427 }
1428
1429 private void removePrivateDnsRoutes(NetworkStateTracker nt) {
1430 // TODO - we should do this explicitly but the NetUtils api doesnt
1431 // support this yet - must remove all. No worse than before
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001432 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001433 if (p == null) return;
1434 String interfaceName = p.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -07001435 boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet();
1436 if (interfaceName != null && privateDnsRouteSet) {
1437 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001438 log("removePrivateDnsRoutes for " + nt.getNetworkInfo().getTypeName() +
Irfan Sheriffd649c122010-06-09 15:39:36 -07001439 " (" + interfaceName + ")");
1440 }
1441 NetworkUtils.removeHostRoutes(interfaceName);
1442 nt.privateDnsRouteSet(false);
1443 }
1444 }
1445
Irfan Sheriffd649c122010-06-09 15:39:36 -07001446
1447 private void addDefaultRoute(NetworkStateTracker nt) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001448 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001449 if (p == null) return;
1450 String interfaceName = p.getInterfaceName();
Robert Greenwalt992564e2011-02-09 13:56:06 -08001451 if (TextUtils.isEmpty(interfaceName)) return;
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001452 for (RouteInfo route : p.getRoutes()) {
Irfan Sheriffd649c122010-06-09 15:39:36 -07001453
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001454 //TODO - handle non-default routes
1455 if (route.isDefaultRoute()) {
1456 InetAddress gateway = route.getGateway();
Robert Greenwaltf43396c2011-05-06 17:10:53 -07001457 if (addHostRoute(nt, gateway, 0) &&
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001458 NetworkUtils.addDefaultRoute(interfaceName, gateway)) {
1459 if (DBG) {
1460 NetworkInfo networkInfo = nt.getNetworkInfo();
1461 log("addDefaultRoute for " + networkInfo.getTypeName() +
1462 " (" + interfaceName + "), GatewayAddr=" +
1463 gateway.getHostAddress());
1464 }
Robert Greenwaltedcb4f92011-03-22 18:47:42 -07001465 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001466 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001467 }
1468 }
1469
1470
1471 public void removeDefaultRoute(NetworkStateTracker nt) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001472 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001473 if (p == null) return;
1474 String interfaceName = p.getInterfaceName();
Irfan Sheriffd649c122010-06-09 15:39:36 -07001475
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001476 if (interfaceName != null) {
Robert Greenwaltedcb4f92011-03-22 18:47:42 -07001477 if (NetworkUtils.removeDefaultRoute(interfaceName) >= 0) {
1478 if (DBG) {
1479 NetworkInfo networkInfo = nt.getNetworkInfo();
1480 log("removeDefaultRoute for " + networkInfo.getTypeName() + " (" +
1481 interfaceName + ")");
1482 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001483 }
Irfan Sheriffd649c122010-06-09 15:39:36 -07001484 }
1485 }
1486
1487 /**
1488 * Reads the network specific TCP buffer sizes from SystemProperties
1489 * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
1490 * wide use
1491 */
1492 public void updateNetworkSettings(NetworkStateTracker nt) {
1493 String key = nt.getTcpBufferSizesPropName();
1494 String bufferSizes = SystemProperties.get(key);
1495
1496 if (bufferSizes.length() == 0) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001497 loge(key + " not found in system properties. Using defaults");
Irfan Sheriffd649c122010-06-09 15:39:36 -07001498
1499 // Setting to default values so we won't be stuck to previous values
1500 key = "net.tcp.buffersize.default";
1501 bufferSizes = SystemProperties.get(key);
1502 }
1503
1504 // Set values in kernel
1505 if (bufferSizes.length() != 0) {
1506 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001507 log("Setting TCP values: [" + bufferSizes
Irfan Sheriffd649c122010-06-09 15:39:36 -07001508 + "] which comes from [" + key + "]");
1509 }
1510 setBufferSize(bufferSizes);
1511 }
1512 }
1513
1514 /**
1515 * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max]
1516 * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem
1517 *
1518 * @param bufferSizes in the format of "readMin, readInitial, readMax,
1519 * writeMin, writeInitial, writeMax"
1520 */
1521 private void setBufferSize(String bufferSizes) {
1522 try {
1523 String[] values = bufferSizes.split(",");
1524
1525 if (values.length == 6) {
1526 final String prefix = "/sys/kernel/ipv4/tcp_";
1527 stringToFile(prefix + "rmem_min", values[0]);
1528 stringToFile(prefix + "rmem_def", values[1]);
1529 stringToFile(prefix + "rmem_max", values[2]);
1530 stringToFile(prefix + "wmem_min", values[3]);
1531 stringToFile(prefix + "wmem_def", values[4]);
1532 stringToFile(prefix + "wmem_max", values[5]);
1533 } else {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001534 loge("Invalid buffersize string: " + bufferSizes);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001535 }
1536 } catch (IOException e) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001537 loge("Can't set tcp buffer sizes:" + e);
Irfan Sheriffd649c122010-06-09 15:39:36 -07001538 }
1539 }
1540
1541 /**
1542 * Writes string to file. Basically same as "echo -n $string > $filename"
1543 *
1544 * @param filename
1545 * @param string
1546 * @throws IOException
1547 */
1548 private void stringToFile(String filename, String string) throws IOException {
1549 FileWriter out = new FileWriter(filename);
1550 try {
1551 out.write(string);
1552 } finally {
1553 out.close();
1554 }
1555 }
1556
1557
Robert Greenwalt42acef32009-08-12 16:08:25 -07001558 /**
1559 * Adjust the per-process dns entries (net.dns<x>.<pid>) based
1560 * on the highest priority active net which this process requested.
1561 * If there aren't any, clear it out
1562 */
1563 private void reassessPidDns(int myPid, boolean doBump)
1564 {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001565 if (DBG) log("reassessPidDns for pid " + myPid);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001566 for(int i : mPriorityList) {
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001567 if (mNetConfigs[i].isDefault()) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001568 continue;
1569 }
1570 NetworkStateTracker nt = mNetTrackers[i];
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001571 if (nt.getNetworkInfo().isConnected() &&
1572 !nt.isTeardownRequested()) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001573 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001574 if (p == null) continue;
Robert Greenwalt42acef32009-08-12 16:08:25 -07001575 List pids = mNetRequestersPids[i];
1576 for (int j=0; j<pids.size(); j++) {
1577 Integer pid = (Integer)pids.get(j);
1578 if (pid.intValue() == myPid) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001579 Collection<InetAddress> dnses = p.getDnses();
1580 writePidDns(dnses, myPid);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001581 if (doBump) {
1582 bumpDns();
1583 }
1584 return;
1585 }
1586 }
1587 }
1588 }
1589 // nothing found - delete
1590 for (int i = 1; ; i++) {
1591 String prop = "net.dns" + i + "." + myPid;
1592 if (SystemProperties.get(prop).length() == 0) {
1593 if (doBump) {
1594 bumpDns();
1595 }
1596 return;
1597 }
1598 SystemProperties.set(prop, "");
1599 }
1600 }
1601
Robert Greenwalt10398722010-12-17 15:20:36 -08001602 // return true if results in a change
1603 private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001604 int j = 1;
Robert Greenwalt10398722010-12-17 15:20:36 -08001605 boolean changed = false;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001606 for (InetAddress dns : dnses) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001607 String dnsString = dns.getHostAddress();
1608 if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
1609 changed = true;
1610 SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
1611 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001612 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001613 return changed;
Robert Greenwalt42acef32009-08-12 16:08:25 -07001614 }
1615
1616 private void bumpDns() {
1617 /*
1618 * Bump the property that tells the name resolver library to reread
1619 * the DNS server list from the properties.
1620 */
1621 String propVal = SystemProperties.get("net.dnschange");
1622 int n = 0;
1623 if (propVal.length() != 0) {
1624 try {
1625 n = Integer.parseInt(propVal);
1626 } catch (NumberFormatException e) {}
1627 }
1628 SystemProperties.set("net.dnschange", "" + (n+1));
Robert Greenwalt03595d02010-11-02 14:08:23 -07001629 /*
1630 * Tell the VMs to toss their DNS caches
1631 */
1632 Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
1633 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Stan Chesnutt3d1db862011-01-05 17:14:03 -08001634 /*
1635 * Connectivity events can happen before boot has completed ...
1636 */
1637 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt03595d02010-11-02 14:08:23 -07001638 mContext.sendBroadcast(intent);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001639 }
1640
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001641 private void handleDnsConfigurationChange(int netType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001642 // add default net's dns entries
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001643 NetworkStateTracker nt = mNetTrackers[netType];
1644 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001645 LinkProperties p = nt.getLinkProperties();
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001646 if (p == null) return;
1647 Collection<InetAddress> dnses = p.getDnses();
Robert Greenwalt10398722010-12-17 15:20:36 -08001648 boolean changed = false;
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001649 if (mNetConfigs[netType].isDefault()) {
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001650 int j = 1;
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001651 if (dnses.size() == 0 && mDefaultDns != null) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001652 String dnsString = mDefaultDns.getHostAddress();
1653 if (!dnsString.equals(SystemProperties.get("net.dns1"))) {
1654 if (DBG) {
1655 log("no dns provided - using " + dnsString);
1656 }
1657 changed = true;
1658 SystemProperties.set("net.dns1", dnsString);
Robert Greenwalt42acef32009-08-12 16:08:25 -07001659 }
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001660 j++;
1661 } else {
1662 for (InetAddress dns : dnses) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001663 String dnsString = dns.getHostAddress();
1664 if (!changed && dnsString.equals(SystemProperties.get("net.dns" + j))) {
1665 j++;
1666 continue;
1667 }
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001668 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001669 log("adding dns " + dns + " for " +
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001670 nt.getNetworkInfo().getTypeName());
1671 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001672 changed = true;
1673 SystemProperties.set("net.dns" + j++, dnsString);
Robert Greenwalte90aa5e2010-09-01 11:34:05 -07001674 }
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001675 }
1676 for (int k=j ; k<mNumDnsEntries; k++) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001677 if (changed || !TextUtils.isEmpty(SystemProperties.get("net.dns" + k))) {
1678 if (DBG) log("erasing net.dns" + k);
1679 changed = true;
1680 SystemProperties.set("net.dns" + k, "");
1681 }
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001682 }
1683 mNumDnsEntries = j;
1684 } else {
1685 // set per-pid dns for attached secondary nets
1686 List pids = mNetRequestersPids[netType];
1687 for (int y=0; y< pids.size(); y++) {
1688 Integer pid = (Integer)pids.get(y);
Robert Greenwalt10398722010-12-17 15:20:36 -08001689 changed = writePidDns(dnses, pid.intValue());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 }
1691 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001692 if (changed) bumpDns();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 }
Robert Greenwalt42acef32009-08-12 16:08:25 -07001694 }
1695
Robert Greenwaltf2102f72011-05-03 19:02:44 -07001696 private int getRestoreDefaultNetworkDelay(int networkType) {
Robert Greenwalt42acef32009-08-12 16:08:25 -07001697 String restoreDefaultNetworkDelayStr = SystemProperties.get(
1698 NETWORK_RESTORE_DELAY_PROP_NAME);
1699 if(restoreDefaultNetworkDelayStr != null &&
1700 restoreDefaultNetworkDelayStr.length() != 0) {
1701 try {
1702 return Integer.valueOf(restoreDefaultNetworkDelayStr);
1703 } catch (NumberFormatException e) {
1704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 }
Robert Greenwaltf2102f72011-05-03 19:02:44 -07001706 // if the system property isn't set, use the value for the apn type
1707 int ret = RESTORE_DEFAULT_NETWORK_DELAY;
1708
1709 if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
1710 (mNetConfigs[networkType] != null)) {
1711 ret = mNetConfigs[networkType].restoreTime;
1712 }
1713 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 }
1715
1716 @Override
1717 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001718 if (mContext.checkCallingOrSelfPermission(
1719 android.Manifest.permission.DUMP)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 != PackageManager.PERMISSION_GRANTED) {
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001721 pw.println("Permission Denial: can't dump ConnectivityService " +
1722 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1723 Binder.getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 return;
1725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 pw.println();
1727 for (NetworkStateTracker nst : mNetTrackers) {
Robert Greenwaltb9285352009-12-21 18:24:07 -08001728 if (nst != null) {
1729 if (nst.getNetworkInfo().isConnected()) {
1730 pw.println("Active network: " + nst.getNetworkInfo().
1731 getTypeName());
1732 }
1733 pw.println(nst.getNetworkInfo());
1734 pw.println(nst);
1735 pw.println();
Robert Greenwalt42acef32009-08-12 16:08:25 -07001736 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001737 }
Robert Greenwaltb9285352009-12-21 18:24:07 -08001738
1739 pw.println("Network Requester Pids:");
1740 for (int net : mPriorityList) {
1741 String pidString = net + ": ";
1742 for (Object pid : mNetRequestersPids[net]) {
1743 pidString = pidString + pid.toString() + ", ";
1744 }
1745 pw.println(pidString);
1746 }
1747 pw.println();
1748
1749 pw.println("FeatureUsers:");
1750 for (Object requester : mFeatureUsers) {
1751 pw.println(requester.toString());
1752 }
1753 pw.println();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001754
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001755 synchronized (this) {
1756 pw.println("NetworkTranstionWakeLock is currently " +
1757 (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held.");
1758 pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy);
1759 }
1760 pw.println();
1761
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001762 mTethering.dump(fd, pw, args);
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -07001763
1764 if (mInetLog != null) {
1765 pw.println();
1766 pw.println("Inet condition reports:");
1767 for(int i = 0; i < mInetLog.size(); i++) {
1768 pw.println(mInetLog.get(i));
1769 }
1770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 }
1772
Robert Greenwalt42acef32009-08-12 16:08:25 -07001773 // must be stateless - things change under us.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 private class MyHandler extends Handler {
Wink Savillebb08caf2010-09-02 19:23:52 -07001775 public MyHandler(Looper looper) {
1776 super(looper);
1777 }
1778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 @Override
1780 public void handleMessage(Message msg) {
1781 NetworkInfo info;
1782 switch (msg.what) {
1783 case NetworkStateTracker.EVENT_STATE_CHANGED:
1784 info = (NetworkInfo) msg.obj;
Robert Greenwalt511288a2009-12-07 11:33:18 -08001785 int type = info.getType();
1786 NetworkInfo.State state = info.getState();
Robert Greenwalt511288a2009-12-07 11:33:18 -08001787
Wink Savilleed9c02b2010-12-03 12:01:38 -08001788 if (DBG) log("ConnectivityChange for " +
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001789 info.getTypeName() + ": " +
Robert Greenwalt511288a2009-12-07 11:33:18 -08001790 state + "/" + info.getDetailedState());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791
1792 // Connectivity state changed:
1793 // [31-13] Reserved for future use
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001794 // [12-9] Network subtype (for mobile network, as defined
1795 // by TelephonyManager)
1796 // [8-3] Detailed state ordinal (as defined by
1797 // NetworkInfo.DetailedState)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 // [2-0] Network type (as defined by ConnectivityManager)
1799 int eventLogParam = (info.getType() & 0x7) |
1800 ((info.getDetailedState().ordinal() & 0x3f) << 3) |
1801 (info.getSubtype() << 9);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001802 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001803 eventLogParam);
1804
1805 if (info.getDetailedState() ==
1806 NetworkInfo.DetailedState.FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001807 handleConnectionFailure(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001808 } else if (state == NetworkInfo.State.DISCONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 handleDisconnect(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001810 } else if (state == NetworkInfo.State.SUSPENDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 // TODO: need to think this over.
Robert Greenwalt86e9e552009-07-16 17:21:39 -07001812 // the logic here is, handle SUSPENDED the same as
1813 // DISCONNECTED. The only difference being we are
1814 // broadcasting an intent with NetworkInfo that's
1815 // suspended. This allows the applications an
1816 // opportunity to handle DISCONNECTED and SUSPENDED
1817 // differently, or not.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 handleDisconnect(info);
Robert Greenwalt511288a2009-12-07 11:33:18 -08001819 } else if (state == NetworkInfo.State.CONNECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 handleConnect(info);
1821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
Robert Greenwaltc76b8fa2010-07-23 15:46:26 -07001824 info = (NetworkInfo) msg.obj;
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001825 handleConnectivityChange(info.getType());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001826 break;
Robert Greenwaltf3331232010-09-24 14:32:21 -07001827 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001828 String causedBy = null;
1829 synchronized (ConnectivityService.this) {
1830 if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
1831 mNetTransitionWakeLock.isHeld()) {
1832 mNetTransitionWakeLock.release();
1833 causedBy = mNetTransitionWakeLockCausedBy;
1834 }
1835 }
1836 if (causedBy != null) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08001837 log("NetTransition Wakelock for " + causedBy + " released by timeout");
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001838 }
Robert Greenwalt057d5e92010-09-09 14:05:10 -07001839 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001840 case EVENT_RESTORE_DEFAULT_NETWORK:
Robert Greenwalt9c75d4a2009-09-27 17:27:04 -07001841 FeatureUser u = (FeatureUser)msg.obj;
1842 u.expire();
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001843 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001844 case EVENT_INET_CONDITION_CHANGE:
1845 {
1846 int netType = msg.arg1;
1847 int condition = msg.arg2;
1848 handleInetConditionChange(netType, condition);
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001849 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001850 }
1851 case EVENT_INET_CONDITION_HOLD_END:
1852 {
1853 int netType = msg.arg1;
1854 int sequence = msg.arg2;
1855 handleInetConditionHoldEnd(netType, sequence);
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001856 break;
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07001857 }
1858 case EVENT_SET_NETWORK_PREFERENCE:
1859 {
1860 int preference = msg.arg1;
1861 handleSetNetworkPreference(preference);
1862 break;
1863 }
1864 case EVENT_SET_BACKGROUND_DATA:
1865 {
1866 boolean enabled = (msg.arg1 == ENABLED);
1867 handleSetBackgroundData(enabled);
1868 break;
1869 }
1870 case EVENT_SET_MOBILE_DATA:
1871 {
1872 boolean enabled = (msg.arg1 == ENABLED);
1873 handleSetMobileData(enabled);
1874 break;
1875 }
Robert Greenwalt434203a2010-10-11 16:00:27 -07001876 case EVENT_APPLY_GLOBAL_HTTP_PROXY:
1877 {
1878 handleDeprecatedGlobalHttpProxy();
Robert Greenwaltd55a6b42011-03-25 13:09:25 -07001879 break;
1880 }
1881 case EVENT_SET_DEPENDENCY_MET:
1882 {
1883 boolean met = (msg.arg1 == ENABLED);
1884 handleSetDependencyMet(msg.arg2, met);
1885 break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 }
1888 }
1889 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001890
1891 // javadoc from interface
Robert Greenwalt5a735062010-03-02 17:25:02 -08001892 public int tether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001893 enforceTetherChangePermission();
Robert Greenwalt5a735062010-03-02 17:25:02 -08001894
1895 if (isTetheringSupported()) {
1896 return mTethering.tether(iface);
1897 } else {
1898 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1899 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001900 }
1901
1902 // javadoc from interface
Robert Greenwalt5a735062010-03-02 17:25:02 -08001903 public int untether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001904 enforceTetherChangePermission();
Robert Greenwalt5a735062010-03-02 17:25:02 -08001905
1906 if (isTetheringSupported()) {
1907 return mTethering.untether(iface);
1908 } else {
1909 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1910 }
1911 }
1912
1913 // javadoc from interface
1914 public int getLastTetherError(String iface) {
1915 enforceTetherAccessPermission();
1916
1917 if (isTetheringSupported()) {
1918 return mTethering.getLastTetherError(iface);
1919 } else {
1920 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
1921 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001922 }
1923
1924 // TODO - proper iface API for selection by property, inspection, etc
1925 public String[] getTetherableUsbRegexs() {
1926 enforceTetherAccessPermission();
1927 if (isTetheringSupported()) {
1928 return mTethering.getTetherableUsbRegexs();
1929 } else {
1930 return new String[0];
1931 }
1932 }
1933
1934 public String[] getTetherableWifiRegexs() {
1935 enforceTetherAccessPermission();
1936 if (isTetheringSupported()) {
1937 return mTethering.getTetherableWifiRegexs();
1938 } else {
1939 return new String[0];
1940 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001941 }
1942
Danica Chang6fdd0c62010-08-11 14:54:43 -07001943 public String[] getTetherableBluetoothRegexs() {
1944 enforceTetherAccessPermission();
1945 if (isTetheringSupported()) {
1946 return mTethering.getTetherableBluetoothRegexs();
1947 } else {
1948 return new String[0];
1949 }
1950 }
1951
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001952 // TODO - move iface listing, queries, etc to new module
1953 // javadoc from interface
1954 public String[] getTetherableIfaces() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001955 enforceTetherAccessPermission();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001956 return mTethering.getTetherableIfaces();
1957 }
1958
1959 public String[] getTetheredIfaces() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001960 enforceTetherAccessPermission();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001961 return mTethering.getTetheredIfaces();
1962 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001963
Robert Greenwalt5a735062010-03-02 17:25:02 -08001964 public String[] getTetheringErroredIfaces() {
1965 enforceTetherAccessPermission();
1966 return mTethering.getErroredIfaces();
1967 }
1968
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001969 // if ro.tether.denied = true we default to no tethering
1970 // gservices could set the secure setting to 1 though to enable it on a build where it
1971 // had previously been turned off.
1972 public boolean isTetheringSupported() {
1973 enforceTetherAccessPermission();
1974 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001975 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
1976 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
1977 return tetherEnabledInSettings && mTetheringConfigValid;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001978 }
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001979
1980 // An API NetworkStateTrackers can call when they lose their network.
1981 // This will automatically be cleared after X seconds or a network becomes CONNECTED,
1982 // whichever happens first. The timer is started by the first caller and not
1983 // restarted by subsequent callers.
1984 public void requestNetworkTransitionWakelock(String forWhom) {
1985 enforceConnectivityInternalPermission();
1986 synchronized (this) {
1987 if (mNetTransitionWakeLock.isHeld()) return;
1988 mNetTransitionWakeLockSerialNumber++;
1989 mNetTransitionWakeLock.acquire();
1990 mNetTransitionWakeLockCausedBy = forWhom;
1991 }
1992 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltf3331232010-09-24 14:32:21 -07001993 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt14f2ef42010-06-15 12:19:37 -07001994 mNetTransitionWakeLockSerialNumber, 0),
1995 mNetTransitionWakeLockTimeout);
1996 return;
1997 }
Robert Greenwaltca4306c2010-09-09 13:15:32 -07001998
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07001999 // 100 percent is full good, 0 is full bad.
2000 public void reportInetCondition(int networkType, int percentage) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002001 if (DBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")");
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07002002 mContext.enforceCallingOrSelfPermission(
2003 android.Manifest.permission.STATUS_BAR,
2004 "ConnectivityService");
2005
Robert Greenwalt4e8dfef2010-09-20 14:35:25 -07002006 if (DBG) {
2007 int pid = getCallingPid();
2008 int uid = getCallingUid();
2009 String s = pid + "(" + uid + ") reports inet is " +
2010 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
2011 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
2012 mInetLog.add(s);
2013 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
2014 mInetLog.remove(0);
2015 }
2016 }
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07002017 mHandler.sendMessage(mHandler.obtainMessage(
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002018 EVENT_INET_CONDITION_CHANGE, networkType, percentage));
2019 }
2020
2021 private void handleInetConditionChange(int netType, int condition) {
2022 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002023 log("Inet connectivity change, net=" +
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002024 netType + ", condition=" + condition +
2025 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
2026 }
2027 if (mActiveDefaultNetwork == -1) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002028 if (DBG) log("no active default network - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002029 return;
2030 }
2031 if (mActiveDefaultNetwork != netType) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002032 if (DBG) log("given net not default - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002033 return;
2034 }
2035 mDefaultInetCondition = condition;
2036 int delay;
2037 if (mInetConditionChangeInFlight == false) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002038 if (DBG) log("starting a change hold");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002039 // setup a new hold to debounce this
2040 if (mDefaultInetCondition > 50) {
2041 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2042 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
2043 } else {
2044 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2045 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
2046 }
2047 mInetConditionChangeInFlight = true;
2048 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
2049 mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
2050 } else {
2051 // we've set the new condition, when this hold ends that will get
2052 // picked up
Wink Savilleed9c02b2010-12-03 12:01:38 -08002053 if (DBG) log("currently in hold - not setting new end evt");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002054 }
2055 }
2056
2057 private void handleInetConditionHoldEnd(int netType, int sequence) {
2058 if (DBG) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002059 log("Inet hold end, net=" + netType +
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002060 ", condition =" + mDefaultInetCondition +
2061 ", published condition =" + mDefaultInetConditionPublished);
2062 }
2063 mInetConditionChangeInFlight = false;
2064
2065 if (mActiveDefaultNetwork == -1) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002066 if (DBG) log("no active default network - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002067 return;
2068 }
2069 if (mDefaultConnectionSequence != sequence) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002070 if (DBG) log("event hold for obsolete network - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002071 return;
2072 }
2073 if (mDefaultInetConditionPublished == mDefaultInetCondition) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002074 if (DBG) log("no change in condition - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002075 return;
2076 }
2077 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
2078 if (networkInfo.isConnected() == false) {
Wink Savilleed9c02b2010-12-03 12:01:38 -08002079 if (DBG) log("default network not connected - aborting");
Robert Greenwalt8dcc28b2010-09-23 10:05:56 -07002080 return;
2081 }
2082 mDefaultInetConditionPublished = mDefaultInetCondition;
2083 sendInetConditionBroadcast(networkInfo);
2084 return;
Robert Greenwaltd7085fc2010-09-08 15:24:47 -07002085 }
Robert Greenwalt434203a2010-10-11 16:00:27 -07002086
2087 public synchronized ProxyProperties getProxy() {
2088 if (mGlobalProxy != null) return mGlobalProxy;
2089 if (mDefaultProxy != null) return mDefaultProxy;
2090 return null;
2091 }
2092
2093 public void setGlobalProxy(ProxyProperties proxyProperties) {
2094 enforceChangePermission();
2095 synchronized (mGlobalProxyLock) {
2096 if (proxyProperties == mGlobalProxy) return;
2097 if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
2098 if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
2099
2100 String host = "";
2101 int port = 0;
2102 String exclList = "";
2103 if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) {
2104 mGlobalProxy = new ProxyProperties(proxyProperties);
2105 host = mGlobalProxy.getHost();
2106 port = mGlobalProxy.getPort();
2107 exclList = mGlobalProxy.getExclusionList();
2108 } else {
2109 mGlobalProxy = null;
2110 }
2111 ContentResolver res = mContext.getContentResolver();
2112 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host);
2113 Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port);
Robert Greenwaltb7090d62010-12-02 11:31:00 -08002114 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
Robert Greenwalt434203a2010-10-11 16:00:27 -07002115 exclList);
2116 }
2117
2118 if (mGlobalProxy == null) {
2119 proxyProperties = mDefaultProxy;
2120 }
2121 sendProxyBroadcast(proxyProperties);
2122 }
2123
Robert Greenwaltb7090d62010-12-02 11:31:00 -08002124 private void loadGlobalProxy() {
2125 ContentResolver res = mContext.getContentResolver();
2126 String host = Settings.Secure.getString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST);
2127 int port = Settings.Secure.getInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, 0);
2128 String exclList = Settings.Secure.getString(res,
2129 Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
2130 if (!TextUtils.isEmpty(host)) {
2131 ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList);
2132 synchronized (mGlobalProxyLock) {
2133 mGlobalProxy = proxyProperties;
2134 }
2135 }
2136 }
2137
Robert Greenwalt434203a2010-10-11 16:00:27 -07002138 public ProxyProperties getGlobalProxy() {
2139 synchronized (mGlobalProxyLock) {
2140 return mGlobalProxy;
2141 }
2142 }
2143
2144 private void handleApplyDefaultProxy(int type) {
2145 // check if new default - push it out to all VM if so
2146 ProxyProperties proxy = mNetTrackers[type].getLinkProperties().getHttpProxy();
2147 synchronized (this) {
2148 if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
2149 if (mDefaultProxy == proxy) return;
2150 if (!TextUtils.isEmpty(proxy.getHost())) {
2151 mDefaultProxy = proxy;
2152 } else {
2153 mDefaultProxy = null;
2154 }
2155 }
Wink Savilleed9c02b2010-12-03 12:01:38 -08002156 if (DBG) log("changing default proxy to " + proxy);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002157 if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return;
2158 if (mGlobalProxy != null) return;
2159 sendProxyBroadcast(proxy);
2160 }
2161
2162 private void handleDeprecatedGlobalHttpProxy() {
2163 String proxy = Settings.Secure.getString(mContext.getContentResolver(),
2164 Settings.Secure.HTTP_PROXY);
2165 if (!TextUtils.isEmpty(proxy)) {
2166 String data[] = proxy.split(":");
2167 String proxyHost = data[0];
2168 int proxyPort = 8080;
2169 if (data.length > 1) {
2170 try {
2171 proxyPort = Integer.parseInt(data[1]);
2172 } catch (NumberFormatException e) {
2173 return;
2174 }
2175 }
2176 ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
2177 setGlobalProxy(p);
2178 }
2179 }
2180
2181 private void sendProxyBroadcast(ProxyProperties proxy) {
Robert Greenwalt55985be2010-12-23 15:51:10 -08002182 if (proxy == null) proxy = new ProxyProperties("", 0, "");
Wink Savilleed9c02b2010-12-03 12:01:38 -08002183 log("sending Proxy Broadcast for " + proxy);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002184 Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
Stan Chesnuttb35d67a2011-01-06 11:00:19 -08002185 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
2186 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002187 intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
Robert Greenwalta2e13392010-12-06 11:29:17 -08002188 mContext.sendStickyBroadcast(intent);
Robert Greenwalt434203a2010-10-11 16:00:27 -07002189 }
2190
2191 private static class SettingsObserver extends ContentObserver {
2192 private int mWhat;
2193 private Handler mHandler;
2194 SettingsObserver(Handler handler, int what) {
2195 super(handler);
2196 mHandler = handler;
2197 mWhat = what;
2198 }
2199
2200 void observe(Context context) {
2201 ContentResolver resolver = context.getContentResolver();
2202 resolver.registerContentObserver(Settings.Secure.getUriFor(
2203 Settings.Secure.HTTP_PROXY), false, this);
2204 }
2205
2206 @Override
2207 public void onChange(boolean selfChange) {
2208 mHandler.obtainMessage(mWhat).sendToTarget();
2209 }
2210 }
Wink Savilleed9c02b2010-12-03 12:01:38 -08002211
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05002212 private void handleTetherIfaceChange(int type) {
2213 String iface = mNetTrackers[type].getLinkProperties().getInterfaceName();
2214
2215 if (isTetheringSupported()) {
2216 mTethering.handleTetherIfaceChange(iface);
2217 }
2218 }
2219
Wink Savilleed9c02b2010-12-03 12:01:38 -08002220 private void log(String s) {
2221 Slog.d(TAG, s);
2222 }
2223
2224 private void loge(String s) {
2225 Slog.e(TAG, s);
2226 }
Wink Saville9d7d6282011-03-12 14:52:01 -08002227 int convertFeatureToNetworkType(String feature){
2228 int networkType = -1;
2229 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
2230 networkType = ConnectivityManager.TYPE_MOBILE_MMS;
2231 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
2232 networkType = ConnectivityManager.TYPE_MOBILE_SUPL;
2233 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
2234 TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
2235 networkType = ConnectivityManager.TYPE_MOBILE_DUN;
2236 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
2237 networkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
2238 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
2239 networkType = ConnectivityManager.TYPE_MOBILE_FOTA;
2240 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
2241 networkType = ConnectivityManager.TYPE_MOBILE_IMS;
2242 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
2243 networkType = ConnectivityManager.TYPE_MOBILE_CBS;
2244 }
2245 return networkType;
2246 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247}