blob: 230f07bb5baf28f0505ecf3f0c6f4b3cc0888fbd [file] [log] [blame]
The Android Open Source Project28527d22009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Jeff Sharkey4434b0b2011-06-16 13:04:20 -070019import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
Jeff Sharkey971cd162011-08-29 16:02:57 -070020import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
21import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070022import static android.net.ConnectivityManager.isNetworkTypeValid;
23import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -070024import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070025
Jaikumar Ganesh0db51a02010-12-21 22:31:44 -080026import android.bluetooth.BluetoothTetheringDataTracker;
The Android Open Source Project28527d22009-03-03 19:31:44 -080027import android.content.ContentResolver;
28import android.content.Context;
tk.mun093f55c2011-10-13 22:51:57 +090029import android.content.ContextWrapper;
The Android Open Source Project28527d22009-03-03 19:31:44 -080030import android.content.Intent;
31import android.content.pm.PackageManager;
tk.mun093f55c2011-10-13 22:51:57 +090032import android.content.res.Resources;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -070033import android.database.ContentObserver;
The Android Open Source Project28527d22009-03-03 19:31:44 -080034import android.net.ConnectivityManager;
Robert Greenwalteb123ac2010-12-06 13:56:24 -080035import android.net.DummyDataStateTracker;
Benoit Goby211b5692010-12-22 14:29:40 -080036import android.net.EthernetDataTracker;
The Android Open Source Project28527d22009-03-03 19:31:44 -080037import android.net.IConnectivityManager;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070038import android.net.INetworkPolicyListener;
39import android.net.INetworkPolicyManager;
Jeff Sharkeyb6188a12011-09-22 14:59:51 -070040import android.net.INetworkStatsService;
Wink Savilledc5d1ba2011-07-14 12:23:28 -070041import android.net.LinkAddress;
Jaikumar Ganesh0db51a02010-12-21 22:31:44 -080042import android.net.LinkProperties;
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -070043import android.net.LinkProperties.CompareResult;
The Android Open Source Project28527d22009-03-03 19:31:44 -080044import android.net.MobileDataStateTracker;
Robert Greenwalt34848c02011-03-25 13:09:25 -070045import android.net.NetworkConfig;
The Android Open Source Project28527d22009-03-03 19:31:44 -080046import android.net.NetworkInfo;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070047import android.net.NetworkInfo.DetailedState;
Jeff Sharkey66fa9682011-08-02 17:22:34 -070048import android.net.NetworkQuotaInfo;
Jeff Sharkey21062e72011-05-28 20:56:34 -070049import android.net.NetworkState;
The Android Open Source Project28527d22009-03-03 19:31:44 -080050import android.net.NetworkStateTracker;
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -070051import android.net.NetworkUtils;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -070052import android.net.Proxy;
53import android.net.ProxyProperties;
Robert Greenwalt5a901292011-04-28 14:28:50 -070054import android.net.RouteInfo;
The Android Open Source Project28527d22009-03-03 19:31:44 -080055import android.net.wifi.WifiStateTracker;
tk.mun093f55c2011-10-13 22:51:57 +090056import android.net.wimax.WimaxManagerConstants;
The Android Open Source Project28527d22009-03-03 19:31:44 -080057import android.os.Binder;
Mike Lockwood0d5916c2011-05-28 13:24:04 -040058import android.os.FileUtils;
The Android Open Source Project28527d22009-03-03 19:31:44 -080059import android.os.Handler;
Wink Saville775aad62010-09-02 19:23:52 -070060import android.os.HandlerThread;
Robert Greenwalt2034b912009-08-12 16:08:25 -070061import android.os.IBinder;
Chia-chi Yeh4df51322011-05-11 16:35:13 -070062import android.os.INetworkManagementService;
The Android Open Source Project28527d22009-03-03 19:31:44 -080063import android.os.Looper;
64import android.os.Message;
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -070065import android.os.ParcelFileDescriptor;
Robert Greenwalt93dc1042010-06-15 12:19:37 -070066import android.os.PowerManager;
Robert Greenwalt2034b912009-08-12 16:08:25 -070067import android.os.RemoteException;
The Android Open Source Project28527d22009-03-03 19:31:44 -080068import android.os.ServiceManager;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -070069import android.os.SystemClock;
The Android Open Source Project28527d22009-03-03 19:31:44 -080070import android.os.SystemProperties;
71import android.provider.Settings;
Robert Greenwalt2034b912009-08-12 16:08:25 -070072import android.text.TextUtils;
The Android Open Source Project28527d22009-03-03 19:31:44 -080073import android.util.EventLog;
Joe Onoratoc2386bb2010-02-26 18:56:32 -080074import android.util.Slog;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070075import android.util.SparseIntArray;
The Android Open Source Project28527d22009-03-03 19:31:44 -080076
Chia-chi Yehbded3eb2011-07-04 03:23:12 -070077import com.android.internal.net.LegacyVpnInfo;
Chia-chi Yeh75cacd52011-06-15 17:07:27 -070078import com.android.internal.net.VpnConfig;
Robert Greenwalt2034b912009-08-12 16:08:25 -070079import com.android.internal.telephony.Phone;
Wink Saville64e3f782012-07-10 12:37:54 -070080import com.android.internal.telephony.PhoneConstants;
Jeff Sharkeyaac2c502011-10-04 16:54:49 -070081import com.android.server.am.BatteryStatsService;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080082import com.android.server.connectivity.Tethering;
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -070083import com.android.server.connectivity.Vpn;
Jeff Sharkey21062e72011-05-28 20:56:34 -070084import com.google.android.collect.Lists;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -070085import com.google.android.collect.Sets;
tk.mun093f55c2011-10-13 22:51:57 +090086import dalvik.system.DexClassLoader;
The Android Open Source Project28527d22009-03-03 19:31:44 -080087import java.io.FileDescriptor;
Irfan Sheriff7f132d92010-06-09 15:39:36 -070088import java.io.IOException;
The Android Open Source Project28527d22009-03-03 19:31:44 -080089import java.io.PrintWriter;
tk.mun093f55c2011-10-13 22:51:57 +090090import java.lang.reflect.Constructor;
91import java.lang.reflect.Method;
92import java.lang.reflect.Modifier;
93import java.lang.reflect.InvocationTargetException;
Wink Savilledc5d1ba2011-07-14 12:23:28 -070094import java.net.Inet4Address;
Wink Saville051a6642011-07-13 13:44:13 -070095import java.net.Inet6Address;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070096import java.net.InetAddress;
97import java.net.UnknownHostException;
Robert Greenwalt2034b912009-08-12 16:08:25 -070098import java.util.ArrayList;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -070099import java.util.Arrays;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700100import java.util.Collection;
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700101import java.util.GregorianCalendar;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700102import java.util.HashSet;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700103import java.util.List;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800104
105/**
106 * @hide
107 */
108public class ConnectivityService extends IConnectivityManager.Stub {
109
Robert Greenwalt063dc7d2010-10-05 19:12:26 -0700110 private static final boolean DBG = true;
Wink Savillea7d56572011-09-21 11:05:43 -0700111 private static final boolean VDBG = false;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800112 private static final String TAG = "ConnectivityService";
113
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700114 private static final boolean LOGD_RULES = false;
115
Robert Greenwalt2034b912009-08-12 16:08:25 -0700116 // how long to wait before switching back to a radio's default network
117 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
118 // system property that can override the above value
119 private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
120 "android.telephony.apn-restore";
121
Robert Greenwaltbd492212011-05-06 17:10:53 -0700122 // used in recursive route setting to add gateways for the host for which
123 // a host route was requested.
124 private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10;
125
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800126 private Tethering mTethering;
Robert Greenwaltf1b66e12010-02-25 12:29:30 -0800127 private boolean mTetheringConfigValid = false;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800128
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -0700129 private Vpn mVpn;
130
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700131 /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
132 private Object mRulesLock = new Object();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700133 /** Currently active network rules by UID. */
134 private SparseIntArray mUidRules = new SparseIntArray();
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700135 /** Set of ifaces that are costly. */
136 private HashSet<String> mMeteredIfaces = Sets.newHashSet();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700137
The Android Open Source Project28527d22009-03-03 19:31:44 -0800138 /**
139 * Sometimes we want to refer to the individual network state
140 * trackers separately, and sometimes we just want to treat them
141 * abstractly.
142 */
143 private NetworkStateTracker mNetTrackers[];
Robert Greenwalt2034b912009-08-12 16:08:25 -0700144
145 /**
Wink Saville051a6642011-07-13 13:44:13 -0700146 * The link properties that define the current links
147 */
148 private LinkProperties mCurrentLinkProperties[];
149
150 /**
Robert Greenwalt2034b912009-08-12 16:08:25 -0700151 * A per Net list of the PID's that requested access to the net
152 * used both as a refcount and for per-PID DNS selection
153 */
154 private List mNetRequestersPids[];
155
Robert Greenwalt2034b912009-08-12 16:08:25 -0700156 // priority order of the nettrackers
157 // (excluding dynamically set mNetworkPreference)
158 // TODO - move mNetworkTypePreference into this
159 private int[] mPriorityList;
160
The Android Open Source Project28527d22009-03-03 19:31:44 -0800161 private Context mContext;
162 private int mNetworkPreference;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700163 private int mActiveDefaultNetwork = -1;
Robert Greenwalt986c7412010-09-08 15:24:47 -0700164 // 0 is full bad, 100 is full good
165 private int mDefaultInetCondition = 0;
166 private int mDefaultInetConditionPublished = 0;
167 private boolean mInetConditionChangeInFlight = false;
168 private int mDefaultConnectionSequence = 0;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800169
Chia-chi Yehcc844502011-07-14 18:01:57 -0700170 private Object mDnsLock = new Object();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800171 private int mNumDnsEntries;
Chia-chi Yehcc844502011-07-14 18:01:57 -0700172 private boolean mDnsOverridden = false;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800173
174 private boolean mTestMode;
Joe Onorato56023ad2010-09-01 21:18:22 -0700175 private static ConnectivityService sServiceInstance;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800176
Robert Greenwalt355205c2011-05-10 15:05:02 -0700177 private INetworkManagementService mNetd;
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700178 private INetworkPolicyManager mPolicyManager;
Robert Greenwalt355205c2011-05-10 15:05:02 -0700179
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700180 private static final int ENABLED = 1;
181 private static final int DISABLED = 0;
182
Robert Greenwalt49c75d32011-11-02 14:37:19 -0700183 private static final boolean ADD = true;
184 private static final boolean REMOVE = false;
185
186 private static final boolean TO_DEFAULT_TABLE = true;
187 private static final boolean TO_SECONDARY_TABLE = false;
188
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700189 // Share the event space with NetworkStateTracker (which can't see this
190 // internal class but sends us events). If you change these, change
191 // NetworkStateTracker.java too.
192 private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1;
193 private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100;
194
195 /**
196 * used internally as a delayed event to make us switch back to the
197 * default network
198 */
199 private static final int EVENT_RESTORE_DEFAULT_NETWORK =
200 MAX_NETWORK_STATE_TRACKER_EVENT + 1;
201
202 /**
203 * used internally to change our mobile data enabled flag
204 */
205 private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED =
206 MAX_NETWORK_STATE_TRACKER_EVENT + 2;
207
208 /**
209 * used internally to change our network preference setting
210 * arg1 = networkType to prefer
211 */
212 private static final int EVENT_SET_NETWORK_PREFERENCE =
213 MAX_NETWORK_STATE_TRACKER_EVENT + 3;
214
215 /**
216 * used internally to synchronize inet condition reports
217 * arg1 = networkType
218 * arg2 = condition (0 bad, 100 good)
219 */
220 private static final int EVENT_INET_CONDITION_CHANGE =
221 MAX_NETWORK_STATE_TRACKER_EVENT + 4;
222
223 /**
224 * used internally to mark the end of inet condition hold periods
225 * arg1 = networkType
226 */
227 private static final int EVENT_INET_CONDITION_HOLD_END =
228 MAX_NETWORK_STATE_TRACKER_EVENT + 5;
229
230 /**
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700231 * used internally to set enable/disable cellular data
232 * arg1 = ENBALED or DISABLED
233 */
234 private static final int EVENT_SET_MOBILE_DATA =
235 MAX_NETWORK_STATE_TRACKER_EVENT + 7;
236
Robert Greenwaltccb36f92010-09-24 14:32:21 -0700237 /**
238 * used internally to clear a wakelock when transitioning
239 * from one net to another
240 */
241 private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK =
242 MAX_NETWORK_STATE_TRACKER_EVENT + 8;
243
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700244 /**
245 * used internally to reload global proxy settings
246 */
247 private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY =
248 MAX_NETWORK_STATE_TRACKER_EVENT + 9;
249
Robert Greenwalt34848c02011-03-25 13:09:25 -0700250 /**
251 * used internally to set external dependency met/unmet
252 * arg1 = ENABLED (met) or DISABLED (unmet)
253 * arg2 = NetworkType
254 */
255 private static final int EVENT_SET_DEPENDENCY_MET =
256 MAX_NETWORK_STATE_TRACKER_EVENT + 10;
257
Chia-chi Yehcc844502011-07-14 18:01:57 -0700258 /**
259 * used internally to restore DNS properties back to the
260 * default network
261 */
262 private static final int EVENT_RESTORE_DNS =
263 MAX_NETWORK_STATE_TRACKER_EVENT + 11;
264
Wink Saville7e4333c2011-08-05 11:40:22 -0700265 /**
Wink Saville4f0de1e2011-08-04 15:01:58 -0700266 * used internally to send a sticky broadcast delayed.
267 */
268 private static final int EVENT_SEND_STICKY_BROADCAST_INTENT =
Wink Saville7e4333c2011-08-05 11:40:22 -0700269 MAX_NETWORK_STATE_TRACKER_EVENT + 12;
Wink Saville4f0de1e2011-08-04 15:01:58 -0700270
Jeff Sharkey805662d2011-08-19 02:24:24 -0700271 /**
272 * Used internally to
273 * {@link NetworkStateTracker#setPolicyDataEnable(boolean)}.
274 */
275 private static final int EVENT_SET_POLICY_DATA_ENABLE = MAX_NETWORK_STATE_TRACKER_EVENT + 13;
276
Robert Greenwalt2034b912009-08-12 16:08:25 -0700277 private Handler mHandler;
278
279 // list of DeathRecipients used to make sure features are turned off when
280 // a process dies
Kazuhiro Ondocae18f12011-07-19 11:23:37 -0500281 private List<FeatureUser> mFeatureUsers;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700282
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400283 private boolean mSystemReady;
Dianne Hackborna417ff82009-12-08 19:45:14 -0800284 private Intent mInitialBroadcast;
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400285
Robert Greenwalt93dc1042010-06-15 12:19:37 -0700286 private PowerManager.WakeLock mNetTransitionWakeLock;
287 private String mNetTransitionWakeLockCausedBy = "";
288 private int mNetTransitionWakeLockSerialNumber;
289 private int mNetTransitionWakeLockTimeout;
290
Robert Greenwalt94daa182010-09-01 11:34:05 -0700291 private InetAddress mDefaultDns;
292
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700293 // this collection is used to refcount the added routes - if there are none left
294 // it's time to remove the route from the route table
295 private Collection<RouteInfo> mAddedRoutes = new ArrayList<RouteInfo>();
296
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700297 // used in DBG mode to track inet condition reports
298 private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
299 private ArrayList mInetLog;
300
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700301 // track the current default http proxy - tell the world if we get a new one (real change)
302 private ProxyProperties mDefaultProxy = null;
Chia-chi Yeh763a11c2011-10-03 15:34:04 -0700303 private Object mDefaultProxyLock = new Object();
304 private boolean mDefaultProxyDisabled = false;
305
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700306 // track the global proxy.
307 private ProxyProperties mGlobalProxy = null;
308 private final Object mGlobalProxyLock = new Object();
309
310 private SettingsObserver mSettingsObserver;
311
Robert Greenwalt34848c02011-03-25 13:09:25 -0700312 NetworkConfig[] mNetConfigs;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700313 int mNetworksDefined;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700314
Robert Greenwalt12c44552009-12-07 11:33:18 -0800315 private static class RadioAttributes {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700316 public int mSimultaneity;
317 public int mType;
318 public RadioAttributes(String init) {
319 String fragments[] = init.split(",");
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700320 mType = Integer.parseInt(fragments[0]);
321 mSimultaneity = Integer.parseInt(fragments[1]);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700322 }
323 }
324 RadioAttributes[] mRadioAttributes;
325
Robert Greenwalt6cac0742011-06-21 17:26:14 -0700326 // the set of network types that can only be enabled by system/sig apps
327 List mProtectedNetworks;
328
Jeff Sharkeyb6188a12011-09-22 14:59:51 -0700329 public ConnectivityService(Context context, INetworkManagementService netd,
330 INetworkStatsService statsService, INetworkPolicyManager policyManager) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800331 if (DBG) log("ConnectivityService starting up");
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800332
Wink Saville775aad62010-09-02 19:23:52 -0700333 HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
334 handlerThread.start();
335 mHandler = new MyHandler(handlerThread.getLooper());
336
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800337 // setup our unique device name
Robert Greenwalt82cde132010-12-06 09:30:17 -0800338 if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
339 String id = Settings.Secure.getString(context.getContentResolver(),
340 Settings.Secure.ANDROID_ID);
341 if (id != null && id.length() > 0) {
Irfan Sheriff4aa0b2e2011-09-20 15:17:07 -0700342 String name = new String("android-").concat(id);
Robert Greenwalt82cde132010-12-06 09:30:17 -0800343 SystemProperties.set("net.hostname", name);
344 }
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800345 }
346
Robert Greenwalt94daa182010-09-01 11:34:05 -0700347 // read our default dns server ip
348 String dns = Settings.Secure.getString(context.getContentResolver(),
349 Settings.Secure.DEFAULT_DNS_SERVER);
350 if (dns == null || dns.length() == 0) {
351 dns = context.getResources().getString(
352 com.android.internal.R.string.config_default_dns_server);
353 }
354 try {
Robert Greenwalt35e34d12011-02-22 16:00:42 -0800355 mDefaultDns = NetworkUtils.numericToInetAddress(dns);
356 } catch (IllegalArgumentException e) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800357 loge("Error setting defaultDns using " + dns);
Robert Greenwalt94daa182010-09-01 11:34:05 -0700358 }
359
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700360 mContext = checkNotNull(context, "missing Context");
361 mNetd = checkNotNull(netd, "missing INetworkManagementService");
362 mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
Robert Greenwalt93dc1042010-06-15 12:19:37 -0700363
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700364 try {
365 mPolicyManager.registerListener(mPolicyListener);
366 } catch (RemoteException e) {
367 // ouch, no rules updates means some processes may never get network
Robert Greenwalt78f28112011-08-02 17:18:41 -0700368 loge("unable to register INetworkPolicyListener" + e.toString());
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700369 }
370
371 final PowerManager powerManager = (PowerManager) context.getSystemService(
372 Context.POWER_SERVICE);
Robert Greenwalt93dc1042010-06-15 12:19:37 -0700373 mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
374 mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
375 com.android.internal.R.integer.config_networkTransitionTimeout);
376
Robert Greenwalt2034b912009-08-12 16:08:25 -0700377 mNetTrackers = new NetworkStateTracker[
378 ConnectivityManager.MAX_NETWORK_TYPE+1];
Wink Saville051a6642011-07-13 13:44:13 -0700379 mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwalt0659da32009-07-16 17:21:39 -0700380
The Android Open Source Project28527d22009-03-03 19:31:44 -0800381 mNetworkPreference = getPersistedNetworkPreference();
Robert Greenwalt0659da32009-07-16 17:21:39 -0700382
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700383 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
Robert Greenwalt34848c02011-03-25 13:09:25 -0700384 mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700385
Robert Greenwalt2034b912009-08-12 16:08:25 -0700386 // Load device network attributes from resources
Robert Greenwalt2034b912009-08-12 16:08:25 -0700387 String[] raStrings = context.getResources().getStringArray(
388 com.android.internal.R.array.radioAttributes);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700389 for (String raString : raStrings) {
390 RadioAttributes r = new RadioAttributes(raString);
391 if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800392 loge("Error in radioAttributes - ignoring attempt to define type " + r.mType);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700393 continue;
394 }
395 if (mRadioAttributes[r.mType] != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800396 loge("Error in radioAttributes - ignoring attempt to redefine type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700397 r.mType);
398 continue;
399 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700400 mRadioAttributes[r.mType] = r;
401 }
402
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700403 String[] naStrings = context.getResources().getStringArray(
404 com.android.internal.R.array.networkAttributes);
405 for (String naString : naStrings) {
406 try {
Robert Greenwalt34848c02011-03-25 13:09:25 -0700407 NetworkConfig n = new NetworkConfig(naString);
Wink Savillef2a62832011-04-07 14:23:45 -0700408 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800409 loge("Error in networkAttributes - ignoring attempt to define type " +
Wink Savillef2a62832011-04-07 14:23:45 -0700410 n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700411 continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700412 }
Wink Savillef2a62832011-04-07 14:23:45 -0700413 if (mNetConfigs[n.type] != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800414 loge("Error in networkAttributes - ignoring attempt to redefine type " +
Wink Savillef2a62832011-04-07 14:23:45 -0700415 n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700416 continue;
417 }
Wink Savillef2a62832011-04-07 14:23:45 -0700418 if (mRadioAttributes[n.radio] == null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800419 loge("Error in networkAttributes - ignoring attempt to use undefined " +
Wink Savillef2a62832011-04-07 14:23:45 -0700420 "radio " + n.radio + " in network type " + n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700421 continue;
422 }
Wink Savillef2a62832011-04-07 14:23:45 -0700423 mNetConfigs[n.type] = n;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700424 mNetworksDefined++;
425 } catch(Exception e) {
426 // ignore it - leave the entry null
Robert Greenwalt2034b912009-08-12 16:08:25 -0700427 }
428 }
429
Robert Greenwalt6cac0742011-06-21 17:26:14 -0700430 mProtectedNetworks = new ArrayList<Integer>();
431 int[] protectedNetworks = context.getResources().getIntArray(
432 com.android.internal.R.array.config_protectedNetworks);
433 for (int p : protectedNetworks) {
434 if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
435 mProtectedNetworks.add(p);
436 } else {
437 if (DBG) loge("Ignoring protectedNetwork " + p);
438 }
439 }
440
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700441 // high priority first
442 mPriorityList = new int[mNetworksDefined];
443 {
444 int insertionPoint = mNetworksDefined-1;
445 int currentLowest = 0;
446 int nextLowest = 0;
447 while (insertionPoint > -1) {
Robert Greenwalt34848c02011-03-25 13:09:25 -0700448 for (NetworkConfig na : mNetConfigs) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700449 if (na == null) continue;
Wink Savillef2a62832011-04-07 14:23:45 -0700450 if (na.priority < currentLowest) continue;
451 if (na.priority > currentLowest) {
452 if (na.priority < nextLowest || nextLowest == 0) {
453 nextLowest = na.priority;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700454 }
455 continue;
456 }
Wink Savillef2a62832011-04-07 14:23:45 -0700457 mPriorityList[insertionPoint--] = na.type;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700458 }
459 currentLowest = nextLowest;
460 nextLowest = 0;
461 }
462 }
463
464 mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
465 for (int i : mPriorityList) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700466 mNetRequestersPids[i] = new ArrayList();
467 }
468
Kazuhiro Ondocae18f12011-07-19 11:23:37 -0500469 mFeatureUsers = new ArrayList<FeatureUser>();
Robert Greenwalt2034b912009-08-12 16:08:25 -0700470
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700471 mNumDnsEntries = 0;
472
473 mTestMode = SystemProperties.get("cm.test.mode").equals("true")
474 && SystemProperties.get("ro.build.type").equals("eng");
The Android Open Source Project28527d22009-03-03 19:31:44 -0800475 /*
476 * Create the network state trackers for Wi-Fi and mobile
477 * data. Maybe this could be done with a factory class,
478 * but it's not clear that it's worth it, given that
479 * the number of different network types is not going
480 * to change very often.
481 */
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700482 for (int netType : mPriorityList) {
Wink Savillef2a62832011-04-07 14:23:45 -0700483 switch (mNetConfigs[netType].radio) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700484 case ConnectivityManager.TYPE_WIFI:
repo syncf5de5572011-07-29 23:55:49 -0700485 mNetTrackers[netType] = new WifiStateTracker(netType,
486 mNetConfigs[netType].name);
487 mNetTrackers[netType].startMonitoring(context, mHandler);
488 break;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700489 case ConnectivityManager.TYPE_MOBILE:
Wink Saville7fabfa22010-08-13 16:11:42 -0700490 mNetTrackers[netType] = new MobileDataStateTracker(netType,
Wink Savillef2a62832011-04-07 14:23:45 -0700491 mNetConfigs[netType].name);
Wink Saville7fabfa22010-08-13 16:11:42 -0700492 mNetTrackers[netType].startMonitoring(context, mHandler);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700493 break;
Robert Greenwalteb123ac2010-12-06 13:56:24 -0800494 case ConnectivityManager.TYPE_DUMMY:
495 mNetTrackers[netType] = new DummyDataStateTracker(netType,
Wink Savillef2a62832011-04-07 14:23:45 -0700496 mNetConfigs[netType].name);
Robert Greenwalteb123ac2010-12-06 13:56:24 -0800497 mNetTrackers[netType].startMonitoring(context, mHandler);
498 break;
Jaikumar Ganesh0db51a02010-12-21 22:31:44 -0800499 case ConnectivityManager.TYPE_BLUETOOTH:
500 mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
501 mNetTrackers[netType].startMonitoring(context, mHandler);
502 break;
tk.mun093f55c2011-10-13 22:51:57 +0900503 case ConnectivityManager.TYPE_WIMAX:
504 mNetTrackers[netType] = makeWimaxStateTracker();
Robert Greenwalte72c4ac2011-11-08 10:12:25 -0800505 if (mNetTrackers[netType]!= null) {
tk.mun093f55c2011-10-13 22:51:57 +0900506 mNetTrackers[netType].startMonitoring(context, mHandler);
507 }
508 break;
Benoit Goby211b5692010-12-22 14:29:40 -0800509 case ConnectivityManager.TYPE_ETHERNET:
510 mNetTrackers[netType] = EthernetDataTracker.getInstance();
511 mNetTrackers[netType].startMonitoring(context, mHandler);
512 break;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700513 default:
Wink Savillee70c6f52010-12-03 12:01:38 -0800514 loge("Trying to create a DataStateTracker for an unknown radio type " +
Wink Savillef2a62832011-04-07 14:23:45 -0700515 mNetConfigs[netType].radio);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700516 continue;
517 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700518 mCurrentLinkProperties[netType] = null;
Robert Greenwaltcafd8582011-11-10 16:55:20 -0800519 if (mNetTrackers[netType] != null && mNetConfigs[netType].isDefault()) {
520 mNetTrackers[netType].reconnect();
521 }
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700522 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800523
Chia-chi Yeh4df51322011-05-11 16:35:13 -0700524 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
525 INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
526
Robert Greenwalt49c75d32011-11-02 14:37:19 -0700527 mTethering = new Tethering(mContext, nmService, statsService, this, mHandler.getLooper());
Robert Greenwalt33cdcdf2011-06-02 17:30:47 -0700528 mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
Danica Chang96567052010-08-11 14:54:43 -0700529 mTethering.getTetherableWifiRegexs().length != 0 ||
530 mTethering.getTetherableBluetoothRegexs().length != 0) &&
Robert Greenwalt33cdcdf2011-06-02 17:30:47 -0700531 mTethering.getUpstreamIfaceTypes().length != 0);
Robert Greenwaltf1b66e12010-02-25 12:29:30 -0800532
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -0700533 mVpn = new Vpn(mContext, new VpnCallback());
534
Chia-chi Yehf3204aa2011-05-23 15:08:29 -0700535 try {
536 nmService.registerObserver(mTethering);
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -0700537 nmService.registerObserver(mVpn);
Chia-chi Yehf3204aa2011-05-23 15:08:29 -0700538 } catch (RemoteException e) {
539 loge("Error registering observer :" + e);
540 }
541
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700542 if (DBG) {
543 mInetLog = new ArrayList();
544 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700545
546 mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
547 mSettingsObserver.observe(mContext);
Robert Greenwalt6f7c6092010-12-02 11:31:00 -0800548
549 loadGlobalProxy();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800550 }
tk.mun093f55c2011-10-13 22:51:57 +0900551private NetworkStateTracker makeWimaxStateTracker() {
552 //Initialize Wimax
553 DexClassLoader wimaxClassLoader;
554 Class wimaxStateTrackerClass = null;
555 Class wimaxServiceClass = null;
556 Class wimaxManagerClass;
557 String wimaxJarLocation;
558 String wimaxLibLocation;
559 String wimaxManagerClassName;
560 String wimaxServiceClassName;
561 String wimaxStateTrackerClassName;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800562
tk.mun093f55c2011-10-13 22:51:57 +0900563 NetworkStateTracker wimaxStateTracker = null;
564
565 boolean isWimaxEnabled = mContext.getResources().getBoolean(
566 com.android.internal.R.bool.config_wimaxEnabled);
567
568 if (isWimaxEnabled) {
569 try {
570 wimaxJarLocation = mContext.getResources().getString(
571 com.android.internal.R.string.config_wimaxServiceJarLocation);
572 wimaxLibLocation = mContext.getResources().getString(
573 com.android.internal.R.string.config_wimaxNativeLibLocation);
574 wimaxManagerClassName = mContext.getResources().getString(
575 com.android.internal.R.string.config_wimaxManagerClassname);
576 wimaxServiceClassName = mContext.getResources().getString(
577 com.android.internal.R.string.config_wimaxServiceClassname);
578 wimaxStateTrackerClassName = mContext.getResources().getString(
579 com.android.internal.R.string.config_wimaxStateTrackerClassname);
580
581 log("wimaxJarLocation: " + wimaxJarLocation);
582 wimaxClassLoader = new DexClassLoader(wimaxJarLocation,
583 new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
584 wimaxLibLocation, ClassLoader.getSystemClassLoader());
585
586 try {
587 wimaxManagerClass = wimaxClassLoader.loadClass(wimaxManagerClassName);
588 wimaxStateTrackerClass = wimaxClassLoader.loadClass(wimaxStateTrackerClassName);
589 wimaxServiceClass = wimaxClassLoader.loadClass(wimaxServiceClassName);
590 } catch (ClassNotFoundException ex) {
591 loge("Exception finding Wimax classes: " + ex.toString());
592 return null;
593 }
594 } catch(Resources.NotFoundException ex) {
595 loge("Wimax Resources does not exist!!! ");
596 return null;
597 }
598
599 try {
600 log("Starting Wimax Service... ");
601
602 Constructor wmxStTrkrConst = wimaxStateTrackerClass.getConstructor
603 (new Class[] {Context.class, Handler.class});
604 wimaxStateTracker = (NetworkStateTracker)wmxStTrkrConst.newInstance(mContext,
605 mHandler);
606
607 Constructor wmxSrvConst = wimaxServiceClass.getDeclaredConstructor
608 (new Class[] {Context.class, wimaxStateTrackerClass});
609 wmxSrvConst.setAccessible(true);
610 IBinder svcInvoker = (IBinder)wmxSrvConst.newInstance(mContext, wimaxStateTracker);
611 wmxSrvConst.setAccessible(false);
612
613 ServiceManager.addService(WimaxManagerConstants.WIMAX_SERVICE, svcInvoker);
614
615 } catch(Exception ex) {
616 loge("Exception creating Wimax classes: " + ex.toString());
617 return null;
618 }
619 } else {
620 loge("Wimax is not enabled or not added to the network attributes!!! ");
621 return null;
622 }
623
624 return wimaxStateTracker;
625 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800626 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700627 * Sets the preferred network.
The Android Open Source Project28527d22009-03-03 19:31:44 -0800628 * @param preference the new preference
629 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700630 public void setNetworkPreference(int preference) {
The Android Open Source Project28527d22009-03-03 19:31:44 -0800631 enforceChangePermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700632
633 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
The Android Open Source Project28527d22009-03-03 19:31:44 -0800634 }
635
636 public int getNetworkPreference() {
637 enforceAccessPermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700638 int preference;
639 synchronized(this) {
640 preference = mNetworkPreference;
641 }
642 return preference;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800643 }
644
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700645 private void handleSetNetworkPreference(int preference) {
646 if (ConnectivityManager.isNetworkTypeValid(preference) &&
Robert Greenwalt34848c02011-03-25 13:09:25 -0700647 mNetConfigs[preference] != null &&
648 mNetConfigs[preference].isDefault()) {
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700649 if (mNetworkPreference != preference) {
650 final ContentResolver cr = mContext.getContentResolver();
651 Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference);
652 synchronized(this) {
653 mNetworkPreference = preference;
654 }
655 enforcePreference();
656 }
657 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800658 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700659
Wink Saville4f0de1e2011-08-04 15:01:58 -0700660 private int getConnectivityChangeDelay() {
661 final ContentResolver cr = mContext.getContentResolver();
662
663 /** Check system properties for the default value then use secure settings value, if any. */
664 int defaultDelay = SystemProperties.getInt(
665 "conn." + Settings.Secure.CONNECTIVITY_CHANGE_DELAY,
666 Settings.Secure.CONNECTIVITY_CHANGE_DELAY_DEFAULT);
667 return Settings.Secure.getInt(cr, Settings.Secure.CONNECTIVITY_CHANGE_DELAY,
668 defaultDelay);
669 }
670
The Android Open Source Project28527d22009-03-03 19:31:44 -0800671 private int getPersistedNetworkPreference() {
672 final ContentResolver cr = mContext.getContentResolver();
673
674 final int networkPrefSetting = Settings.Secure
675 .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
676 if (networkPrefSetting != -1) {
677 return networkPrefSetting;
678 }
679
680 return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
681 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700682
The Android Open Source Project28527d22009-03-03 19:31:44 -0800683 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700684 * Make the state of network connectivity conform to the preference settings
The Android Open Source Project28527d22009-03-03 19:31:44 -0800685 * In this method, we only tear down a non-preferred network. Establishing
686 * a connection to the preferred network is taken care of when we handle
687 * the disconnect event from the non-preferred network
688 * (see {@link #handleDisconnect(NetworkInfo)}).
689 */
690 private void enforcePreference() {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700691 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
The Android Open Source Project28527d22009-03-03 19:31:44 -0800692 return;
693
Robert Greenwalt2034b912009-08-12 16:08:25 -0700694 if (!mNetTrackers[mNetworkPreference].isAvailable())
695 return;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800696
Robert Greenwalt2034b912009-08-12 16:08:25 -0700697 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700698 if (t != mNetworkPreference && mNetTrackers[t] != null &&
Robert Greenwalt2034b912009-08-12 16:08:25 -0700699 mNetTrackers[t].getNetworkInfo().isConnected()) {
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700700 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800701 log("tearing down " + mNetTrackers[t].getNetworkInfo() +
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700702 " in enforcePreference");
703 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700704 teardown(mNetTrackers[t]);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800705 }
706 }
707 }
708
709 private boolean teardown(NetworkStateTracker netTracker) {
710 if (netTracker.teardown()) {
711 netTracker.setTeardownRequested(true);
712 return true;
713 } else {
714 return false;
715 }
716 }
717
718 /**
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700719 * Check if UID should be blocked from using the network represented by the
720 * given {@link NetworkStateTracker}.
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700721 */
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700722 private boolean isNetworkBlocked(NetworkStateTracker tracker, int uid) {
723 final String iface = tracker.getLinkProperties().getInterfaceName();
Jeff Sharkey21062e72011-05-28 20:56:34 -0700724
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700725 final boolean networkCostly;
726 final int uidRules;
727 synchronized (mRulesLock) {
728 networkCostly = mMeteredIfaces.contains(iface);
729 uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700730 }
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700731
732 if (networkCostly && (uidRules & RULE_REJECT_METERED) != 0) {
733 return true;
734 }
735
736 // no restrictive rules; network is visible
737 return false;
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700738 }
739
740 /**
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700741 * Return a filtered {@link NetworkInfo}, potentially marked
742 * {@link DetailedState#BLOCKED} based on
743 * {@link #isNetworkBlocked(NetworkStateTracker, int)}.
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700744 */
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700745 private NetworkInfo getFilteredNetworkInfo(NetworkStateTracker tracker, int uid) {
746 NetworkInfo info = tracker.getNetworkInfo();
747 if (isNetworkBlocked(tracker, uid)) {
Jeff Sharkey21062e72011-05-28 20:56:34 -0700748 // network is blocked; clone and override state
749 info = new NetworkInfo(info);
750 info.setDetailedState(DetailedState.BLOCKED, null, null);
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700751 }
Jeff Sharkey21062e72011-05-28 20:56:34 -0700752 return info;
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700753 }
754
755 /**
The Android Open Source Project28527d22009-03-03 19:31:44 -0800756 * Return NetworkInfo for the active (i.e., connected) network interface.
757 * It is assumed that at most one network is active at a time. If more
758 * than one is active, it is indeterminate which will be returned.
Robert Greenwalt0659da32009-07-16 17:21:39 -0700759 * @return the info for the active network, or {@code null} if none is
760 * active
The Android Open Source Project28527d22009-03-03 19:31:44 -0800761 */
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700762 @Override
The Android Open Source Project28527d22009-03-03 19:31:44 -0800763 public NetworkInfo getActiveNetworkInfo() {
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700764 enforceAccessPermission();
765 final int uid = Binder.getCallingUid();
766 return getNetworkInfo(mActiveDefaultNetwork, uid);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800767 }
768
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700769 @Override
770 public NetworkInfo getActiveNetworkInfoForUid(int uid) {
771 enforceConnectivityInternalPermission();
772 return getNetworkInfo(mActiveDefaultNetwork, uid);
773 }
774
775 @Override
The Android Open Source Project28527d22009-03-03 19:31:44 -0800776 public NetworkInfo getNetworkInfo(int networkType) {
777 enforceAccessPermission();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700778 final int uid = Binder.getCallingUid();
779 return getNetworkInfo(networkType, uid);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800780 }
781
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700782 private NetworkInfo getNetworkInfo(int networkType, int uid) {
783 NetworkInfo info = null;
784 if (isNetworkTypeValid(networkType)) {
785 final NetworkStateTracker tracker = mNetTrackers[networkType];
786 if (tracker != null) {
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700787 info = getFilteredNetworkInfo(tracker, uid);
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700788 }
789 }
790 return info;
791 }
792
793 @Override
The Android Open Source Project28527d22009-03-03 19:31:44 -0800794 public NetworkInfo[] getAllNetworkInfo() {
795 enforceAccessPermission();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700796 final int uid = Binder.getCallingUid();
Jeff Sharkey21062e72011-05-28 20:56:34 -0700797 final ArrayList<NetworkInfo> result = Lists.newArrayList();
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700798 synchronized (mRulesLock) {
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700799 for (NetworkStateTracker tracker : mNetTrackers) {
800 if (tracker != null) {
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700801 result.add(getFilteredNetworkInfo(tracker, uid));
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700802 }
803 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800804 }
Jeff Sharkey21062e72011-05-28 20:56:34 -0700805 return result.toArray(new NetworkInfo[result.size()]);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800806 }
807
Robert Greenwalt0114f6e2011-08-31 11:46:42 -0700808 @Override
809 public boolean isNetworkSupported(int networkType) {
810 enforceAccessPermission();
811 return (isNetworkTypeValid(networkType) && (mNetTrackers[networkType] != null));
812 }
813
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700814 /**
815 * Return LinkProperties for the active (i.e., connected) default
816 * network interface. It is assumed that at most one default network
817 * is active at a time. If more than one is active, it is indeterminate
818 * which will be returned.
819 * @return the ip properties for the active network, or {@code null} if
820 * none is active
821 */
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700822 @Override
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700823 public LinkProperties getActiveLinkProperties() {
Robert Greenwalte1544bb2011-05-20 12:23:41 -0700824 return getLinkProperties(mActiveDefaultNetwork);
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700825 }
826
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700827 @Override
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700828 public LinkProperties getLinkProperties(int networkType) {
829 enforceAccessPermission();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700830 if (isNetworkTypeValid(networkType)) {
831 final NetworkStateTracker tracker = mNetTrackers[networkType];
832 if (tracker != null) {
833 return tracker.getLinkProperties();
834 }
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700835 }
836 return null;
837 }
838
Jeff Sharkey21062e72011-05-28 20:56:34 -0700839 @Override
840 public NetworkState[] getAllNetworkState() {
841 enforceAccessPermission();
842 final int uid = Binder.getCallingUid();
843 final ArrayList<NetworkState> result = Lists.newArrayList();
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700844 synchronized (mRulesLock) {
Jeff Sharkey21062e72011-05-28 20:56:34 -0700845 for (NetworkStateTracker tracker : mNetTrackers) {
846 if (tracker != null) {
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700847 final NetworkInfo info = getFilteredNetworkInfo(tracker, uid);
Jeff Sharkey21062e72011-05-28 20:56:34 -0700848 result.add(new NetworkState(
849 info, tracker.getLinkProperties(), tracker.getLinkCapabilities()));
850 }
851 }
852 }
853 return result.toArray(new NetworkState[result.size()]);
854 }
855
Jeff Sharkey66fa9682011-08-02 17:22:34 -0700856 private NetworkState getNetworkStateUnchecked(int networkType) {
857 if (isNetworkTypeValid(networkType)) {
858 final NetworkStateTracker tracker = mNetTrackers[networkType];
859 if (tracker != null) {
860 return new NetworkState(tracker.getNetworkInfo(), tracker.getLinkProperties(),
861 tracker.getLinkCapabilities());
862 }
863 }
864 return null;
865 }
866
867 @Override
868 public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
869 enforceAccessPermission();
Jeff Sharkey3022ee12012-04-17 12:23:40 -0700870
871 final long token = Binder.clearCallingIdentity();
872 try {
873 final NetworkState state = getNetworkStateUnchecked(mActiveDefaultNetwork);
874 if (state != null) {
875 try {
876 return mPolicyManager.getNetworkQuotaInfo(state);
877 } catch (RemoteException e) {
878 }
Jeff Sharkey66fa9682011-08-02 17:22:34 -0700879 }
Jeff Sharkey3022ee12012-04-17 12:23:40 -0700880 return null;
881 } finally {
882 Binder.restoreCallingIdentity(token);
Jeff Sharkey66fa9682011-08-02 17:22:34 -0700883 }
Jeff Sharkey66fa9682011-08-02 17:22:34 -0700884 }
885
Jeff Sharkeyd00b1302012-04-12 18:34:54 -0700886 @Override
887 public boolean isActiveNetworkMetered() {
888 enforceAccessPermission();
Jeff Sharkey3022ee12012-04-17 12:23:40 -0700889 final long token = Binder.clearCallingIdentity();
890 try {
Jeff Sharkeyedf85d42012-04-30 15:47:05 -0700891 return isNetworkMeteredUnchecked(mActiveDefaultNetwork);
Jeff Sharkey3022ee12012-04-17 12:23:40 -0700892 } finally {
893 Binder.restoreCallingIdentity(token);
Jeff Sharkeyd00b1302012-04-12 18:34:54 -0700894 }
Jeff Sharkeyd00b1302012-04-12 18:34:54 -0700895 }
896
Jeff Sharkeyedf85d42012-04-30 15:47:05 -0700897 private boolean isNetworkMeteredUnchecked(int networkType) {
898 final NetworkState state = getNetworkStateUnchecked(networkType);
899 if (state != null) {
900 try {
901 return mPolicyManager.isNetworkMetered(state);
902 } catch (RemoteException e) {
903 }
904 }
905 return false;
906 }
907
The Android Open Source Project28527d22009-03-03 19:31:44 -0800908 public boolean setRadios(boolean turnOn) {
909 boolean result = true;
910 enforceChangePermission();
911 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700912 if (t != null) result = t.setRadio(turnOn) && result;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800913 }
914 return result;
915 }
916
917 public boolean setRadio(int netType, boolean turnOn) {
918 enforceChangePermission();
919 if (!ConnectivityManager.isNetworkTypeValid(netType)) {
920 return false;
921 }
922 NetworkStateTracker tracker = mNetTrackers[netType];
923 return tracker != null && tracker.setRadio(turnOn);
924 }
925
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700926 /**
927 * Used to notice when the calling process dies so we can self-expire
928 *
929 * Also used to know if the process has cleaned up after itself when
930 * our auto-expire timer goes off. The timer has a link to an object.
931 *
932 */
Robert Greenwalt2034b912009-08-12 16:08:25 -0700933 private class FeatureUser implements IBinder.DeathRecipient {
934 int mNetworkType;
935 String mFeature;
936 IBinder mBinder;
937 int mPid;
938 int mUid;
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800939 long mCreateTime;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700940
941 FeatureUser(int type, String feature, IBinder binder) {
942 super();
943 mNetworkType = type;
944 mFeature = feature;
945 mBinder = binder;
946 mPid = getCallingPid();
947 mUid = getCallingUid();
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800948 mCreateTime = System.currentTimeMillis();
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700949
Robert Greenwalt2034b912009-08-12 16:08:25 -0700950 try {
951 mBinder.linkToDeath(this, 0);
952 } catch (RemoteException e) {
953 binderDied();
954 }
955 }
956
957 void unlinkDeathRecipient() {
958 mBinder.unlinkToDeath(this, 0);
959 }
960
961 public void binderDied() {
Wink Savillee70c6f52010-12-03 12:01:38 -0800962 log("ConnectivityService FeatureUser binderDied(" +
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800963 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
964 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700965 stopUsingNetworkFeature(this, false);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700966 }
967
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700968 public void expire() {
Robert Greenwalt78f28112011-08-02 17:18:41 -0700969 if (VDBG) {
970 log("ConnectivityService FeatureUser expire(" +
971 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
972 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
973 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700974 stopUsingNetworkFeature(this, false);
975 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800976
Kazuhiro Ondocae18f12011-07-19 11:23:37 -0500977 public boolean isSameUser(FeatureUser u) {
978 if (u == null) return false;
979
980 return isSameUser(u.mPid, u.mUid, u.mNetworkType, u.mFeature);
981 }
982
983 public boolean isSameUser(int pid, int uid, int networkType, String feature) {
984 if ((mPid == pid) && (mUid == uid) && (mNetworkType == networkType) &&
985 TextUtils.equals(mFeature, feature)) {
986 return true;
987 }
988 return false;
989 }
990
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800991 public String toString() {
992 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
993 (System.currentTimeMillis() - mCreateTime) + " mSec ago";
994 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700995 }
996
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700997 // javadoc from interface
Robert Greenwalt2034b912009-08-12 16:08:25 -0700998 public int startUsingNetworkFeature(int networkType, String feature,
999 IBinder binder) {
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001000 long startTime = 0;
1001 if (DBG) {
1002 startTime = SystemClock.elapsedRealtime();
1003 }
Wink Savillea7d56572011-09-21 11:05:43 -07001004 if (VDBG) {
Jeff Sharkeyedf85d42012-04-30 15:47:05 -07001005 log("startUsingNetworkFeature for net " + networkType + ": " + feature + ", uid="
1006 + Binder.getCallingUid());
Robert Greenwalt2034b912009-08-12 16:08:25 -07001007 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001008 enforceChangePermission();
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001009 try {
1010 if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
1011 mNetConfigs[networkType] == null) {
Wink Saville64e3f782012-07-10 12:37:54 -07001012 return PhoneConstants.APN_REQUEST_FAILED;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001013 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001014
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001015 FeatureUser f = new FeatureUser(networkType, feature, binder);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001016
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001017 // TODO - move this into individual networktrackers
1018 int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
Robert Greenwalt6cac0742011-06-21 17:26:14 -07001019
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001020 if (mProtectedNetworks.contains(usedNetworkType)) {
1021 enforceConnectivityInternalPermission();
1022 }
Robert Greenwalt6cac0742011-06-21 17:26:14 -07001023
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001024 // if UID is restricted, don't allow them to bring up metered APNs
1025 final boolean networkMetered = isNetworkMeteredUnchecked(usedNetworkType);
1026 final int uidRules;
1027 synchronized (mRulesLock) {
1028 uidRules = mUidRules.get(Binder.getCallingUid(), RULE_ALLOW_ALL);
1029 }
1030 if (networkMetered && (uidRules & RULE_REJECT_METERED) != 0) {
Wink Saville64e3f782012-07-10 12:37:54 -07001031 return PhoneConstants.APN_REQUEST_FAILED;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001032 }
Jeff Sharkeyedf85d42012-04-30 15:47:05 -07001033
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001034 NetworkStateTracker network = mNetTrackers[usedNetworkType];
1035 if (network != null) {
1036 Integer currentPid = new Integer(getCallingPid());
1037 if (usedNetworkType != networkType) {
1038 NetworkInfo ni = network.getNetworkInfo();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001039
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001040 if (ni.isAvailable() == false) {
1041 if (!TextUtils.equals(feature,Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
1042 if (DBG) log("special network not available ni=" + ni.getTypeName());
Wink Saville64e3f782012-07-10 12:37:54 -07001043 return PhoneConstants.APN_TYPE_NOT_AVAILABLE;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001044 } else {
1045 // else make the attempt anyway - probably giving REQUEST_STARTED below
1046 if (DBG) {
1047 log("special network not available, but try anyway ni=" +
1048 ni.getTypeName());
Kazuhiro Ondocae18f12011-07-19 11:23:37 -05001049 }
1050 }
1051 }
1052
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001053 int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001054
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001055 synchronized(this) {
1056 boolean addToList = true;
1057 if (restoreTimer < 0) {
1058 // In case there is no timer is specified for the feature,
1059 // make sure we don't add duplicate entry with the same request.
1060 for (FeatureUser u : mFeatureUsers) {
1061 if (u.isSameUser(f)) {
1062 // Duplicate user is found. Do not add.
1063 addToList = false;
1064 break;
1065 }
1066 }
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001067 }
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001068
1069 if (addToList) mFeatureUsers.add(f);
1070 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
1071 // this gets used for per-pid dns when connected
1072 mNetRequestersPids[usedNetworkType].add(currentPid);
1073 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001074 }
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001075
1076 if (restoreTimer >= 0) {
1077 mHandler.sendMessageDelayed(mHandler.obtainMessage(
1078 EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer);
1079 }
1080
1081 if ((ni.isConnectedOrConnecting() == true) &&
1082 !network.isTeardownRequested()) {
1083 if (ni.isConnected() == true) {
1084 final long token = Binder.clearCallingIdentity();
1085 try {
1086 // add the pid-specific dns
1087 handleDnsConfigurationChange(usedNetworkType);
1088 if (VDBG) log("special network already active");
1089 } finally {
1090 Binder.restoreCallingIdentity(token);
1091 }
Wink Saville64e3f782012-07-10 12:37:54 -07001092 return PhoneConstants.APN_ALREADY_ACTIVE;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001093 }
1094 if (VDBG) log("special network already connecting");
Wink Saville64e3f782012-07-10 12:37:54 -07001095 return PhoneConstants.APN_REQUEST_STARTED;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001096 }
1097
1098 // check if the radio in play can make another contact
1099 // assume if cannot for now
1100
1101 if (DBG) {
1102 log("startUsingNetworkFeature reconnecting to " + networkType + ": " +
1103 feature);
1104 }
1105 network.reconnect();
Wink Saville64e3f782012-07-10 12:37:54 -07001106 return PhoneConstants.APN_REQUEST_STARTED;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001107 } else {
1108 // need to remember this unsupported request so we respond appropriately on stop
1109 synchronized(this) {
1110 mFeatureUsers.add(f);
1111 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
1112 // this gets used for per-pid dns when connected
1113 mNetRequestersPids[usedNetworkType].add(currentPid);
1114 }
Robert Greenwalt5364d752010-12-15 13:26:33 -08001115 }
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001116 return -1;
Robert Greenwalt5364d752010-12-15 13:26:33 -08001117 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001118 }
Wink Saville64e3f782012-07-10 12:37:54 -07001119 return PhoneConstants.APN_TYPE_NOT_AVAILABLE;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001120 } finally {
1121 if (DBG) {
1122 final long execTime = SystemClock.elapsedRealtime() - startTime;
1123 if (execTime > 250) {
1124 loge("startUsingNetworkFeature took too long: " + execTime + "ms");
1125 } else {
1126 if (VDBG) log("startUsingNetworkFeature took " + execTime + "ms");
1127 }
1128 }
1129 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001130 }
1131
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001132 // javadoc from interface
The Android Open Source Project28527d22009-03-03 19:31:44 -08001133 public int stopUsingNetworkFeature(int networkType, String feature) {
Robert Greenwalt28f43012009-10-06 17:52:40 -07001134 enforceChangePermission();
1135
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001136 int pid = getCallingPid();
1137 int uid = getCallingUid();
1138
1139 FeatureUser u = null;
1140 boolean found = false;
1141
1142 synchronized(this) {
Kazuhiro Ondocae18f12011-07-19 11:23:37 -05001143 for (FeatureUser x : mFeatureUsers) {
1144 if (x.isSameUser(pid, uid, networkType, feature)) {
1145 u = x;
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001146 found = true;
1147 break;
1148 }
1149 }
1150 }
1151 if (found && u != null) {
1152 // stop regardless of how many other time this proc had called start
1153 return stopUsingNetworkFeature(u, true);
1154 } else {
1155 // none found!
Wink Savillea7d56572011-09-21 11:05:43 -07001156 if (VDBG) log("stopUsingNetworkFeature - not a live request, ignoring");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001157 return 1;
1158 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001159 }
1160
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001161 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
1162 int networkType = u.mNetworkType;
1163 String feature = u.mFeature;
1164 int pid = u.mPid;
1165 int uid = u.mUid;
1166
1167 NetworkStateTracker tracker = null;
1168 boolean callTeardown = false; // used to carry our decision outside of sync block
1169
Wink Savillea7d56572011-09-21 11:05:43 -07001170 if (VDBG) {
1171 log("stopUsingNetworkFeature: net " + networkType + ": " + feature);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001172 }
Robert Greenwalt28f43012009-10-06 17:52:40 -07001173
The Android Open Source Project28527d22009-03-03 19:31:44 -08001174 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
Wink Savillea7d56572011-09-21 11:05:43 -07001175 if (DBG) {
1176 log("stopUsingNetworkFeature: net " + networkType + ": " + feature +
1177 ", net is invalid");
1178 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001179 return -1;
1180 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001181
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001182 // need to link the mFeatureUsers list with the mNetRequestersPids state in this
1183 // sync block
1184 synchronized(this) {
1185 // check if this process still has an outstanding start request
1186 if (!mFeatureUsers.contains(u)) {
Wink Savillea7d56572011-09-21 11:05:43 -07001187 if (VDBG) {
1188 log("stopUsingNetworkFeature: this process has no outstanding requests" +
1189 ", ignoring");
1190 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001191 return 1;
1192 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001193 u.unlinkDeathRecipient();
1194 mFeatureUsers.remove(mFeatureUsers.indexOf(u));
1195 // If we care about duplicate requests, check for that here.
1196 //
1197 // This is done to support the extension of a request - the app
1198 // can request we start the network feature again and renew the
1199 // auto-shutoff delay. Normal "stop" calls from the app though
1200 // do not pay attention to duplicate requests - in effect the
1201 // API does not refcount and a single stop will counter multiple starts.
1202 if (ignoreDups == false) {
Kazuhiro Ondocae18f12011-07-19 11:23:37 -05001203 for (FeatureUser x : mFeatureUsers) {
1204 if (x.isSameUser(u)) {
Wink Savillea7d56572011-09-21 11:05:43 -07001205 if (VDBG) log("stopUsingNetworkFeature: dup is found, ignoring");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001206 return 1;
1207 }
1208 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001209 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001210
repo syncf5de5572011-07-29 23:55:49 -07001211 // TODO - move to individual network trackers
1212 int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
1213
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001214 tracker = mNetTrackers[usedNetworkType];
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001215 if (tracker == null) {
Wink Savillea7d56572011-09-21 11:05:43 -07001216 if (DBG) {
1217 log("stopUsingNetworkFeature: net " + networkType + ": " + feature +
1218 " no known tracker for used net type " + usedNetworkType);
1219 }
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001220 return -1;
1221 }
1222 if (usedNetworkType != networkType) {
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001223 Integer currentPid = new Integer(pid);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001224 mNetRequestersPids[usedNetworkType].remove(currentPid);
Robert Greenwalt0ca68a02009-12-17 14:54:59 -08001225 reassessPidDns(pid, true);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001226 if (mNetRequestersPids[usedNetworkType].size() != 0) {
Wink Savillea7d56572011-09-21 11:05:43 -07001227 if (VDBG) {
1228 log("stopUsingNetworkFeature: net " + networkType + ": " + feature +
1229 " others still using it");
1230 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001231 return 1;
1232 }
1233 callTeardown = true;
Robert Greenwalt9f3be4c2011-01-10 11:58:31 -08001234 } else {
Wink Savillea7d56572011-09-21 11:05:43 -07001235 if (DBG) {
1236 log("stopUsingNetworkFeature: net " + networkType + ": " + feature +
1237 " not a known feature - dropping");
1238 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001239 }
1240 }
Wink Savillea7d56572011-09-21 11:05:43 -07001241
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001242 if (callTeardown) {
Wink Savillea7d56572011-09-21 11:05:43 -07001243 if (DBG) {
1244 log("stopUsingNetworkFeature: teardown net " + networkType + ": " + feature);
1245 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001246 tracker.teardown();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001247 return 1;
1248 } else {
Robert Greenwaltd391e892010-05-18 10:52:51 -07001249 return -1;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001250 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001251 }
1252
1253 /**
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -07001254 * @deprecated use requestRouteToHostAddress instead
1255 *
The Android Open Source Project28527d22009-03-03 19:31:44 -08001256 * Ensure that a network route exists to deliver traffic to the specified
1257 * host via the specified network interface.
Robert Greenwalt0659da32009-07-16 17:21:39 -07001258 * @param networkType the type of the network over which traffic to the
1259 * specified host is to be routed
1260 * @param hostAddress the IP address of the host to which the route is
1261 * desired
The Android Open Source Project28527d22009-03-03 19:31:44 -08001262 * @return {@code true} on success, {@code false} on failure
1263 */
1264 public boolean requestRouteToHost(int networkType, int hostAddress) {
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -07001265 InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
1266
1267 if (inetAddress == null) {
1268 return false;
1269 }
1270
1271 return requestRouteToHostAddress(networkType, inetAddress.getAddress());
1272 }
1273
1274 /**
1275 * Ensure that a network route exists to deliver traffic to the specified
1276 * host via the specified network interface.
1277 * @param networkType the type of the network over which traffic to the
1278 * specified host is to be routed
1279 * @param hostAddress the IP address of the host to which the route is
1280 * desired
1281 * @return {@code true} on success, {@code false} on failure
1282 */
1283 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001284 enforceChangePermission();
Robert Greenwalt6cac0742011-06-21 17:26:14 -07001285 if (mProtectedNetworks.contains(networkType)) {
1286 enforceConnectivityInternalPermission();
1287 }
1288
The Android Open Source Project28527d22009-03-03 19:31:44 -08001289 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001290 if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001291 return false;
1292 }
1293 NetworkStateTracker tracker = mNetTrackers[networkType];
Robert Greenwalt4666ed02009-09-10 15:06:20 -07001294
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001295 if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
1296 tracker.isTeardownRequested()) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001297 if (VDBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001298 log("requestRouteToHostAddress on down network " +
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -07001299 "(" + networkType + ") - dropped");
Robert Greenwalt4666ed02009-09-10 15:06:20 -07001300 }
1301 return false;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001302 }
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001303 final long token = Binder.clearCallingIdentity();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001304 try {
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -07001305 InetAddress addr = InetAddress.getByAddress(hostAddress);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001306 LinkProperties lp = tracker.getLinkProperties();
Robert Greenwalt98107422011-07-22 11:55:33 -07001307 return addRouteToAddress(lp, addr);
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001308 } catch (UnknownHostException e) {
1309 if (DBG) log("requestRouteToHostAddress got " + e.toString());
1310 } finally {
1311 Binder.restoreCallingIdentity(token);
1312 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001313 return false;
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001314 }
1315
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001316 private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
1317 return modifyRoute(p.getInterfaceName(), p, r, 0, ADD, toDefaultTable);
Robert Greenwaltbd492212011-05-06 17:10:53 -07001318 }
1319
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001320 private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
1321 return modifyRoute(p.getInterfaceName(), p, r, 0, REMOVE, toDefaultTable);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001322 }
1323
Robert Greenwalt98107422011-07-22 11:55:33 -07001324 private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001325 return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE);
Robert Greenwalt98107422011-07-22 11:55:33 -07001326 }
1327
1328 private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001329 return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE);
Robert Greenwalt98107422011-07-22 11:55:33 -07001330 }
1331
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001332 private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd,
1333 boolean toDefaultTable) {
Robert Greenwalt98107422011-07-22 11:55:33 -07001334 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr);
1335 if (bestRoute == null) {
1336 bestRoute = RouteInfo.makeHostRoute(addr);
1337 } else {
1338 if (bestRoute.getGateway().equals(addr)) {
1339 // if there is no better route, add the implied hostroute for our gateway
1340 bestRoute = RouteInfo.makeHostRoute(addr);
1341 } else {
1342 // if we will connect to this through another route, add a direct route
1343 // to it's gateway
1344 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway());
1345 }
1346 }
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001347 return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd, toDefaultTable);
Robert Greenwalt98107422011-07-22 11:55:33 -07001348 }
1349
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001350 private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount,
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001351 boolean doAdd, boolean toDefaultTable) {
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001352 if ((ifaceName == null) || (lp == null) || (r == null)) {
1353 if (DBG) log("modifyRoute got unexpected null: " + ifaceName + ", " + lp + ", " + r);
1354 return false;
1355 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001356
1357 if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001358 loge("Error modifying route - too much recursion");
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001359 return false;
1360 }
1361
1362 if (r.isHostRoute() == false) {
1363 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), r.getGateway());
1364 if (bestRoute != null) {
Robert Greenwalt57c83bb2011-07-15 09:45:08 -07001365 if (bestRoute.getGateway().equals(r.getGateway())) {
1366 // if there is no better route, add the implied hostroute for our gateway
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001367 bestRoute = RouteInfo.makeHostRoute(r.getGateway());
Robert Greenwalt57c83bb2011-07-15 09:45:08 -07001368 } else {
1369 // if we will connect to our gateway through another route, add a direct
1370 // route to it's gateway
1371 bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway());
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001372 }
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001373 modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd, toDefaultTable);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001374 }
1375 }
1376 if (doAdd) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001377 if (VDBG) log("Adding " + r + " for interface " + ifaceName);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001378 try {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001379 if (toDefaultTable) {
1380 mAddedRoutes.add(r); // only track default table - only one apps can effect
1381 mNetd.addRoute(ifaceName, r);
1382 } else {
1383 mNetd.addSecondaryRoute(ifaceName, r);
1384 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001385 } catch (Exception e) {
1386 // never crash - catch them all
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001387 if (DBG) loge("Exception trying to add a route: " + e);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001388 return false;
1389 }
1390 } else {
1391 // if we remove this one and there are no more like it, then refcount==0 and
1392 // we can remove it from the table
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001393 if (toDefaultTable) {
1394 mAddedRoutes.remove(r);
1395 if (mAddedRoutes.contains(r) == false) {
1396 if (VDBG) log("Removing " + r + " for interface " + ifaceName);
1397 try {
1398 mNetd.removeRoute(ifaceName, r);
1399 } catch (Exception e) {
1400 // never crash - catch them all
Robert Greenwalt436db352012-04-23 18:00:37 -07001401 if (VDBG) loge("Exception trying to remove a route: " + e);
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001402 return false;
1403 }
1404 } else {
1405 if (VDBG) log("not removing " + r + " as it's still in use");
1406 }
1407 } else {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001408 if (VDBG) log("Removing " + r + " for interface " + ifaceName);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001409 try {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001410 mNetd.removeSecondaryRoute(ifaceName, r);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001411 } catch (Exception e) {
1412 // never crash - catch them all
Robert Greenwalt436db352012-04-23 18:00:37 -07001413 if (VDBG) loge("Exception trying to remove a route: " + e);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001414 return false;
1415 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001416 }
1417 }
1418 return true;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001419 }
1420
1421 /**
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001422 * @see ConnectivityManager#getMobileDataEnabled()
1423 */
1424 public boolean getMobileDataEnabled() {
Wink Savilleb9024c62010-12-07 10:31:02 -08001425 // TODO: This detail should probably be in DataConnectionTracker's
1426 // which is where we store the value and maybe make this
1427 // asynchronous.
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001428 enforceAccessPermission();
1429 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
1430 Settings.Secure.MOBILE_DATA, 1) == 1;
Robert Greenwalt78f28112011-08-02 17:18:41 -07001431 if (VDBG) log("getMobileDataEnabled returning " + retVal);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001432 return retVal;
1433 }
1434
Robert Greenwalt34848c02011-03-25 13:09:25 -07001435 public void setDataDependency(int networkType, boolean met) {
Robert Greenwalt6cac0742011-06-21 17:26:14 -07001436 enforceConnectivityInternalPermission();
1437
Robert Greenwalt34848c02011-03-25 13:09:25 -07001438 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
1439 (met ? ENABLED : DISABLED), networkType));
1440 }
1441
1442 private void handleSetDependencyMet(int networkType, boolean met) {
1443 if (mNetTrackers[networkType] != null) {
1444 if (DBG) {
1445 log("handleSetDependencyMet(" + networkType + ", " + met + ")");
1446 }
1447 mNetTrackers[networkType].setDependencyMet(met);
1448 }
1449 }
1450
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001451 private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
1452 @Override
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001453 public void onUidRulesChanged(int uid, int uidRules) {
Jeff Sharkeyb1b6ccd2012-02-07 12:05:43 -08001454 // caller is NPMS, since we only register with them
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001455 if (LOGD_RULES) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001456 log("onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001457 }
1458
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001459 synchronized (mRulesLock) {
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001460 // skip update when we've already applied rules
1461 final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL);
1462 if (oldRules == uidRules) return;
1463
1464 mUidRules.put(uid, uidRules);
1465 }
1466
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001467 // TODO: notify UID when it has requested targeted updates
1468 }
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001469
1470 @Override
1471 public void onMeteredIfacesChanged(String[] meteredIfaces) {
Jeff Sharkeyb1b6ccd2012-02-07 12:05:43 -08001472 // caller is NPMS, since we only register with them
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001473 if (LOGD_RULES) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001474 log("onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001475 }
1476
1477 synchronized (mRulesLock) {
1478 mMeteredIfaces.clear();
1479 for (String iface : meteredIfaces) {
1480 mMeteredIfaces.add(iface);
1481 }
1482 }
1483 }
Jeff Sharkeyb1b6ccd2012-02-07 12:05:43 -08001484
1485 @Override
1486 public void onRestrictBackgroundChanged(boolean restrictBackground) {
1487 // caller is NPMS, since we only register with them
1488 if (LOGD_RULES) {
1489 log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
1490 }
1491
1492 // kick off connectivity change broadcast for active network, since
1493 // global background policy change is radical.
1494 final int networkType = mActiveDefaultNetwork;
1495 if (isNetworkTypeValid(networkType)) {
1496 final NetworkStateTracker tracker = mNetTrackers[networkType];
1497 if (tracker != null) {
1498 final NetworkInfo info = tracker.getNetworkInfo();
1499 if (info != null && info.isConnected()) {
1500 sendConnectedBroadcast(info);
1501 }
1502 }
1503 }
1504 }
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001505 };
1506
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001507 /**
1508 * @see ConnectivityManager#setMobileDataEnabled(boolean)
1509 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001510 public void setMobileDataEnabled(boolean enabled) {
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001511 enforceChangePermission();
Wink Savillee70c6f52010-12-03 12:01:38 -08001512 if (DBG) log("setMobileDataEnabled(" + enabled + ")");
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001513
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001514 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
Robert Greenwalt34848c02011-03-25 13:09:25 -07001515 (enabled ? ENABLED : DISABLED), 0));
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001516 }
1517
1518 private void handleSetMobileData(boolean enabled) {
Wink Savilleb9024c62010-12-07 10:31:02 -08001519 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001520 if (VDBG) {
1521 log(mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001522 }
Jeff Sharkey805662d2011-08-19 02:24:24 -07001523 mNetTrackers[ConnectivityManager.TYPE_MOBILE].setUserDataEnable(enabled);
1524 }
tk.mun5eee1042012-01-06 10:43:52 +09001525 if (mNetTrackers[ConnectivityManager.TYPE_WIMAX] != null) {
1526 if (VDBG) {
1527 log(mNetTrackers[ConnectivityManager.TYPE_WIMAX].toString() + enabled);
1528 }
1529 mNetTrackers[ConnectivityManager.TYPE_WIMAX].setUserDataEnable(enabled);
1530 }
Jeff Sharkey805662d2011-08-19 02:24:24 -07001531 }
1532
1533 @Override
1534 public void setPolicyDataEnable(int networkType, boolean enabled) {
1535 // only someone like NPMS should only be calling us
1536 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1537
1538 mHandler.sendMessage(mHandler.obtainMessage(
1539 EVENT_SET_POLICY_DATA_ENABLE, networkType, (enabled ? ENABLED : DISABLED)));
1540 }
1541
1542 private void handleSetPolicyDataEnable(int networkType, boolean enabled) {
1543 if (isNetworkTypeValid(networkType)) {
1544 final NetworkStateTracker tracker = mNetTrackers[networkType];
1545 if (tracker != null) {
1546 tracker.setPolicyDataEnable(enabled);
1547 }
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001548 }
1549 }
1550
The Android Open Source Project28527d22009-03-03 19:31:44 -08001551 private void enforceAccessPermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001552 mContext.enforceCallingOrSelfPermission(
1553 android.Manifest.permission.ACCESS_NETWORK_STATE,
1554 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001555 }
1556
1557 private void enforceChangePermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001558 mContext.enforceCallingOrSelfPermission(
1559 android.Manifest.permission.CHANGE_NETWORK_STATE,
1560 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001561 }
1562
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001563 // TODO Make this a special check when it goes public
1564 private void enforceTetherChangePermission() {
1565 mContext.enforceCallingOrSelfPermission(
1566 android.Manifest.permission.CHANGE_NETWORK_STATE,
1567 "ConnectivityService");
1568 }
1569
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001570 private void enforceTetherAccessPermission() {
1571 mContext.enforceCallingOrSelfPermission(
1572 android.Manifest.permission.ACCESS_NETWORK_STATE,
1573 "ConnectivityService");
1574 }
1575
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001576 private void enforceConnectivityInternalPermission() {
1577 mContext.enforceCallingOrSelfPermission(
1578 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1579 "ConnectivityService");
1580 }
1581
The Android Open Source Project28527d22009-03-03 19:31:44 -08001582 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -07001583 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
1584 * network, we ignore it. If it is for the active network, we send out a
1585 * broadcast. But first, we check whether it might be possible to connect
1586 * to a different network.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001587 * @param info the {@code NetworkInfo} for the network
1588 */
1589 private void handleDisconnect(NetworkInfo info) {
1590
Robert Greenwalt2034b912009-08-12 16:08:25 -07001591 int prevNetType = info.getType();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001592
Robert Greenwalt2034b912009-08-12 16:08:25 -07001593 mNetTrackers[prevNetType].setTeardownRequested(false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001594 /*
1595 * If the disconnected network is not the active one, then don't report
1596 * this as a loss of connectivity. What probably happened is that we're
1597 * getting the disconnect for a network that we explicitly disabled
1598 * in accordance with network preference policies.
1599 */
Robert Greenwalt34848c02011-03-25 13:09:25 -07001600 if (!mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001601 List pids = mNetRequestersPids[prevNetType];
1602 for (int i = 0; i<pids.size(); i++) {
1603 Integer pid = (Integer)pids.get(i);
1604 // will remove them because the net's no longer connected
1605 // need to do this now as only now do we know the pids and
1606 // can properly null things that are no longer referenced.
1607 reassessPidDns(pid.intValue(), false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001608 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001609 }
1610
The Android Open Source Project28527d22009-03-03 19:31:44 -08001611 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1612 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1613 if (info.isFailover()) {
1614 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1615 info.setFailover(false);
1616 }
1617 if (info.getReason() != null) {
1618 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1619 }
1620 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001621 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1622 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001623 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001624
Robert Greenwalt34848c02011-03-25 13:09:25 -07001625 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001626 tryFailover(prevNetType);
1627 if (mActiveDefaultNetwork != -1) {
1628 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001629 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1630 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001631 mDefaultInetConditionPublished = 0; // we're not connected anymore
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001632 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1633 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001634 }
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001635 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001636
1637 // Reset interface if no other connections are using the same interface
1638 boolean doReset = true;
1639 LinkProperties linkProperties = mNetTrackers[prevNetType].getLinkProperties();
1640 if (linkProperties != null) {
1641 String oldIface = linkProperties.getInterfaceName();
1642 if (TextUtils.isEmpty(oldIface) == false) {
1643 for (NetworkStateTracker networkStateTracker : mNetTrackers) {
1644 if (networkStateTracker == null) continue;
1645 NetworkInfo networkInfo = networkStateTracker.getNetworkInfo();
1646 if (networkInfo.isConnected() && networkInfo.getType() != prevNetType) {
1647 LinkProperties l = networkStateTracker.getLinkProperties();
1648 if (l == null) continue;
1649 if (oldIface.equals(l.getInterfaceName())) {
1650 doReset = false;
1651 break;
1652 }
1653 }
1654 }
1655 }
1656 }
1657
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001658 // do this before we broadcast the change
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001659 handleConnectivityChange(prevNetType, doReset);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001660
Jeff Sharkey971cd162011-08-29 16:02:57 -07001661 final Intent immediateIntent = new Intent(intent);
1662 immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
1663 sendStickyBroadcast(immediateIntent);
Wink Saville4f0de1e2011-08-04 15:01:58 -07001664 sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001665 /*
1666 * If the failover network is already connected, then immediately send
1667 * out a followup broadcast indicating successful failover
1668 */
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001669 if (mActiveDefaultNetwork != -1) {
Wink Saville4f0de1e2011-08-04 15:01:58 -07001670 sendConnectedBroadcastDelayed(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(),
1671 getConnectivityChangeDelay());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001672 }
1673 }
1674
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001675 private void tryFailover(int prevNetType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001676 /*
Robert Greenwalt92564852011-01-06 15:41:07 -08001677 * If this is a default network, check if other defaults are available.
1678 * Try to reconnect on all available and let them hash it out when
1679 * more than one connects.
Robert Greenwalt2034b912009-08-12 16:08:25 -07001680 */
Robert Greenwalt34848c02011-03-25 13:09:25 -07001681 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001682 if (mActiveDefaultNetwork == prevNetType) {
1683 mActiveDefaultNetwork = -1;
1684 }
1685
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001686 // don't signal a reconnect for anything lower or equal priority than our
1687 // current connected default
1688 // TODO - don't filter by priority now - nice optimization but risky
1689// int currentPriority = -1;
1690// if (mActiveDefaultNetwork != -1) {
Robert Greenwalt34848c02011-03-25 13:09:25 -07001691// currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority;
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001692// }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001693 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001694 if (checkType == prevNetType) continue;
Robert Greenwalt34848c02011-03-25 13:09:25 -07001695 if (mNetConfigs[checkType] == null) continue;
1696 if (!mNetConfigs[checkType].isDefault()) continue;
Robert Greenwaltbc026d02011-11-11 09:56:03 -08001697 if (mNetTrackers[checkType] == null) continue;
Wink Saville72a95b92011-01-26 15:43:49 -08001698
1699// Enabling the isAvailable() optimization caused mobile to not get
1700// selected if it was in the middle of error handling. Specifically
1701// a moble connection that took 30 seconds to complete the DEACTIVATE_DATA_CALL
1702// would not be available and we wouldn't get connected to anything.
1703// So removing the isAvailable() optimization below for now. TODO: This
1704// optimization should work and we need to investigate why it doesn't work.
1705// This could be related to how DEACTIVATE_DATA_CALL is reporting its
1706// complete before it is really complete.
1707// if (!mNetTrackers[checkType].isAvailable()) continue;
1708
Robert Greenwalt34848c02011-03-25 13:09:25 -07001709// if (currentPriority >= mNetConfigs[checkType].mPriority) continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001710
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001711 NetworkStateTracker checkTracker = mNetTrackers[checkType];
1712 NetworkInfo checkInfo = checkTracker.getNetworkInfo();
1713 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
1714 checkInfo.setFailover(true);
1715 checkTracker.reconnect();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001716 }
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001717 if (DBG) log("Attempting to switch to " + checkInfo.getTypeName());
Robert Greenwalt2034b912009-08-12 16:08:25 -07001718 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001719 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001720 }
1721
1722 private void sendConnectedBroadcast(NetworkInfo info) {
Jeff Sharkey971cd162011-08-29 16:02:57 -07001723 sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
1724 sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001725 }
1726
Wink Saville4f0de1e2011-08-04 15:01:58 -07001727 private void sendConnectedBroadcastDelayed(NetworkInfo info, int delayMs) {
Jeff Sharkey971cd162011-08-29 16:02:57 -07001728 sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
1729 sendGeneralBroadcastDelayed(info, CONNECTIVITY_ACTION, delayMs);
Wink Saville4f0de1e2011-08-04 15:01:58 -07001730 }
1731
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001732 private void sendInetConditionBroadcast(NetworkInfo info) {
1733 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1734 }
1735
Wink Saville4f0de1e2011-08-04 15:01:58 -07001736 private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001737 Intent intent = new Intent(bcastType);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001738 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1739 if (info.isFailover()) {
1740 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1741 info.setFailover(false);
1742 }
1743 if (info.getReason() != null) {
1744 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1745 }
1746 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001747 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1748 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001749 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07001750 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Wink Saville4f0de1e2011-08-04 15:01:58 -07001751 return intent;
1752 }
1753
1754 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1755 sendStickyBroadcast(makeGeneralIntent(info, bcastType));
1756 }
1757
1758 private void sendGeneralBroadcastDelayed(NetworkInfo info, String bcastType, int delayMs) {
1759 sendStickyBroadcastDelayed(makeGeneralIntent(info, bcastType), delayMs);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001760 }
1761
1762 /**
1763 * Called when an attempt to fail over to another network has failed.
1764 * @param info the {@link NetworkInfo} for the failed network
1765 */
1766 private void handleConnectionFailure(NetworkInfo info) {
1767 mNetTrackers[info.getType()].setTeardownRequested(false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001768
Robert Greenwalt2034b912009-08-12 16:08:25 -07001769 String reason = info.getReason();
1770 String extraInfo = info.getExtraInfo();
Robert Greenwalt0659da32009-07-16 17:21:39 -07001771
Robert Greenwalte981bc52010-10-08 16:35:52 -07001772 String reasonText;
1773 if (reason == null) {
1774 reasonText = ".";
1775 } else {
1776 reasonText = " (" + reason + ").";
The Android Open Source Project28527d22009-03-03 19:31:44 -08001777 }
Wink Savillee70c6f52010-12-03 12:01:38 -08001778 loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001779
1780 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1781 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1782 if (getActiveNetworkInfo() == null) {
1783 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1784 }
1785 if (reason != null) {
1786 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
1787 }
1788 if (extraInfo != null) {
1789 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
1790 }
1791 if (info.isFailover()) {
1792 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1793 info.setFailover(false);
1794 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001795
Robert Greenwalt34848c02011-03-25 13:09:25 -07001796 if (mNetConfigs[info.getType()].isDefault()) {
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001797 tryFailover(info.getType());
1798 if (mActiveDefaultNetwork != -1) {
1799 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001800 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1801 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001802 mDefaultInetConditionPublished = 0;
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001803 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1804 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001805 }
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001806
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001807 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Jeff Sharkey971cd162011-08-29 16:02:57 -07001808
1809 final Intent immediateIntent = new Intent(intent);
1810 immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
1811 sendStickyBroadcast(immediateIntent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001812 sendStickyBroadcast(intent);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001813 /*
1814 * If the failover network is already connected, then immediately send
1815 * out a followup broadcast indicating successful failover
1816 */
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001817 if (mActiveDefaultNetwork != -1) {
1818 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001819 }
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001820 }
1821
1822 private void sendStickyBroadcast(Intent intent) {
1823 synchronized(this) {
Dianne Hackborna417ff82009-12-08 19:45:14 -08001824 if (!mSystemReady) {
1825 mInitialBroadcast = new Intent(intent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001826 }
Dianne Hackborna417ff82009-12-08 19:45:14 -08001827 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Wink Savillea7d56572011-09-21 11:05:43 -07001828 if (VDBG) {
Jeff Sharkey971cd162011-08-29 16:02:57 -07001829 log("sendStickyBroadcast: action=" + intent.getAction());
Wink Saville4f0de1e2011-08-04 15:01:58 -07001830 }
1831
Dianne Hackborna417ff82009-12-08 19:45:14 -08001832 mContext.sendStickyBroadcast(intent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001833 }
1834 }
1835
Wink Saville4f0de1e2011-08-04 15:01:58 -07001836 private void sendStickyBroadcastDelayed(Intent intent, int delayMs) {
1837 if (delayMs <= 0) {
1838 sendStickyBroadcast(intent);
1839 } else {
Wink Savillea7d56572011-09-21 11:05:43 -07001840 if (VDBG) {
Jeff Sharkey971cd162011-08-29 16:02:57 -07001841 log("sendStickyBroadcastDelayed: delayMs=" + delayMs + ", action="
1842 + intent.getAction());
1843 }
Wink Saville4f0de1e2011-08-04 15:01:58 -07001844 mHandler.sendMessageDelayed(mHandler.obtainMessage(
1845 EVENT_SEND_STICKY_BROADCAST_INTENT, intent), delayMs);
1846 }
1847 }
1848
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001849 void systemReady() {
1850 synchronized(this) {
1851 mSystemReady = true;
Dianne Hackborna417ff82009-12-08 19:45:14 -08001852 if (mInitialBroadcast != null) {
1853 mContext.sendStickyBroadcast(mInitialBroadcast);
1854 mInitialBroadcast = null;
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001855 }
1856 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07001857 // load the global proxy at startup
1858 mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
The Android Open Source Project28527d22009-03-03 19:31:44 -08001859 }
1860
1861 private void handleConnect(NetworkInfo info) {
Jeff Sharkeyaac2c502011-10-04 16:54:49 -07001862 final int type = info.getType();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001863
1864 // snapshot isFailover, because sendConnectedBroadcast() resets it
1865 boolean isFailover = info.isFailover();
Jeff Sharkeyaac2c502011-10-04 16:54:49 -07001866 final NetworkStateTracker thisNet = mNetTrackers[type];
The Android Open Source Project28527d22009-03-03 19:31:44 -08001867
Robert Greenwalt2034b912009-08-12 16:08:25 -07001868 // if this is a default net and other default is running
1869 // kill the one not preferred
Robert Greenwalt34848c02011-03-25 13:09:25 -07001870 if (mNetConfigs[type].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001871 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
1872 if ((type != mNetworkPreference &&
Wink Savillef2a62832011-04-07 14:23:45 -07001873 mNetConfigs[mActiveDefaultNetwork].priority >
1874 mNetConfigs[type].priority) ||
Robert Greenwalt2034b912009-08-12 16:08:25 -07001875 mNetworkPreference == mActiveDefaultNetwork) {
1876 // don't accept this one
Robert Greenwalt78f28112011-08-02 17:18:41 -07001877 if (VDBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001878 log("Not broadcasting CONNECT_ACTION " +
Robert Greenwalt2034b912009-08-12 16:08:25 -07001879 "to torn down network " + info.getTypeName());
Wink Savillee70c6f52010-12-03 12:01:38 -08001880 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001881 teardown(thisNet);
1882 return;
1883 } else {
1884 // tear down the other
1885 NetworkStateTracker otherNet =
1886 mNetTrackers[mActiveDefaultNetwork];
Wink Savillee70c6f52010-12-03 12:01:38 -08001887 if (DBG) {
1888 log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
Robert Greenwalt2034b912009-08-12 16:08:25 -07001889 " teardown");
Wink Savillee70c6f52010-12-03 12:01:38 -08001890 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001891 if (!teardown(otherNet)) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001892 loge("Network declined teardown request");
Robert Greenwalt99910172011-03-29 11:36:28 -07001893 teardown(thisNet);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001894 return;
1895 }
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001896 }
1897 }
1898 synchronized (ConnectivityService.this) {
1899 // have a new default network, release the transition wakelock in a second
1900 // if it's held. The second pause is to allow apps to reconnect over the
1901 // new network
1902 if (mNetTransitionWakeLock.isHeld()) {
1903 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltccb36f92010-09-24 14:32:21 -07001904 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001905 mNetTransitionWakeLockSerialNumber, 0),
1906 1000);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001907 }
1908 }
1909 mActiveDefaultNetwork = type;
Robert Greenwalt986c7412010-09-08 15:24:47 -07001910 // this will cause us to come up initially as unconnected and switching
1911 // to connected after our normal pause unless somebody reports us as reall
1912 // disconnected
1913 mDefaultInetConditionPublished = 0;
1914 mDefaultConnectionSequence++;
1915 mInetConditionChangeInFlight = false;
1916 // Don't do this - if we never sign in stay, grey
1917 //reportNetworkCondition(mActiveDefaultNetwork, 100);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001918 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001919 thisNet.setTeardownRequested(false);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001920 updateNetworkSettings(thisNet);
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001921 handleConnectivityChange(type, false);
Wink Saville4f0de1e2011-08-04 15:01:58 -07001922 sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
Jeff Sharkeyaac2c502011-10-04 16:54:49 -07001923
1924 // notify battery stats service about this network
1925 final String iface = thisNet.getLinkProperties().getInterfaceName();
1926 if (iface != null) {
1927 try {
1928 BatteryStatsService.getService().noteNetworkInterfaceType(iface, type);
1929 } catch (RemoteException e) {
1930 // ignored; service lives in system_server
1931 }
1932 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001933 }
1934
The Android Open Source Project28527d22009-03-03 19:31:44 -08001935 /**
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001936 * After a change in the connectivity state of a network. We're mainly
1937 * concerned with making sure that the list of DNS servers is set up
1938 * according to which networks are connected, and ensuring that the
1939 * right routing table entries exist.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001940 */
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001941 private void handleConnectivityChange(int netType, boolean doReset) {
Wink Saville051a6642011-07-13 13:44:13 -07001942 int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0;
1943
The Android Open Source Project28527d22009-03-03 19:31:44 -08001944 /*
Robert Greenwalt2034b912009-08-12 16:08:25 -07001945 * If a non-default network is enabled, add the host routes that
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001946 * will allow it's DNS servers to be accessed.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001947 */
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001948 handleDnsConfigurationChange(netType);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001949
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001950 LinkProperties curLp = mCurrentLinkProperties[netType];
1951 LinkProperties newLp = null;
1952
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001953 if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001954 newLp = mNetTrackers[netType].getLinkProperties();
Wink Saville051a6642011-07-13 13:44:13 -07001955 if (VDBG) {
1956 log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
1957 " doReset=" + doReset + " resetMask=" + resetMask +
1958 "\n curLp=" + curLp +
1959 "\n newLp=" + newLp);
1960 }
1961
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001962 if (curLp != null) {
1963 if (curLp.isIdenticalInterfaceName(newLp)) {
1964 CompareResult<LinkAddress> car = curLp.compareAddresses(newLp);
1965 if ((car.removed.size() != 0) || (car.added.size() != 0)) {
1966 for (LinkAddress linkAddr : car.removed) {
1967 if (linkAddr.getAddress() instanceof Inet4Address) {
1968 resetMask |= NetworkUtils.RESET_IPV4_ADDRESSES;
1969 }
1970 if (linkAddr.getAddress() instanceof Inet6Address) {
1971 resetMask |= NetworkUtils.RESET_IPV6_ADDRESSES;
1972 }
Wink Saville051a6642011-07-13 13:44:13 -07001973 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001974 if (DBG) {
1975 log("handleConnectivityChange: addresses changed" +
1976 " linkProperty[" + netType + "]:" + " resetMask=" + resetMask +
1977 "\n car=" + car);
Wink Saville051a6642011-07-13 13:44:13 -07001978 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001979 } else {
1980 if (DBG) {
1981 log("handleConnectivityChange: address are the same reset per doReset" +
1982 " linkProperty[" + netType + "]:" +
1983 " resetMask=" + resetMask);
1984 }
Wink Saville051a6642011-07-13 13:44:13 -07001985 }
1986 } else {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001987 resetMask = NetworkUtils.RESET_ALL_ADDRESSES;
Robert Greenwalt78f28112011-08-02 17:18:41 -07001988 if (DBG) {
1989 log("handleConnectivityChange: interface not not equivalent reset both" +
1990 " linkProperty[" + netType + "]:" +
1991 " resetMask=" + resetMask);
1992 }
Wink Saville051a6642011-07-13 13:44:13 -07001993 }
Wink Saville051a6642011-07-13 13:44:13 -07001994 }
Robert Greenwalt34848c02011-03-25 13:09:25 -07001995 if (mNetConfigs[netType].isDefault()) {
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07001996 handleApplyDefaultProxy(newLp.getHttpProxy());
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001997 }
1998 } else {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001999 if (VDBG) {
2000 log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
2001 " doReset=" + doReset + " resetMask=" + resetMask +
2002 "\n curLp=" + curLp +
2003 "\n newLp= null");
Robert Greenwalt2034b912009-08-12 16:08:25 -07002004 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002005 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002006 mCurrentLinkProperties[netType] = newLp;
Robert Greenwalt8d777252011-08-15 12:31:55 -07002007 boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault());
Robert Greenwalt36ea8692011-06-15 12:22:07 -07002008
Chia-chi Yeh4a243f52011-08-15 15:19:40 -07002009 if (resetMask != 0 || resetDns) {
Robert Greenwalt36ea8692011-06-15 12:22:07 -07002010 LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties();
2011 if (linkProperties != null) {
2012 String iface = linkProperties.getInterfaceName();
2013 if (TextUtils.isEmpty(iface) == false) {
Chia-chi Yeh4a243f52011-08-15 15:19:40 -07002014 if (resetMask != 0) {
Robert Greenwalt8d777252011-08-15 12:31:55 -07002015 if (DBG) log("resetConnections(" + iface + ", " + resetMask + ")");
2016 NetworkUtils.resetConnections(iface, resetMask);
Chia-chi Yeh4a243f52011-08-15 15:19:40 -07002017
2018 // Tell VPN the interface is down. It is a temporary
2019 // but effective fix to make VPN aware of the change.
2020 if ((resetMask & NetworkUtils.RESET_IPV4_ADDRESSES) != 0) {
2021 mVpn.interfaceStatusChanged(iface, false);
2022 }
Robert Greenwalt8d777252011-08-15 12:31:55 -07002023 }
2024 if (resetDns) {
Wink Savillea7d56572011-09-21 11:05:43 -07002025 if (VDBG) log("resetting DNS cache for " + iface);
Robert Greenwalt8d777252011-08-15 12:31:55 -07002026 try {
2027 mNetd.flushInterfaceDnsCache(iface);
2028 } catch (Exception e) {
2029 // never crash - catch them all
Wink Savillea7d56572011-09-21 11:05:43 -07002030 if (DBG) loge("Exception resetting dns cache: " + e);
Robert Greenwalt8d777252011-08-15 12:31:55 -07002031 }
2032 }
Robert Greenwalt36ea8692011-06-15 12:22:07 -07002033 }
2034 }
2035 }
Kazuhiro Ondo07680062011-06-22 21:10:34 -05002036
2037 // TODO: Temporary notifying upstread change to Tethering.
2038 // @see bug/4455071
2039 /** Notify TetheringService if interface name has been changed. */
2040 if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
Wink Saville64e3f782012-07-10 12:37:54 -07002041 PhoneConstants.REASON_LINK_PROPERTIES_CHANGED)) {
Kazuhiro Ondo07680062011-06-22 21:10:34 -05002042 if (isTetheringSupported()) {
2043 mTethering.handleTetherIfaceChange();
2044 }
2045 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002046 }
2047
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002048 /**
2049 * Add and remove routes using the old properties (null if not previously connected),
2050 * new properties (null if becoming disconnected). May even be double null, which
2051 * is a noop.
2052 * Uses isLinkDefault to determine if default routes should be set or conversely if
2053 * host routes should be set to the dns servers
Robert Greenwalt8d777252011-08-15 12:31:55 -07002054 * returns a boolean indicating the routes changed
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002055 */
Robert Greenwalt8d777252011-08-15 12:31:55 -07002056 private boolean updateRoutes(LinkProperties newLp, LinkProperties curLp,
2057 boolean isLinkDefault) {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002058 Collection<RouteInfo> routesToAdd = null;
Robert Greenwalt98107422011-07-22 11:55:33 -07002059 CompareResult<InetAddress> dnsDiff = new CompareResult<InetAddress>();
2060 CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>();
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002061 if (curLp != null) {
2062 // check for the delta between the current set and the new
Robert Greenwalt98107422011-07-22 11:55:33 -07002063 routeDiff = curLp.compareRoutes(newLp);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002064 dnsDiff = curLp.compareDnses(newLp);
Robert Greenwalt98107422011-07-22 11:55:33 -07002065 } else if (newLp != null) {
2066 routeDiff.added = newLp.getRoutes();
2067 dnsDiff.added = newLp.getDnses();
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002068 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002069
Robert Greenwalt8d777252011-08-15 12:31:55 -07002070 boolean routesChanged = (routeDiff.removed.size() != 0 || routeDiff.added.size() != 0);
2071
Robert Greenwalt98107422011-07-22 11:55:33 -07002072 for (RouteInfo r : routeDiff.removed) {
2073 if (isLinkDefault || ! r.isDefaultRoute()) {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07002074 removeRoute(curLp, r, TO_DEFAULT_TABLE);
2075 }
2076 if (isLinkDefault == false) {
2077 // remove from a secondary route table
2078 removeRoute(curLp, r, TO_SECONDARY_TABLE);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002079 }
Robert Greenwalt98107422011-07-22 11:55:33 -07002080 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002081
Robert Greenwalt98107422011-07-22 11:55:33 -07002082 for (RouteInfo r : routeDiff.added) {
2083 if (isLinkDefault || ! r.isDefaultRoute()) {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07002084 addRoute(newLp, r, TO_DEFAULT_TABLE);
Robert Greenwalt08ae9bc2011-08-09 16:52:58 -07002085 } else {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07002086 // add to a secondary route table
2087 addRoute(newLp, r, TO_SECONDARY_TABLE);
2088
Robert Greenwalt08ae9bc2011-08-09 16:52:58 -07002089 // many radios add a default route even when we don't want one.
2090 // remove the default route unless somebody else has asked for it
2091 String ifaceName = newLp.getInterfaceName();
2092 if (TextUtils.isEmpty(ifaceName) == false && mAddedRoutes.contains(r) == false) {
Wink Savillea7d56572011-09-21 11:05:43 -07002093 if (VDBG) log("Removing " + r + " for interface " + ifaceName);
Robert Greenwalt08ae9bc2011-08-09 16:52:58 -07002094 try {
2095 mNetd.removeRoute(ifaceName, r);
2096 } catch (Exception e) {
2097 // never crash - catch them all
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08002098 if (DBG) loge("Exception trying to remove a route: " + e);
Robert Greenwalt08ae9bc2011-08-09 16:52:58 -07002099 }
2100 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002101 }
2102 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002103
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002104 if (!isLinkDefault) {
2105 // handle DNS routes
Robert Greenwalt8d777252011-08-15 12:31:55 -07002106 if (routesChanged) {
Robert Greenwalt98107422011-07-22 11:55:33 -07002107 // routes changed - remove all old dns entries and add new
2108 if (curLp != null) {
2109 for (InetAddress oldDns : curLp.getDnses()) {
2110 removeRouteToAddress(curLp, oldDns);
2111 }
2112 }
2113 if (newLp != null) {
2114 for (InetAddress newDns : newLp.getDnses()) {
2115 addRouteToAddress(newLp, newDns);
2116 }
Robert Greenwalt03d53da2011-03-22 18:47:42 -07002117 }
Robert Greenwalt8d777252011-08-15 12:31:55 -07002118 } else {
2119 // no change in routes, check for change in dns themselves
2120 for (InetAddress oldDns : dnsDiff.removed) {
2121 removeRouteToAddress(curLp, oldDns);
2122 }
2123 for (InetAddress newDns : dnsDiff.added) {
2124 addRouteToAddress(newLp, newDns);
2125 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002126 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002127 }
Robert Greenwalt8d777252011-08-15 12:31:55 -07002128 return routesChanged;
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002129 }
2130
2131
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002132 /**
2133 * Reads the network specific TCP buffer sizes from SystemProperties
2134 * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
2135 * wide use
2136 */
2137 public void updateNetworkSettings(NetworkStateTracker nt) {
2138 String key = nt.getTcpBufferSizesPropName();
2139 String bufferSizes = SystemProperties.get(key);
2140
2141 if (bufferSizes.length() == 0) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002142 if (VDBG) log(key + " not found in system properties. Using defaults");
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002143
2144 // Setting to default values so we won't be stuck to previous values
2145 key = "net.tcp.buffersize.default";
2146 bufferSizes = SystemProperties.get(key);
2147 }
2148
2149 // Set values in kernel
2150 if (bufferSizes.length() != 0) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002151 if (VDBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002152 log("Setting TCP values: [" + bufferSizes
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002153 + "] which comes from [" + key + "]");
2154 }
2155 setBufferSize(bufferSizes);
2156 }
2157 }
2158
2159 /**
2160 * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max]
2161 * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem
2162 *
2163 * @param bufferSizes in the format of "readMin, readInitial, readMax,
2164 * writeMin, writeInitial, writeMax"
2165 */
2166 private void setBufferSize(String bufferSizes) {
2167 try {
2168 String[] values = bufferSizes.split(",");
2169
2170 if (values.length == 6) {
2171 final String prefix = "/sys/kernel/ipv4/tcp_";
Mike Lockwood0d5916c2011-05-28 13:24:04 -04002172 FileUtils.stringToFile(prefix + "rmem_min", values[0]);
2173 FileUtils.stringToFile(prefix + "rmem_def", values[1]);
2174 FileUtils.stringToFile(prefix + "rmem_max", values[2]);
2175 FileUtils.stringToFile(prefix + "wmem_min", values[3]);
2176 FileUtils.stringToFile(prefix + "wmem_def", values[4]);
2177 FileUtils.stringToFile(prefix + "wmem_max", values[5]);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002178 } else {
Wink Savillee70c6f52010-12-03 12:01:38 -08002179 loge("Invalid buffersize string: " + bufferSizes);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002180 }
2181 } catch (IOException e) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002182 loge("Can't set tcp buffer sizes:" + e);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002183 }
2184 }
2185
Robert Greenwalt2034b912009-08-12 16:08:25 -07002186 /**
2187 * Adjust the per-process dns entries (net.dns<x>.<pid>) based
2188 * on the highest priority active net which this process requested.
2189 * If there aren't any, clear it out
2190 */
2191 private void reassessPidDns(int myPid, boolean doBump)
2192 {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002193 if (VDBG) log("reassessPidDns for pid " + myPid);
Robert Greenwalt2034b912009-08-12 16:08:25 -07002194 for(int i : mPriorityList) {
Robert Greenwalt34848c02011-03-25 13:09:25 -07002195 if (mNetConfigs[i].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07002196 continue;
2197 }
2198 NetworkStateTracker nt = mNetTrackers[i];
Robert Greenwalt0659da32009-07-16 17:21:39 -07002199 if (nt.getNetworkInfo().isConnected() &&
2200 !nt.isTeardownRequested()) {
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07002201 LinkProperties p = nt.getLinkProperties();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07002202 if (p == null) continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -07002203 List pids = mNetRequestersPids[i];
2204 for (int j=0; j<pids.size(); j++) {
2205 Integer pid = (Integer)pids.get(j);
2206 if (pid.intValue() == myPid) {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07002207 Collection<InetAddress> dnses = p.getDnses();
Lorenzo Colittiaa035382011-09-28 22:31:45 -07002208 writePidDns(dnses, myPid);
Robert Greenwalt2034b912009-08-12 16:08:25 -07002209 if (doBump) {
2210 bumpDns();
2211 }
2212 return;
2213 }
2214 }
2215 }
2216 }
2217 // nothing found - delete
2218 for (int i = 1; ; i++) {
2219 String prop = "net.dns" + i + "." + myPid;
2220 if (SystemProperties.get(prop).length() == 0) {
2221 if (doBump) {
2222 bumpDns();
2223 }
2224 return;
2225 }
2226 SystemProperties.set(prop, "");
2227 }
2228 }
2229
Robert Greenwalt8ca88762010-12-17 15:20:36 -08002230 // return true if results in a change
Lorenzo Colittiaa035382011-09-28 22:31:45 -07002231 private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07002232 int j = 1;
Robert Greenwalt8ca88762010-12-17 15:20:36 -08002233 boolean changed = false;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07002234 for (InetAddress dns : dnses) {
Robert Greenwalt8ca88762010-12-17 15:20:36 -08002235 String dnsString = dns.getHostAddress();
2236 if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
2237 changed = true;
yoonsung.nam48d18332012-03-02 19:56:16 +09002238 SystemProperties.set("net.dns" + j + "." + pid, dns.getHostAddress());
Robert Greenwalt8ca88762010-12-17 15:20:36 -08002239 }
yoonsung.nam48d18332012-03-02 19:56:16 +09002240 j++;
Robert Greenwalt2034b912009-08-12 16:08:25 -07002241 }
Robert Greenwalt8ca88762010-12-17 15:20:36 -08002242 return changed;
Robert Greenwalt2034b912009-08-12 16:08:25 -07002243 }
2244
2245 private void bumpDns() {
2246 /*
2247 * Bump the property that tells the name resolver library to reread
2248 * the DNS server list from the properties.
2249 */
2250 String propVal = SystemProperties.get("net.dnschange");
2251 int n = 0;
2252 if (propVal.length() != 0) {
2253 try {
2254 n = Integer.parseInt(propVal);
2255 } catch (NumberFormatException e) {}
2256 }
2257 SystemProperties.set("net.dnschange", "" + (n+1));
Robert Greenwalt051642b2010-11-02 14:08:23 -07002258 /*
2259 * Tell the VMs to toss their DNS caches
2260 */
2261 Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
2262 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Stan Chesnuttf444f502011-01-05 17:14:03 -08002263 /*
2264 * Connectivity events can happen before boot has completed ...
2265 */
2266 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt051642b2010-11-02 14:08:23 -07002267 mContext.sendBroadcast(intent);
Robert Greenwalt2034b912009-08-12 16:08:25 -07002268 }
2269
Chia-chi Yehcc844502011-07-14 18:01:57 -07002270 // Caller must grab mDnsLock.
Robert Greenwaltfce71862011-07-25 16:06:25 -07002271 private boolean updateDns(String network, String iface,
Lorenzo Colittiaa035382011-09-28 22:31:45 -07002272 Collection<InetAddress> dnses, String domains) {
Chia-chi Yehcc844502011-07-14 18:01:57 -07002273 boolean changed = false;
2274 int last = 0;
2275 if (dnses.size() == 0 && mDefaultDns != null) {
2276 ++last;
2277 String value = mDefaultDns.getHostAddress();
2278 if (!value.equals(SystemProperties.get("net.dns1"))) {
2279 if (DBG) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002280 loge("no dns provided for " + network + " - using " + value);
Chia-chi Yehcc844502011-07-14 18:01:57 -07002281 }
2282 changed = true;
2283 SystemProperties.set("net.dns1", value);
2284 }
2285 } else {
2286 for (InetAddress dns : dnses) {
2287 ++last;
2288 String key = "net.dns" + last;
2289 String value = dns.getHostAddress();
2290 if (!changed && value.equals(SystemProperties.get(key))) {
2291 continue;
2292 }
Robert Greenwalt78f28112011-08-02 17:18:41 -07002293 if (VDBG) {
Chia-chi Yehcc844502011-07-14 18:01:57 -07002294 log("adding dns " + value + " for " + network);
2295 }
2296 changed = true;
2297 SystemProperties.set(key, value);
2298 }
2299 }
2300 for (int i = last + 1; i <= mNumDnsEntries; ++i) {
2301 String key = "net.dns" + i;
Robert Greenwalt78f28112011-08-02 17:18:41 -07002302 if (VDBG) log("erasing " + key);
Chia-chi Yehcc844502011-07-14 18:01:57 -07002303 changed = true;
2304 SystemProperties.set(key, "");
2305 }
2306 mNumDnsEntries = last;
2307
Robert Greenwaltfce71862011-07-25 16:06:25 -07002308 if (changed) {
2309 try {
2310 mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses));
2311 mNetd.setDefaultInterfaceForDns(iface);
2312 } catch (Exception e) {
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08002313 if (DBG) loge("exception setting default dns interface: " + e);
Robert Greenwaltfce71862011-07-25 16:06:25 -07002314 }
2315 }
Chia-chi Yehcc844502011-07-14 18:01:57 -07002316 if (!domains.equals(SystemProperties.get("net.dns.search"))) {
2317 SystemProperties.set("net.dns.search", domains);
2318 changed = true;
2319 }
2320 return changed;
2321 }
2322
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002323 private void handleDnsConfigurationChange(int netType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07002324 // add default net's dns entries
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002325 NetworkStateTracker nt = mNetTrackers[netType];
2326 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07002327 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002328 if (p == null) return;
2329 Collection<InetAddress> dnses = p.getDnses();
Robert Greenwalt8ca88762010-12-17 15:20:36 -08002330 boolean changed = false;
Robert Greenwalt34848c02011-03-25 13:09:25 -07002331 if (mNetConfigs[netType].isDefault()) {
Chia-chi Yehcc844502011-07-14 18:01:57 -07002332 String network = nt.getNetworkInfo().getTypeName();
2333 synchronized (mDnsLock) {
2334 if (!mDnsOverridden) {
Lorenzo Colittiaa035382011-09-28 22:31:45 -07002335 changed = updateDns(network, p.getInterfaceName(), dnses, "");
Robert Greenwalt94daa182010-09-01 11:34:05 -07002336 }
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002337 }
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002338 } else {
Robert Greenwaltfce71862011-07-25 16:06:25 -07002339 try {
Robert Greenwalt49f762e2011-07-27 10:00:36 -07002340 mNetd.setDnsServersForInterface(p.getInterfaceName(),
Robert Greenwaltfce71862011-07-25 16:06:25 -07002341 NetworkUtils.makeStrings(dnses));
2342 } catch (Exception e) {
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08002343 if (DBG) loge("exception setting dns servers: " + e);
Robert Greenwaltfce71862011-07-25 16:06:25 -07002344 }
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002345 // set per-pid dns for attached secondary nets
2346 List pids = mNetRequestersPids[netType];
2347 for (int y=0; y< pids.size(); y++) {
2348 Integer pid = (Integer)pids.get(y);
Lorenzo Colittiaa035382011-09-28 22:31:45 -07002349 changed = writePidDns(dnses, pid.intValue());
The Android Open Source Project28527d22009-03-03 19:31:44 -08002350 }
2351 }
Robert Greenwalt8ca88762010-12-17 15:20:36 -08002352 if (changed) bumpDns();
The Android Open Source Project28527d22009-03-03 19:31:44 -08002353 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07002354 }
2355
Robert Greenwalt20f819c2011-05-03 19:02:44 -07002356 private int getRestoreDefaultNetworkDelay(int networkType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07002357 String restoreDefaultNetworkDelayStr = SystemProperties.get(
2358 NETWORK_RESTORE_DELAY_PROP_NAME);
2359 if(restoreDefaultNetworkDelayStr != null &&
2360 restoreDefaultNetworkDelayStr.length() != 0) {
2361 try {
2362 return Integer.valueOf(restoreDefaultNetworkDelayStr);
2363 } catch (NumberFormatException e) {
2364 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002365 }
Robert Greenwalt20f819c2011-05-03 19:02:44 -07002366 // if the system property isn't set, use the value for the apn type
2367 int ret = RESTORE_DEFAULT_NETWORK_DELAY;
2368
2369 if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
2370 (mNetConfigs[networkType] != null)) {
2371 ret = mNetConfigs[networkType].restoreTime;
2372 }
2373 return ret;
The Android Open Source Project28527d22009-03-03 19:31:44 -08002374 }
2375
2376 @Override
2377 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07002378 if (mContext.checkCallingOrSelfPermission(
2379 android.Manifest.permission.DUMP)
The Android Open Source Project28527d22009-03-03 19:31:44 -08002380 != PackageManager.PERMISSION_GRANTED) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07002381 pw.println("Permission Denial: can't dump ConnectivityService " +
2382 "from from pid=" + Binder.getCallingPid() + ", uid=" +
2383 Binder.getCallingUid());
The Android Open Source Project28527d22009-03-03 19:31:44 -08002384 return;
2385 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002386 pw.println();
2387 for (NetworkStateTracker nst : mNetTrackers) {
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002388 if (nst != null) {
2389 if (nst.getNetworkInfo().isConnected()) {
2390 pw.println("Active network: " + nst.getNetworkInfo().
2391 getTypeName());
2392 }
2393 pw.println(nst.getNetworkInfo());
2394 pw.println(nst);
2395 pw.println();
Robert Greenwalt2034b912009-08-12 16:08:25 -07002396 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002397 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002398
2399 pw.println("Network Requester Pids:");
2400 for (int net : mPriorityList) {
2401 String pidString = net + ": ";
2402 for (Object pid : mNetRequestersPids[net]) {
2403 pidString = pidString + pid.toString() + ", ";
2404 }
2405 pw.println(pidString);
2406 }
2407 pw.println();
2408
2409 pw.println("FeatureUsers:");
2410 for (Object requester : mFeatureUsers) {
2411 pw.println(requester.toString());
2412 }
2413 pw.println();
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002414
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002415 synchronized (this) {
2416 pw.println("NetworkTranstionWakeLock is currently " +
2417 (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held.");
2418 pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy);
2419 }
2420 pw.println();
2421
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002422 mTethering.dump(fd, pw, args);
Robert Greenwalt0e80be12010-09-20 14:35:25 -07002423
2424 if (mInetLog != null) {
2425 pw.println();
2426 pw.println("Inet condition reports:");
2427 for(int i = 0; i < mInetLog.size(); i++) {
2428 pw.println(mInetLog.get(i));
2429 }
2430 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002431 }
2432
Robert Greenwalt2034b912009-08-12 16:08:25 -07002433 // must be stateless - things change under us.
The Android Open Source Project28527d22009-03-03 19:31:44 -08002434 private class MyHandler extends Handler {
Wink Saville775aad62010-09-02 19:23:52 -07002435 public MyHandler(Looper looper) {
2436 super(looper);
2437 }
2438
The Android Open Source Project28527d22009-03-03 19:31:44 -08002439 @Override
2440 public void handleMessage(Message msg) {
2441 NetworkInfo info;
2442 switch (msg.what) {
2443 case NetworkStateTracker.EVENT_STATE_CHANGED:
2444 info = (NetworkInfo) msg.obj;
Robert Greenwalt12c44552009-12-07 11:33:18 -08002445 int type = info.getType();
2446 NetworkInfo.State state = info.getState();
Robert Greenwalt12c44552009-12-07 11:33:18 -08002447
Wink Savillea7d56572011-09-21 11:05:43 -07002448 if (VDBG || (state == NetworkInfo.State.CONNECTED) ||
2449 (state == NetworkInfo.State.DISCONNECTED)) {
2450 log("ConnectivityChange for " +
Robert Greenwalt0659da32009-07-16 17:21:39 -07002451 info.getTypeName() + ": " +
Robert Greenwalt12c44552009-12-07 11:33:18 -08002452 state + "/" + info.getDetailedState());
Wink Savillea7d56572011-09-21 11:05:43 -07002453 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002454
2455 // Connectivity state changed:
Robert Greenwalt310fa082012-04-25 13:45:02 -07002456 // [31-14] Reserved for future use
2457 // [13-10] Network subtype (for mobile network, as defined
Robert Greenwalt0659da32009-07-16 17:21:39 -07002458 // by TelephonyManager)
Robert Greenwalt310fa082012-04-25 13:45:02 -07002459 // [9-4] Detailed state ordinal (as defined by
Robert Greenwalt0659da32009-07-16 17:21:39 -07002460 // NetworkInfo.DetailedState)
Robert Greenwalt310fa082012-04-25 13:45:02 -07002461 // [3-0] Network type (as defined by ConnectivityManager)
2462 int eventLogParam = (info.getType() & 0xf) |
2463 ((info.getDetailedState().ordinal() & 0x3f) << 4) |
2464 (info.getSubtype() << 10);
Doug Zongker2fc96232009-12-04 10:31:43 -08002465 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
Robert Greenwalt0659da32009-07-16 17:21:39 -07002466 eventLogParam);
2467
2468 if (info.getDetailedState() ==
2469 NetworkInfo.DetailedState.FAILED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002470 handleConnectionFailure(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08002471 } else if (state == NetworkInfo.State.DISCONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002472 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08002473 } else if (state == NetworkInfo.State.SUSPENDED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002474 // TODO: need to think this over.
Robert Greenwalt0659da32009-07-16 17:21:39 -07002475 // the logic here is, handle SUSPENDED the same as
2476 // DISCONNECTED. The only difference being we are
2477 // broadcasting an intent with NetworkInfo that's
2478 // suspended. This allows the applications an
2479 // opportunity to handle DISCONNECTED and SUSPENDED
2480 // differently, or not.
The Android Open Source Project28527d22009-03-03 19:31:44 -08002481 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08002482 } else if (state == NetworkInfo.State.CONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002483 handleConnect(info);
2484 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002485 break;
The Android Open Source Project28527d22009-03-03 19:31:44 -08002486 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002487 info = (NetworkInfo) msg.obj;
Kazuhiro Ondo07680062011-06-22 21:10:34 -05002488 // TODO: Temporary allowing network configuration
2489 // change not resetting sockets.
2490 // @see bug/4455071
2491 handleConnectivityChange(info.getType(), false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08002492 break;
Robert Greenwaltccb36f92010-09-24 14:32:21 -07002493 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002494 String causedBy = null;
2495 synchronized (ConnectivityService.this) {
2496 if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
2497 mNetTransitionWakeLock.isHeld()) {
2498 mNetTransitionWakeLock.release();
2499 causedBy = mNetTransitionWakeLockCausedBy;
2500 }
2501 }
2502 if (causedBy != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002503 log("NetTransition Wakelock for " + causedBy + " released by timeout");
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002504 }
Robert Greenwaltcf1a56c2010-09-09 14:05:10 -07002505 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002506 case EVENT_RESTORE_DEFAULT_NETWORK:
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07002507 FeatureUser u = (FeatureUser)msg.obj;
2508 u.expire();
Robert Greenwalt986c7412010-09-08 15:24:47 -07002509 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002510 case EVENT_INET_CONDITION_CHANGE:
2511 {
2512 int netType = msg.arg1;
2513 int condition = msg.arg2;
2514 handleInetConditionChange(netType, condition);
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002515 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002516 }
2517 case EVENT_INET_CONDITION_HOLD_END:
2518 {
2519 int netType = msg.arg1;
2520 int sequence = msg.arg2;
2521 handleInetConditionHoldEnd(netType, sequence);
Robert Greenwalt986c7412010-09-08 15:24:47 -07002522 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002523 }
2524 case EVENT_SET_NETWORK_PREFERENCE:
2525 {
2526 int preference = msg.arg1;
2527 handleSetNetworkPreference(preference);
2528 break;
2529 }
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002530 case EVENT_SET_MOBILE_DATA:
2531 {
2532 boolean enabled = (msg.arg1 == ENABLED);
2533 handleSetMobileData(enabled);
2534 break;
2535 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002536 case EVENT_APPLY_GLOBAL_HTTP_PROXY:
2537 {
2538 handleDeprecatedGlobalHttpProxy();
Robert Greenwalt34848c02011-03-25 13:09:25 -07002539 break;
2540 }
2541 case EVENT_SET_DEPENDENCY_MET:
2542 {
2543 boolean met = (msg.arg1 == ENABLED);
2544 handleSetDependencyMet(msg.arg2, met);
2545 break;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002546 }
Chia-chi Yehcc844502011-07-14 18:01:57 -07002547 case EVENT_RESTORE_DNS:
2548 {
2549 if (mActiveDefaultNetwork != -1) {
2550 handleDnsConfigurationChange(mActiveDefaultNetwork);
2551 }
2552 break;
2553 }
Wink Saville4f0de1e2011-08-04 15:01:58 -07002554 case EVENT_SEND_STICKY_BROADCAST_INTENT:
2555 {
2556 Intent intent = (Intent)msg.obj;
Wink Saville4f0de1e2011-08-04 15:01:58 -07002557 sendStickyBroadcast(intent);
2558 break;
2559 }
Jeff Sharkey805662d2011-08-19 02:24:24 -07002560 case EVENT_SET_POLICY_DATA_ENABLE: {
2561 final int networkType = msg.arg1;
2562 final boolean enabled = msg.arg2 == ENABLED;
2563 handleSetPolicyDataEnable(networkType, enabled);
2564 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002565 }
2566 }
2567 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002568
2569 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002570 public int tether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002571 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002572
2573 if (isTetheringSupported()) {
2574 return mTethering.tether(iface);
2575 } else {
2576 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2577 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002578 }
2579
2580 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002581 public int untether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002582 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002583
2584 if (isTetheringSupported()) {
2585 return mTethering.untether(iface);
2586 } else {
2587 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2588 }
2589 }
2590
2591 // javadoc from interface
2592 public int getLastTetherError(String iface) {
2593 enforceTetherAccessPermission();
2594
2595 if (isTetheringSupported()) {
2596 return mTethering.getLastTetherError(iface);
2597 } else {
2598 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2599 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002600 }
2601
2602 // TODO - proper iface API for selection by property, inspection, etc
2603 public String[] getTetherableUsbRegexs() {
2604 enforceTetherAccessPermission();
2605 if (isTetheringSupported()) {
2606 return mTethering.getTetherableUsbRegexs();
2607 } else {
2608 return new String[0];
2609 }
2610 }
2611
2612 public String[] getTetherableWifiRegexs() {
2613 enforceTetherAccessPermission();
2614 if (isTetheringSupported()) {
2615 return mTethering.getTetherableWifiRegexs();
2616 } else {
2617 return new String[0];
2618 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002619 }
2620
Danica Chang96567052010-08-11 14:54:43 -07002621 public String[] getTetherableBluetoothRegexs() {
2622 enforceTetherAccessPermission();
2623 if (isTetheringSupported()) {
2624 return mTethering.getTetherableBluetoothRegexs();
2625 } else {
2626 return new String[0];
2627 }
2628 }
2629
Mike Lockwooded4a1742011-07-19 13:04:47 -07002630 public int setUsbTethering(boolean enable) {
2631 enforceTetherAccessPermission();
2632 if (isTetheringSupported()) {
2633 return mTethering.setUsbTethering(enable);
2634 } else {
2635 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2636 }
2637 }
2638
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002639 // TODO - move iface listing, queries, etc to new module
2640 // javadoc from interface
2641 public String[] getTetherableIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002642 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002643 return mTethering.getTetherableIfaces();
2644 }
2645
2646 public String[] getTetheredIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002647 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002648 return mTethering.getTetheredIfaces();
2649 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002650
Jeff Sharkey300f08f2011-09-16 01:52:49 -07002651 @Override
2652 public String[] getTetheredIfacePairs() {
2653 enforceTetherAccessPermission();
2654 return mTethering.getTetheredIfacePairs();
2655 }
2656
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002657 public String[] getTetheringErroredIfaces() {
2658 enforceTetherAccessPermission();
2659 return mTethering.getErroredIfaces();
2660 }
2661
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002662 // if ro.tether.denied = true we default to no tethering
2663 // gservices could set the secure setting to 1 though to enable it on a build where it
2664 // had previously been turned off.
2665 public boolean isTetheringSupported() {
2666 enforceTetherAccessPermission();
2667 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
Robert Greenwaltf1b66e12010-02-25 12:29:30 -08002668 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
2669 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
2670 return tetherEnabledInSettings && mTetheringConfigValid;
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002671 }
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002672
2673 // An API NetworkStateTrackers can call when they lose their network.
2674 // This will automatically be cleared after X seconds or a network becomes CONNECTED,
2675 // whichever happens first. The timer is started by the first caller and not
2676 // restarted by subsequent callers.
2677 public void requestNetworkTransitionWakelock(String forWhom) {
2678 enforceConnectivityInternalPermission();
2679 synchronized (this) {
2680 if (mNetTransitionWakeLock.isHeld()) return;
2681 mNetTransitionWakeLockSerialNumber++;
2682 mNetTransitionWakeLock.acquire();
2683 mNetTransitionWakeLockCausedBy = forWhom;
2684 }
2685 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltccb36f92010-09-24 14:32:21 -07002686 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002687 mNetTransitionWakeLockSerialNumber, 0),
2688 mNetTransitionWakeLockTimeout);
2689 return;
2690 }
Robert Greenwalt24118e82010-09-09 13:15:32 -07002691
Robert Greenwalt986c7412010-09-08 15:24:47 -07002692 // 100 percent is full good, 0 is full bad.
2693 public void reportInetCondition(int networkType, int percentage) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002694 if (VDBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")");
Robert Greenwalt986c7412010-09-08 15:24:47 -07002695 mContext.enforceCallingOrSelfPermission(
2696 android.Manifest.permission.STATUS_BAR,
2697 "ConnectivityService");
2698
Robert Greenwalt0e80be12010-09-20 14:35:25 -07002699 if (DBG) {
2700 int pid = getCallingPid();
2701 int uid = getCallingUid();
2702 String s = pid + "(" + uid + ") reports inet is " +
2703 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
2704 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
2705 mInetLog.add(s);
2706 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
2707 mInetLog.remove(0);
2708 }
2709 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07002710 mHandler.sendMessage(mHandler.obtainMessage(
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002711 EVENT_INET_CONDITION_CHANGE, networkType, percentage));
2712 }
2713
2714 private void handleInetConditionChange(int netType, int condition) {
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002715 if (mActiveDefaultNetwork == -1) {
Wink Savillea7d56572011-09-21 11:05:43 -07002716 if (DBG) log("handleInetConditionChange: no active default network - ignore");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002717 return;
2718 }
2719 if (mActiveDefaultNetwork != netType) {
Wink Savillea7d56572011-09-21 11:05:43 -07002720 if (DBG) log("handleInetConditionChange: net=" + netType +
2721 " != default=" + mActiveDefaultNetwork + " - ignore");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002722 return;
2723 }
Wink Savillea7d56572011-09-21 11:05:43 -07002724 if (VDBG) {
2725 log("handleInetConditionChange: net=" +
2726 netType + ", condition=" + condition +
2727 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
2728 }
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002729 mDefaultInetCondition = condition;
2730 int delay;
2731 if (mInetConditionChangeInFlight == false) {
Wink Savillea7d56572011-09-21 11:05:43 -07002732 if (VDBG) log("handleInetConditionChange: starting a change hold");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002733 // setup a new hold to debounce this
2734 if (mDefaultInetCondition > 50) {
2735 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2736 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
2737 } else {
2738 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2739 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
2740 }
2741 mInetConditionChangeInFlight = true;
2742 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
2743 mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
2744 } else {
Wink Savillea7d56572011-09-21 11:05:43 -07002745 // we've set the new condition, when this hold ends that will get picked up
2746 if (VDBG) log("handleInetConditionChange: currently in hold - not setting new end evt");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002747 }
2748 }
2749
2750 private void handleInetConditionHoldEnd(int netType, int sequence) {
Wink Savillea7d56572011-09-21 11:05:43 -07002751 if (DBG) {
2752 log("handleInetConditionHoldEnd: net=" + netType +
2753 ", condition=" + mDefaultInetCondition +
2754 ", published condition=" + mDefaultInetConditionPublished);
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002755 }
2756 mInetConditionChangeInFlight = false;
2757
2758 if (mActiveDefaultNetwork == -1) {
Wink Savillea7d56572011-09-21 11:05:43 -07002759 if (DBG) log("handleInetConditionHoldEnd: no active default network - ignoring");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002760 return;
2761 }
2762 if (mDefaultConnectionSequence != sequence) {
Wink Savillea7d56572011-09-21 11:05:43 -07002763 if (DBG) log("handleInetConditionHoldEnd: event hold for obsolete network - ignoring");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002764 return;
2765 }
Wink Saville4f0de1e2011-08-04 15:01:58 -07002766 // TODO: Figure out why this optimization sometimes causes a
2767 // change in mDefaultInetCondition to be missed and the
2768 // UI to not be updated.
2769 //if (mDefaultInetConditionPublished == mDefaultInetCondition) {
2770 // if (DBG) log("no change in condition - aborting");
2771 // return;
2772 //}
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002773 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
2774 if (networkInfo.isConnected() == false) {
Wink Savillea7d56572011-09-21 11:05:43 -07002775 if (DBG) log("handleInetConditionHoldEnd: default network not connected - ignoring");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002776 return;
2777 }
2778 mDefaultInetConditionPublished = mDefaultInetCondition;
2779 sendInetConditionBroadcast(networkInfo);
2780 return;
Robert Greenwalt986c7412010-09-08 15:24:47 -07002781 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002782
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07002783 public ProxyProperties getProxy() {
2784 synchronized (mDefaultProxyLock) {
2785 return mDefaultProxyDisabled ? null : mDefaultProxy;
2786 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002787 }
2788
2789 public void setGlobalProxy(ProxyProperties proxyProperties) {
2790 enforceChangePermission();
2791 synchronized (mGlobalProxyLock) {
2792 if (proxyProperties == mGlobalProxy) return;
2793 if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
2794 if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
2795
2796 String host = "";
2797 int port = 0;
2798 String exclList = "";
2799 if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) {
2800 mGlobalProxy = new ProxyProperties(proxyProperties);
2801 host = mGlobalProxy.getHost();
2802 port = mGlobalProxy.getPort();
2803 exclList = mGlobalProxy.getExclusionList();
2804 } else {
2805 mGlobalProxy = null;
2806 }
2807 ContentResolver res = mContext.getContentResolver();
2808 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host);
2809 Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port);
Robert Greenwalt6f7c6092010-12-02 11:31:00 -08002810 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002811 exclList);
2812 }
2813
2814 if (mGlobalProxy == null) {
2815 proxyProperties = mDefaultProxy;
2816 }
Chia-chi Yehae166612011-09-28 16:38:18 -07002817 //sendProxyBroadcast(proxyProperties);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002818 }
2819
Robert Greenwalt6f7c6092010-12-02 11:31:00 -08002820 private void loadGlobalProxy() {
2821 ContentResolver res = mContext.getContentResolver();
2822 String host = Settings.Secure.getString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST);
2823 int port = Settings.Secure.getInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, 0);
2824 String exclList = Settings.Secure.getString(res,
2825 Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
2826 if (!TextUtils.isEmpty(host)) {
2827 ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList);
2828 synchronized (mGlobalProxyLock) {
2829 mGlobalProxy = proxyProperties;
2830 }
2831 }
2832 }
2833
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002834 public ProxyProperties getGlobalProxy() {
2835 synchronized (mGlobalProxyLock) {
2836 return mGlobalProxy;
2837 }
2838 }
2839
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07002840 private void handleApplyDefaultProxy(ProxyProperties proxy) {
2841 if (proxy != null && TextUtils.isEmpty(proxy.getHost())) {
2842 proxy = null;
2843 }
2844 synchronized (mDefaultProxyLock) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002845 if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
2846 if (mDefaultProxy == proxy) return;
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07002847 mDefaultProxy = proxy;
2848
2849 if (!mDefaultProxyDisabled) {
2850 sendProxyBroadcast(proxy);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002851 }
2852 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002853 }
2854
2855 private void handleDeprecatedGlobalHttpProxy() {
2856 String proxy = Settings.Secure.getString(mContext.getContentResolver(),
2857 Settings.Secure.HTTP_PROXY);
2858 if (!TextUtils.isEmpty(proxy)) {
2859 String data[] = proxy.split(":");
2860 String proxyHost = data[0];
2861 int proxyPort = 8080;
2862 if (data.length > 1) {
2863 try {
2864 proxyPort = Integer.parseInt(data[1]);
2865 } catch (NumberFormatException e) {
2866 return;
2867 }
2868 }
2869 ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
2870 setGlobalProxy(p);
2871 }
2872 }
2873
2874 private void sendProxyBroadcast(ProxyProperties proxy) {
Robert Greenwalt611291c2010-12-23 15:51:10 -08002875 if (proxy == null) proxy = new ProxyProperties("", 0, "");
Robert Greenwalt78f28112011-08-02 17:18:41 -07002876 if (DBG) log("sending Proxy Broadcast for " + proxy);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002877 Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
Stan Chesnutt1f2a2ac2011-01-06 11:00:19 -08002878 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
2879 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002880 intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
Robert Greenwaltd93dc8f2010-12-06 11:29:17 -08002881 mContext.sendStickyBroadcast(intent);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002882 }
2883
2884 private static class SettingsObserver extends ContentObserver {
2885 private int mWhat;
2886 private Handler mHandler;
2887 SettingsObserver(Handler handler, int what) {
2888 super(handler);
2889 mHandler = handler;
2890 mWhat = what;
2891 }
2892
2893 void observe(Context context) {
2894 ContentResolver resolver = context.getContentResolver();
2895 resolver.registerContentObserver(Settings.Secure.getUriFor(
2896 Settings.Secure.HTTP_PROXY), false, this);
2897 }
2898
2899 @Override
2900 public void onChange(boolean selfChange) {
2901 mHandler.obtainMessage(mWhat).sendToTarget();
2902 }
2903 }
Wink Savillee70c6f52010-12-03 12:01:38 -08002904
2905 private void log(String s) {
2906 Slog.d(TAG, s);
2907 }
2908
2909 private void loge(String s) {
2910 Slog.e(TAG, s);
2911 }
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002912
repo syncf5de5572011-07-29 23:55:49 -07002913 int convertFeatureToNetworkType(int networkType, String feature) {
2914 int usedNetworkType = networkType;
2915
2916 if(networkType == ConnectivityManager.TYPE_MOBILE) {
2917 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
2918 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
2919 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
2920 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
2921 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
2922 TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
2923 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
2924 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
2925 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
2926 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
2927 usedNetworkType = ConnectivityManager.TYPE_MOBILE_FOTA;
2928 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
2929 usedNetworkType = ConnectivityManager.TYPE_MOBILE_IMS;
2930 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
2931 usedNetworkType = ConnectivityManager.TYPE_MOBILE_CBS;
2932 } else {
2933 Slog.e(TAG, "Can't match any mobile netTracker!");
2934 }
2935 } else if (networkType == ConnectivityManager.TYPE_WIFI) {
2936 if (TextUtils.equals(feature, "p2p")) {
2937 usedNetworkType = ConnectivityManager.TYPE_WIFI_P2P;
2938 } else {
2939 Slog.e(TAG, "Can't match any wifi netTracker!");
2940 }
2941 } else {
2942 Slog.e(TAG, "Unexpected network type");
Wink Savillef6b76692011-02-24 17:58:51 -08002943 }
repo syncf5de5572011-07-29 23:55:49 -07002944 return usedNetworkType;
Wink Savillef6b76692011-02-24 17:58:51 -08002945 }
Jeff Sharkey921ebf22011-05-19 17:12:49 -07002946
2947 private static <T> T checkNotNull(T value, String message) {
2948 if (value == null) {
2949 throw new NullPointerException(message);
2950 }
2951 return value;
2952 }
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002953
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002954 /**
2955 * Protect a socket from VPN routing rules. This method is used by
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07002956 * VpnBuilder and not available in ConnectivityManager. Permissions
2957 * are checked in Vpn class.
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002958 * @hide
2959 */
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002960 @Override
Chia-chi Yeh9e4ff6e2011-07-14 16:19:19 -07002961 public boolean protectVpn(ParcelFileDescriptor socket) {
2962 try {
2963 int type = mActiveDefaultNetwork;
2964 if (ConnectivityManager.isNetworkTypeValid(type)) {
2965 mVpn.protect(socket, mNetTrackers[type].getLinkProperties().getInterfaceName());
2966 return true;
2967 }
2968 } catch (Exception e) {
2969 // ignore
2970 } finally {
2971 try {
2972 socket.close();
2973 } catch (Exception e) {
2974 // ignore
2975 }
2976 }
2977 return false;
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002978 }
2979
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002980 /**
2981 * Prepare for a VPN application. This method is used by VpnDialogs
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07002982 * and not available in ConnectivityManager. Permissions are checked
2983 * in Vpn class.
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002984 * @hide
2985 */
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002986 @Override
Chia-chi Yeh3e2e1da2011-07-03 16:52:38 -07002987 public boolean prepareVpn(String oldPackage, String newPackage) {
2988 return mVpn.prepare(oldPackage, newPackage);
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002989 }
2990
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002991 /**
2992 * Configure a TUN interface and return its file descriptor. Parameters
2993 * are encoded and opaque to this class. This method is used by VpnBuilder
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07002994 * and not available in ConnectivityManager. Permissions are checked in
2995 * Vpn class.
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002996 * @hide
2997 */
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002998 @Override
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002999 public ParcelFileDescriptor establishVpn(VpnConfig config) {
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003000 return mVpn.establish(config);
3001 }
3002
Chia-chi Yeh7e026b32011-07-02 17:15:00 -07003003 /**
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07003004 * Start legacy VPN and return an intent to VpnDialogs. This method is
3005 * used by VpnSettings and not available in ConnectivityManager.
3006 * Permissions are checked in Vpn class.
Chia-chi Yeh7e026b32011-07-02 17:15:00 -07003007 * @hide
3008 */
3009 @Override
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07003010 public void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
3011 mVpn.startLegacyVpn(config, racoon, mtpd);
3012 }
3013
3014 /**
3015 * Return the information of the ongoing legacy VPN. This method is used
3016 * by VpnSettings and not available in ConnectivityManager. Permissions
3017 * are checked in Vpn class.
3018 * @hide
3019 */
3020 @Override
3021 public LegacyVpnInfo getLegacyVpnInfo() {
3022 return mVpn.getLegacyVpnInfo();
Chia-chi Yeh7e026b32011-07-02 17:15:00 -07003023 }
3024
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003025 /**
3026 * Callback for VPN subsystem. Currently VPN is not adapted to the service
3027 * through NetworkStateTracker since it works differently. For example, it
3028 * needs to override DNS servers but never takes the default routes. It
3029 * relies on another data network, and it could keep existing connections
3030 * alive after reconnecting, switching between networks, or even resuming
3031 * from deep sleep. Calls from applications should be done synchronously
3032 * to avoid race conditions. As these are all hidden APIs, refactoring can
3033 * be done whenever a better abstraction is developed.
3034 */
3035 public class VpnCallback {
3036
3037 private VpnCallback() {
3038 }
3039
Chia-chi Yehcc844502011-07-14 18:01:57 -07003040 public void override(List<String> dnsServers, List<String> searchDomains) {
3041 if (dnsServers == null) {
3042 restore();
3043 return;
3044 }
3045
3046 // Convert DNS servers into addresses.
3047 List<InetAddress> addresses = new ArrayList<InetAddress>();
3048 for (String address : dnsServers) {
3049 // Double check the addresses and remove invalid ones.
3050 try {
3051 addresses.add(InetAddress.parseNumericAddress(address));
3052 } catch (Exception e) {
3053 // ignore
3054 }
3055 }
3056 if (addresses.isEmpty()) {
3057 restore();
3058 return;
3059 }
3060
3061 // Concatenate search domains into a string.
3062 StringBuilder buffer = new StringBuilder();
3063 if (searchDomains != null) {
3064 for (String domain : searchDomains) {
3065 buffer.append(domain).append(' ');
3066 }
3067 }
3068 String domains = buffer.toString().trim();
3069
3070 // Apply DNS changes.
3071 boolean changed = false;
3072 synchronized (mDnsLock) {
Lorenzo Colittiaa035382011-09-28 22:31:45 -07003073 changed = updateDns("VPN", "VPN", addresses, domains);
Chia-chi Yehcc844502011-07-14 18:01:57 -07003074 mDnsOverridden = true;
3075 }
3076 if (changed) {
3077 bumpDns();
3078 }
3079
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003080 // Temporarily disable the default proxy.
3081 synchronized (mDefaultProxyLock) {
3082 mDefaultProxyDisabled = true;
3083 if (mDefaultProxy != null) {
3084 sendProxyBroadcast(null);
3085 }
3086 }
3087
3088 // TODO: support proxy per network.
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003089 }
3090
Chia-chi Yehcc844502011-07-14 18:01:57 -07003091 public void restore() {
3092 synchronized (mDnsLock) {
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003093 if (mDnsOverridden) {
3094 mDnsOverridden = false;
3095 mHandler.sendEmptyMessage(EVENT_RESTORE_DNS);
Chia-chi Yehcc844502011-07-14 18:01:57 -07003096 }
Chia-chi Yehcc844502011-07-14 18:01:57 -07003097 }
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003098 synchronized (mDefaultProxyLock) {
3099 mDefaultProxyDisabled = false;
3100 if (mDefaultProxy != null) {
3101 sendProxyBroadcast(mDefaultProxy);
3102 }
3103 }
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003104 }
3105 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08003106}