blob: 1341dd4dd560d33696d365b5e8aa52e660be36d7 [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 Sharkey921ebf22011-05-19 17:12:49 -070020import static android.net.ConnectivityManager.isNetworkTypeValid;
21import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -070022import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070023
Jaikumar Ganesh0db51a02010-12-21 22:31:44 -080024import android.bluetooth.BluetoothTetheringDataTracker;
The Android Open Source Project28527d22009-03-03 19:31:44 -080025import android.content.ContentResolver;
26import android.content.Context;
27import android.content.Intent;
28import android.content.pm.PackageManager;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -070029import android.database.ContentObserver;
The Android Open Source Project28527d22009-03-03 19:31:44 -080030import android.net.ConnectivityManager;
Robert Greenwalteb123ac2010-12-06 13:56:24 -080031import android.net.DummyDataStateTracker;
Benoit Goby211b5692010-12-22 14:29:40 -080032import android.net.EthernetDataTracker;
The Android Open Source Project28527d22009-03-03 19:31:44 -080033import android.net.IConnectivityManager;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070034import android.net.INetworkPolicyListener;
35import android.net.INetworkPolicyManager;
Wink Savilledc5d1ba2011-07-14 12:23:28 -070036import android.net.LinkAddress;
Jaikumar Ganesh0db51a02010-12-21 22:31:44 -080037import android.net.LinkProperties;
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -070038import android.net.LinkProperties.CompareResult;
The Android Open Source Project28527d22009-03-03 19:31:44 -080039import android.net.MobileDataStateTracker;
Robert Greenwalt34848c02011-03-25 13:09:25 -070040import android.net.NetworkConfig;
The Android Open Source Project28527d22009-03-03 19:31:44 -080041import android.net.NetworkInfo;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070042import android.net.NetworkInfo.DetailedState;
Jeff Sharkey66fa9682011-08-02 17:22:34 -070043import android.net.NetworkQuotaInfo;
Jeff Sharkey21062e72011-05-28 20:56:34 -070044import android.net.NetworkState;
The Android Open Source Project28527d22009-03-03 19:31:44 -080045import android.net.NetworkStateTracker;
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -070046import android.net.NetworkUtils;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -070047import android.net.Proxy;
48import android.net.ProxyProperties;
Robert Greenwalt5a901292011-04-28 14:28:50 -070049import android.net.RouteInfo;
The Android Open Source Project28527d22009-03-03 19:31:44 -080050import android.net.wifi.WifiStateTracker;
51import android.os.Binder;
Mike Lockwood0d5916c2011-05-28 13:24:04 -040052import android.os.FileUtils;
The Android Open Source Project28527d22009-03-03 19:31:44 -080053import android.os.Handler;
Wink Saville775aad62010-09-02 19:23:52 -070054import android.os.HandlerThread;
Robert Greenwalt2034b912009-08-12 16:08:25 -070055import android.os.IBinder;
Chia-chi Yeh4df51322011-05-11 16:35:13 -070056import android.os.INetworkManagementService;
The Android Open Source Project28527d22009-03-03 19:31:44 -080057import android.os.Looper;
58import android.os.Message;
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -070059import android.os.ParcelFileDescriptor;
Robert Greenwalt93dc1042010-06-15 12:19:37 -070060import android.os.PowerManager;
Robert Greenwalt2034b912009-08-12 16:08:25 -070061import android.os.RemoteException;
The Android Open Source Project28527d22009-03-03 19:31:44 -080062import android.os.ServiceManager;
63import android.os.SystemProperties;
64import android.provider.Settings;
Robert Greenwalt2034b912009-08-12 16:08:25 -070065import android.text.TextUtils;
The Android Open Source Project28527d22009-03-03 19:31:44 -080066import android.util.EventLog;
Joe Onoratoc2386bb2010-02-26 18:56:32 -080067import android.util.Slog;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070068import android.util.SparseIntArray;
The Android Open Source Project28527d22009-03-03 19:31:44 -080069
Chia-chi Yehbded3eb2011-07-04 03:23:12 -070070import com.android.internal.net.LegacyVpnInfo;
Chia-chi Yeh75cacd52011-06-15 17:07:27 -070071import com.android.internal.net.VpnConfig;
Robert Greenwalt2034b912009-08-12 16:08:25 -070072import com.android.internal.telephony.Phone;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080073import com.android.server.connectivity.Tethering;
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -070074import com.android.server.connectivity.Vpn;
75
Jeff Sharkey21062e72011-05-28 20:56:34 -070076import com.google.android.collect.Lists;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -070077import com.google.android.collect.Sets;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -080078
The Android Open Source Project28527d22009-03-03 19:31:44 -080079import java.io.FileDescriptor;
Irfan Sheriff7f132d92010-06-09 15:39:36 -070080import java.io.IOException;
The Android Open Source Project28527d22009-03-03 19:31:44 -080081import java.io.PrintWriter;
Wink Savilledc5d1ba2011-07-14 12:23:28 -070082import java.net.Inet4Address;
Wink Saville051a6642011-07-13 13:44:13 -070083import java.net.Inet6Address;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070084import java.net.InetAddress;
85import java.net.UnknownHostException;
Robert Greenwalt2034b912009-08-12 16:08:25 -070086import java.util.ArrayList;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -070087import java.util.Arrays;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070088import java.util.Collection;
Robert Greenwalt0e80be12010-09-20 14:35:25 -070089import java.util.GregorianCalendar;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -070090import java.util.HashSet;
Robert Greenwalt2034b912009-08-12 16:08:25 -070091import java.util.List;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070092import java.util.concurrent.atomic.AtomicBoolean;
The Android Open Source Project28527d22009-03-03 19:31:44 -080093
94/**
95 * @hide
96 */
97public class ConnectivityService extends IConnectivityManager.Stub {
98
Robert Greenwalt063dc7d2010-10-05 19:12:26 -070099 private static final boolean DBG = true;
Wink Saville051a6642011-07-13 13:44:13 -0700100 private static final boolean VDBG = true;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800101 private static final String TAG = "ConnectivityService";
102
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700103 private static final boolean LOGD_RULES = false;
104
Robert Greenwalt2034b912009-08-12 16:08:25 -0700105 // how long to wait before switching back to a radio's default network
106 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
107 // system property that can override the above value
108 private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
109 "android.telephony.apn-restore";
110
Robert Greenwaltbd492212011-05-06 17:10:53 -0700111 // used in recursive route setting to add gateways for the host for which
112 // a host route was requested.
113 private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10;
114
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800115 private Tethering mTethering;
Robert Greenwaltf1b66e12010-02-25 12:29:30 -0800116 private boolean mTetheringConfigValid = false;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800117
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -0700118 private Vpn mVpn;
119
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700120 /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
121 private Object mRulesLock = new Object();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700122 /** Currently active network rules by UID. */
123 private SparseIntArray mUidRules = new SparseIntArray();
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700124 /** Set of ifaces that are costly. */
125 private HashSet<String> mMeteredIfaces = Sets.newHashSet();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700126
The Android Open Source Project28527d22009-03-03 19:31:44 -0800127 /**
128 * Sometimes we want to refer to the individual network state
129 * trackers separately, and sometimes we just want to treat them
130 * abstractly.
131 */
132 private NetworkStateTracker mNetTrackers[];
Robert Greenwalt2034b912009-08-12 16:08:25 -0700133
134 /**
Wink Saville051a6642011-07-13 13:44:13 -0700135 * The link properties that define the current links
136 */
137 private LinkProperties mCurrentLinkProperties[];
138
139 /**
Robert Greenwalt2034b912009-08-12 16:08:25 -0700140 * A per Net list of the PID's that requested access to the net
141 * used both as a refcount and for per-PID DNS selection
142 */
143 private List mNetRequestersPids[];
144
Robert Greenwalt2034b912009-08-12 16:08:25 -0700145 // priority order of the nettrackers
146 // (excluding dynamically set mNetworkPreference)
147 // TODO - move mNetworkTypePreference into this
148 private int[] mPriorityList;
149
The Android Open Source Project28527d22009-03-03 19:31:44 -0800150 private Context mContext;
151 private int mNetworkPreference;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700152 private int mActiveDefaultNetwork = -1;
Robert Greenwalt986c7412010-09-08 15:24:47 -0700153 // 0 is full bad, 100 is full good
154 private int mDefaultInetCondition = 0;
155 private int mDefaultInetConditionPublished = 0;
156 private boolean mInetConditionChangeInFlight = false;
157 private int mDefaultConnectionSequence = 0;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800158
Chia-chi Yehcc844502011-07-14 18:01:57 -0700159 private Object mDnsLock = new Object();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800160 private int mNumDnsEntries;
Chia-chi Yehcc844502011-07-14 18:01:57 -0700161 private boolean mDnsOverridden = false;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800162
163 private boolean mTestMode;
Joe Onorato56023ad2010-09-01 21:18:22 -0700164 private static ConnectivityService sServiceInstance;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800165
Robert Greenwalt355205c2011-05-10 15:05:02 -0700166 private INetworkManagementService mNetd;
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700167 private INetworkPolicyManager mPolicyManager;
Robert Greenwalt355205c2011-05-10 15:05:02 -0700168
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700169 private static final int ENABLED = 1;
170 private static final int DISABLED = 0;
171
172 // Share the event space with NetworkStateTracker (which can't see this
173 // internal class but sends us events). If you change these, change
174 // NetworkStateTracker.java too.
175 private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1;
176 private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100;
177
178 /**
179 * used internally as a delayed event to make us switch back to the
180 * default network
181 */
182 private static final int EVENT_RESTORE_DEFAULT_NETWORK =
183 MAX_NETWORK_STATE_TRACKER_EVENT + 1;
184
185 /**
186 * used internally to change our mobile data enabled flag
187 */
188 private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED =
189 MAX_NETWORK_STATE_TRACKER_EVENT + 2;
190
191 /**
192 * used internally to change our network preference setting
193 * arg1 = networkType to prefer
194 */
195 private static final int EVENT_SET_NETWORK_PREFERENCE =
196 MAX_NETWORK_STATE_TRACKER_EVENT + 3;
197
198 /**
199 * used internally to synchronize inet condition reports
200 * arg1 = networkType
201 * arg2 = condition (0 bad, 100 good)
202 */
203 private static final int EVENT_INET_CONDITION_CHANGE =
204 MAX_NETWORK_STATE_TRACKER_EVENT + 4;
205
206 /**
207 * used internally to mark the end of inet condition hold periods
208 * arg1 = networkType
209 */
210 private static final int EVENT_INET_CONDITION_HOLD_END =
211 MAX_NETWORK_STATE_TRACKER_EVENT + 5;
212
213 /**
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700214 * used internally to set enable/disable cellular data
215 * arg1 = ENBALED or DISABLED
216 */
217 private static final int EVENT_SET_MOBILE_DATA =
218 MAX_NETWORK_STATE_TRACKER_EVENT + 7;
219
Robert Greenwaltccb36f92010-09-24 14:32:21 -0700220 /**
221 * used internally to clear a wakelock when transitioning
222 * from one net to another
223 */
224 private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK =
225 MAX_NETWORK_STATE_TRACKER_EVENT + 8;
226
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700227 /**
228 * used internally to reload global proxy settings
229 */
230 private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY =
231 MAX_NETWORK_STATE_TRACKER_EVENT + 9;
232
Robert Greenwalt34848c02011-03-25 13:09:25 -0700233 /**
234 * used internally to set external dependency met/unmet
235 * arg1 = ENABLED (met) or DISABLED (unmet)
236 * arg2 = NetworkType
237 */
238 private static final int EVENT_SET_DEPENDENCY_MET =
239 MAX_NETWORK_STATE_TRACKER_EVENT + 10;
240
Chia-chi Yehcc844502011-07-14 18:01:57 -0700241 /**
242 * used internally to restore DNS properties back to the
243 * default network
244 */
245 private static final int EVENT_RESTORE_DNS =
246 MAX_NETWORK_STATE_TRACKER_EVENT + 11;
247
Wink Saville7e4333c2011-08-05 11:40:22 -0700248 /**
Wink Saville4f0de1e2011-08-04 15:01:58 -0700249 * used internally to send a sticky broadcast delayed.
250 */
251 private static final int EVENT_SEND_STICKY_BROADCAST_INTENT =
Wink Saville7e4333c2011-08-05 11:40:22 -0700252 MAX_NETWORK_STATE_TRACKER_EVENT + 12;
Wink Saville4f0de1e2011-08-04 15:01:58 -0700253
Robert Greenwalt2034b912009-08-12 16:08:25 -0700254 private Handler mHandler;
255
256 // list of DeathRecipients used to make sure features are turned off when
257 // a process dies
Kazuhiro Ondocae18f12011-07-19 11:23:37 -0500258 private List<FeatureUser> mFeatureUsers;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700259
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400260 private boolean mSystemReady;
Dianne Hackborna417ff82009-12-08 19:45:14 -0800261 private Intent mInitialBroadcast;
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400262
Robert Greenwalt93dc1042010-06-15 12:19:37 -0700263 private PowerManager.WakeLock mNetTransitionWakeLock;
264 private String mNetTransitionWakeLockCausedBy = "";
265 private int mNetTransitionWakeLockSerialNumber;
266 private int mNetTransitionWakeLockTimeout;
267
Robert Greenwalt94daa182010-09-01 11:34:05 -0700268 private InetAddress mDefaultDns;
269
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700270 // this collection is used to refcount the added routes - if there are none left
271 // it's time to remove the route from the route table
272 private Collection<RouteInfo> mAddedRoutes = new ArrayList<RouteInfo>();
273
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700274 // used in DBG mode to track inet condition reports
275 private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
276 private ArrayList mInetLog;
277
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700278 // track the current default http proxy - tell the world if we get a new one (real change)
279 private ProxyProperties mDefaultProxy = null;
280 // track the global proxy.
281 private ProxyProperties mGlobalProxy = null;
282 private final Object mGlobalProxyLock = new Object();
283
284 private SettingsObserver mSettingsObserver;
285
Robert Greenwalt34848c02011-03-25 13:09:25 -0700286 NetworkConfig[] mNetConfigs;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700287 int mNetworksDefined;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700288
Robert Greenwalt12c44552009-12-07 11:33:18 -0800289 private static class RadioAttributes {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700290 public int mSimultaneity;
291 public int mType;
292 public RadioAttributes(String init) {
293 String fragments[] = init.split(",");
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700294 mType = Integer.parseInt(fragments[0]);
295 mSimultaneity = Integer.parseInt(fragments[1]);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700296 }
297 }
298 RadioAttributes[] mRadioAttributes;
299
Robert Greenwalt6cac0742011-06-21 17:26:14 -0700300 // the set of network types that can only be enabled by system/sig apps
301 List mProtectedNetworks;
302
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700303 public ConnectivityService(
304 Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800305 if (DBG) log("ConnectivityService starting up");
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800306
Wink Saville775aad62010-09-02 19:23:52 -0700307 HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
308 handlerThread.start();
309 mHandler = new MyHandler(handlerThread.getLooper());
310
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800311 // setup our unique device name
Robert Greenwalt82cde132010-12-06 09:30:17 -0800312 if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
313 String id = Settings.Secure.getString(context.getContentResolver(),
314 Settings.Secure.ANDROID_ID);
315 if (id != null && id.length() > 0) {
316 String name = new String("android_").concat(id);
317 SystemProperties.set("net.hostname", name);
318 }
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800319 }
320
Robert Greenwalt94daa182010-09-01 11:34:05 -0700321 // read our default dns server ip
322 String dns = Settings.Secure.getString(context.getContentResolver(),
323 Settings.Secure.DEFAULT_DNS_SERVER);
324 if (dns == null || dns.length() == 0) {
325 dns = context.getResources().getString(
326 com.android.internal.R.string.config_default_dns_server);
327 }
328 try {
Robert Greenwalt35e34d12011-02-22 16:00:42 -0800329 mDefaultDns = NetworkUtils.numericToInetAddress(dns);
330 } catch (IllegalArgumentException e) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800331 loge("Error setting defaultDns using " + dns);
Robert Greenwalt94daa182010-09-01 11:34:05 -0700332 }
333
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700334 mContext = checkNotNull(context, "missing Context");
335 mNetd = checkNotNull(netd, "missing INetworkManagementService");
336 mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
Robert Greenwalt93dc1042010-06-15 12:19:37 -0700337
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700338 try {
339 mPolicyManager.registerListener(mPolicyListener);
340 } catch (RemoteException e) {
341 // ouch, no rules updates means some processes may never get network
Robert Greenwalt78f28112011-08-02 17:18:41 -0700342 loge("unable to register INetworkPolicyListener" + e.toString());
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700343 }
344
345 final PowerManager powerManager = (PowerManager) context.getSystemService(
346 Context.POWER_SERVICE);
Robert Greenwalt93dc1042010-06-15 12:19:37 -0700347 mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
348 mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
349 com.android.internal.R.integer.config_networkTransitionTimeout);
350
Robert Greenwalt2034b912009-08-12 16:08:25 -0700351 mNetTrackers = new NetworkStateTracker[
352 ConnectivityManager.MAX_NETWORK_TYPE+1];
Wink Saville051a6642011-07-13 13:44:13 -0700353 mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwalt0659da32009-07-16 17:21:39 -0700354
The Android Open Source Project28527d22009-03-03 19:31:44 -0800355 mNetworkPreference = getPersistedNetworkPreference();
Robert Greenwalt0659da32009-07-16 17:21:39 -0700356
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700357 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
Robert Greenwalt34848c02011-03-25 13:09:25 -0700358 mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700359
Robert Greenwalt2034b912009-08-12 16:08:25 -0700360 // Load device network attributes from resources
Robert Greenwalt2034b912009-08-12 16:08:25 -0700361 String[] raStrings = context.getResources().getStringArray(
362 com.android.internal.R.array.radioAttributes);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700363 for (String raString : raStrings) {
364 RadioAttributes r = new RadioAttributes(raString);
365 if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800366 loge("Error in radioAttributes - ignoring attempt to define type " + r.mType);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700367 continue;
368 }
369 if (mRadioAttributes[r.mType] != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800370 loge("Error in radioAttributes - ignoring attempt to redefine type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700371 r.mType);
372 continue;
373 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700374 mRadioAttributes[r.mType] = r;
375 }
376
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700377 String[] naStrings = context.getResources().getStringArray(
378 com.android.internal.R.array.networkAttributes);
379 for (String naString : naStrings) {
380 try {
Robert Greenwalt34848c02011-03-25 13:09:25 -0700381 NetworkConfig n = new NetworkConfig(naString);
Wink Savillef2a62832011-04-07 14:23:45 -0700382 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800383 loge("Error in networkAttributes - ignoring attempt to define type " +
Wink Savillef2a62832011-04-07 14:23:45 -0700384 n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700385 continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700386 }
Wink Savillef2a62832011-04-07 14:23:45 -0700387 if (mNetConfigs[n.type] != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800388 loge("Error in networkAttributes - ignoring attempt to redefine type " +
Wink Savillef2a62832011-04-07 14:23:45 -0700389 n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700390 continue;
391 }
Wink Savillef2a62832011-04-07 14:23:45 -0700392 if (mRadioAttributes[n.radio] == null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800393 loge("Error in networkAttributes - ignoring attempt to use undefined " +
Wink Savillef2a62832011-04-07 14:23:45 -0700394 "radio " + n.radio + " in network type " + n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700395 continue;
396 }
Wink Savillef2a62832011-04-07 14:23:45 -0700397 mNetConfigs[n.type] = n;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700398 mNetworksDefined++;
399 } catch(Exception e) {
400 // ignore it - leave the entry null
Robert Greenwalt2034b912009-08-12 16:08:25 -0700401 }
402 }
403
Robert Greenwalt6cac0742011-06-21 17:26:14 -0700404 mProtectedNetworks = new ArrayList<Integer>();
405 int[] protectedNetworks = context.getResources().getIntArray(
406 com.android.internal.R.array.config_protectedNetworks);
407 for (int p : protectedNetworks) {
408 if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
409 mProtectedNetworks.add(p);
410 } else {
411 if (DBG) loge("Ignoring protectedNetwork " + p);
412 }
413 }
414
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700415 // high priority first
416 mPriorityList = new int[mNetworksDefined];
417 {
418 int insertionPoint = mNetworksDefined-1;
419 int currentLowest = 0;
420 int nextLowest = 0;
421 while (insertionPoint > -1) {
Robert Greenwalt34848c02011-03-25 13:09:25 -0700422 for (NetworkConfig na : mNetConfigs) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700423 if (na == null) continue;
Wink Savillef2a62832011-04-07 14:23:45 -0700424 if (na.priority < currentLowest) continue;
425 if (na.priority > currentLowest) {
426 if (na.priority < nextLowest || nextLowest == 0) {
427 nextLowest = na.priority;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700428 }
429 continue;
430 }
Wink Savillef2a62832011-04-07 14:23:45 -0700431 mPriorityList[insertionPoint--] = na.type;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700432 }
433 currentLowest = nextLowest;
434 nextLowest = 0;
435 }
436 }
437
438 mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
439 for (int i : mPriorityList) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700440 mNetRequestersPids[i] = new ArrayList();
441 }
442
Kazuhiro Ondocae18f12011-07-19 11:23:37 -0500443 mFeatureUsers = new ArrayList<FeatureUser>();
Robert Greenwalt2034b912009-08-12 16:08:25 -0700444
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700445 mNumDnsEntries = 0;
446
447 mTestMode = SystemProperties.get("cm.test.mode").equals("true")
448 && SystemProperties.get("ro.build.type").equals("eng");
The Android Open Source Project28527d22009-03-03 19:31:44 -0800449 /*
450 * Create the network state trackers for Wi-Fi and mobile
451 * data. Maybe this could be done with a factory class,
452 * but it's not clear that it's worth it, given that
453 * the number of different network types is not going
454 * to change very often.
455 */
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700456 for (int netType : mPriorityList) {
Wink Savillef2a62832011-04-07 14:23:45 -0700457 switch (mNetConfigs[netType].radio) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700458 case ConnectivityManager.TYPE_WIFI:
repo syncf5de5572011-07-29 23:55:49 -0700459 mNetTrackers[netType] = new WifiStateTracker(netType,
460 mNetConfigs[netType].name);
461 mNetTrackers[netType].startMonitoring(context, mHandler);
462 break;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700463 case ConnectivityManager.TYPE_MOBILE:
Wink Saville7fabfa22010-08-13 16:11:42 -0700464 mNetTrackers[netType] = new MobileDataStateTracker(netType,
Wink Savillef2a62832011-04-07 14:23:45 -0700465 mNetConfigs[netType].name);
Wink Saville7fabfa22010-08-13 16:11:42 -0700466 mNetTrackers[netType].startMonitoring(context, mHandler);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700467 break;
Robert Greenwalteb123ac2010-12-06 13:56:24 -0800468 case ConnectivityManager.TYPE_DUMMY:
469 mNetTrackers[netType] = new DummyDataStateTracker(netType,
Wink Savillef2a62832011-04-07 14:23:45 -0700470 mNetConfigs[netType].name);
Robert Greenwalteb123ac2010-12-06 13:56:24 -0800471 mNetTrackers[netType].startMonitoring(context, mHandler);
472 break;
Jaikumar Ganesh0db51a02010-12-21 22:31:44 -0800473 case ConnectivityManager.TYPE_BLUETOOTH:
474 mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
475 mNetTrackers[netType].startMonitoring(context, mHandler);
476 break;
Benoit Goby211b5692010-12-22 14:29:40 -0800477 case ConnectivityManager.TYPE_ETHERNET:
478 mNetTrackers[netType] = EthernetDataTracker.getInstance();
479 mNetTrackers[netType].startMonitoring(context, mHandler);
480 break;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700481 default:
Wink Savillee70c6f52010-12-03 12:01:38 -0800482 loge("Trying to create a DataStateTracker for an unknown radio type " +
Wink Savillef2a62832011-04-07 14:23:45 -0700483 mNetConfigs[netType].radio);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700484 continue;
485 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700486 mCurrentLinkProperties[netType] = null;
Robert Greenwalt497ff5e72011-07-15 11:16:45 -0700487 if (mNetConfigs[netType].isDefault()) mNetTrackers[netType].reconnect();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700488 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800489
Chia-chi Yeh4df51322011-05-11 16:35:13 -0700490 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
491 INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
492
493 mTethering = new Tethering(mContext, nmService, mHandler.getLooper());
Robert Greenwalt33cdcdf2011-06-02 17:30:47 -0700494 mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
Danica Chang96567052010-08-11 14:54:43 -0700495 mTethering.getTetherableWifiRegexs().length != 0 ||
496 mTethering.getTetherableBluetoothRegexs().length != 0) &&
Robert Greenwalt33cdcdf2011-06-02 17:30:47 -0700497 mTethering.getUpstreamIfaceTypes().length != 0);
Robert Greenwaltf1b66e12010-02-25 12:29:30 -0800498
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -0700499 mVpn = new Vpn(mContext, new VpnCallback());
500
Chia-chi Yehf3204aa2011-05-23 15:08:29 -0700501 try {
502 nmService.registerObserver(mTethering);
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -0700503 nmService.registerObserver(mVpn);
Chia-chi Yehf3204aa2011-05-23 15:08:29 -0700504 } catch (RemoteException e) {
505 loge("Error registering observer :" + e);
506 }
507
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700508 if (DBG) {
509 mInetLog = new ArrayList();
510 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700511
512 mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
513 mSettingsObserver.observe(mContext);
Robert Greenwalt6f7c6092010-12-02 11:31:00 -0800514
515 loadGlobalProxy();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800516 }
517
518 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700519 * Sets the preferred network.
The Android Open Source Project28527d22009-03-03 19:31:44 -0800520 * @param preference the new preference
521 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700522 public void setNetworkPreference(int preference) {
The Android Open Source Project28527d22009-03-03 19:31:44 -0800523 enforceChangePermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700524
525 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
The Android Open Source Project28527d22009-03-03 19:31:44 -0800526 }
527
528 public int getNetworkPreference() {
529 enforceAccessPermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700530 int preference;
531 synchronized(this) {
532 preference = mNetworkPreference;
533 }
534 return preference;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800535 }
536
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700537 private void handleSetNetworkPreference(int preference) {
538 if (ConnectivityManager.isNetworkTypeValid(preference) &&
Robert Greenwalt34848c02011-03-25 13:09:25 -0700539 mNetConfigs[preference] != null &&
540 mNetConfigs[preference].isDefault()) {
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700541 if (mNetworkPreference != preference) {
542 final ContentResolver cr = mContext.getContentResolver();
543 Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference);
544 synchronized(this) {
545 mNetworkPreference = preference;
546 }
547 enforcePreference();
548 }
549 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800550 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700551
Wink Saville4f0de1e2011-08-04 15:01:58 -0700552 private int getConnectivityChangeDelay() {
553 final ContentResolver cr = mContext.getContentResolver();
554
555 /** Check system properties for the default value then use secure settings value, if any. */
556 int defaultDelay = SystemProperties.getInt(
557 "conn." + Settings.Secure.CONNECTIVITY_CHANGE_DELAY,
558 Settings.Secure.CONNECTIVITY_CHANGE_DELAY_DEFAULT);
559 return Settings.Secure.getInt(cr, Settings.Secure.CONNECTIVITY_CHANGE_DELAY,
560 defaultDelay);
561 }
562
The Android Open Source Project28527d22009-03-03 19:31:44 -0800563 private int getPersistedNetworkPreference() {
564 final ContentResolver cr = mContext.getContentResolver();
565
566 final int networkPrefSetting = Settings.Secure
567 .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1);
568 if (networkPrefSetting != -1) {
569 return networkPrefSetting;
570 }
571
572 return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
573 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700574
The Android Open Source Project28527d22009-03-03 19:31:44 -0800575 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700576 * Make the state of network connectivity conform to the preference settings
The Android Open Source Project28527d22009-03-03 19:31:44 -0800577 * In this method, we only tear down a non-preferred network. Establishing
578 * a connection to the preferred network is taken care of when we handle
579 * the disconnect event from the non-preferred network
580 * (see {@link #handleDisconnect(NetworkInfo)}).
581 */
582 private void enforcePreference() {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700583 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
The Android Open Source Project28527d22009-03-03 19:31:44 -0800584 return;
585
Robert Greenwalt2034b912009-08-12 16:08:25 -0700586 if (!mNetTrackers[mNetworkPreference].isAvailable())
587 return;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800588
Robert Greenwalt2034b912009-08-12 16:08:25 -0700589 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700590 if (t != mNetworkPreference && mNetTrackers[t] != null &&
Robert Greenwalt2034b912009-08-12 16:08:25 -0700591 mNetTrackers[t].getNetworkInfo().isConnected()) {
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700592 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800593 log("tearing down " + mNetTrackers[t].getNetworkInfo() +
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700594 " in enforcePreference");
595 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700596 teardown(mNetTrackers[t]);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800597 }
598 }
599 }
600
601 private boolean teardown(NetworkStateTracker netTracker) {
602 if (netTracker.teardown()) {
603 netTracker.setTeardownRequested(true);
604 return true;
605 } else {
606 return false;
607 }
608 }
609
610 /**
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700611 * Check if UID should be blocked from using the network represented by the
612 * given {@link NetworkStateTracker}.
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700613 */
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700614 private boolean isNetworkBlocked(NetworkStateTracker tracker, int uid) {
615 final String iface = tracker.getLinkProperties().getInterfaceName();
Jeff Sharkey21062e72011-05-28 20:56:34 -0700616
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700617 final boolean networkCostly;
618 final int uidRules;
619 synchronized (mRulesLock) {
620 networkCostly = mMeteredIfaces.contains(iface);
621 uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700622 }
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700623
624 if (networkCostly && (uidRules & RULE_REJECT_METERED) != 0) {
625 return true;
626 }
627
628 // no restrictive rules; network is visible
629 return false;
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700630 }
631
632 /**
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700633 * Return a filtered {@link NetworkInfo}, potentially marked
634 * {@link DetailedState#BLOCKED} based on
635 * {@link #isNetworkBlocked(NetworkStateTracker, int)}.
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700636 */
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700637 private NetworkInfo getFilteredNetworkInfo(NetworkStateTracker tracker, int uid) {
638 NetworkInfo info = tracker.getNetworkInfo();
639 if (isNetworkBlocked(tracker, uid)) {
Jeff Sharkey21062e72011-05-28 20:56:34 -0700640 // network is blocked; clone and override state
641 info = new NetworkInfo(info);
642 info.setDetailedState(DetailedState.BLOCKED, null, null);
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700643 }
Jeff Sharkey21062e72011-05-28 20:56:34 -0700644 return info;
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700645 }
646
647 /**
The Android Open Source Project28527d22009-03-03 19:31:44 -0800648 * Return NetworkInfo for the active (i.e., connected) network interface.
649 * It is assumed that at most one network is active at a time. If more
650 * than one is active, it is indeterminate which will be returned.
Robert Greenwalt0659da32009-07-16 17:21:39 -0700651 * @return the info for the active network, or {@code null} if none is
652 * active
The Android Open Source Project28527d22009-03-03 19:31:44 -0800653 */
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700654 @Override
The Android Open Source Project28527d22009-03-03 19:31:44 -0800655 public NetworkInfo getActiveNetworkInfo() {
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700656 enforceAccessPermission();
657 final int uid = Binder.getCallingUid();
658 return getNetworkInfo(mActiveDefaultNetwork, uid);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800659 }
660
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700661 @Override
662 public NetworkInfo getActiveNetworkInfoForUid(int uid) {
663 enforceConnectivityInternalPermission();
664 return getNetworkInfo(mActiveDefaultNetwork, uid);
665 }
666
667 @Override
The Android Open Source Project28527d22009-03-03 19:31:44 -0800668 public NetworkInfo getNetworkInfo(int networkType) {
669 enforceAccessPermission();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700670 final int uid = Binder.getCallingUid();
671 return getNetworkInfo(networkType, uid);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800672 }
673
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700674 private NetworkInfo getNetworkInfo(int networkType, int uid) {
675 NetworkInfo info = null;
676 if (isNetworkTypeValid(networkType)) {
677 final NetworkStateTracker tracker = mNetTrackers[networkType];
678 if (tracker != null) {
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700679 info = getFilteredNetworkInfo(tracker, uid);
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700680 }
681 }
682 return info;
683 }
684
685 @Override
The Android Open Source Project28527d22009-03-03 19:31:44 -0800686 public NetworkInfo[] getAllNetworkInfo() {
687 enforceAccessPermission();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700688 final int uid = Binder.getCallingUid();
Jeff Sharkey21062e72011-05-28 20:56:34 -0700689 final ArrayList<NetworkInfo> result = Lists.newArrayList();
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700690 synchronized (mRulesLock) {
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700691 for (NetworkStateTracker tracker : mNetTrackers) {
692 if (tracker != null) {
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700693 result.add(getFilteredNetworkInfo(tracker, uid));
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700694 }
695 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800696 }
Jeff Sharkey21062e72011-05-28 20:56:34 -0700697 return result.toArray(new NetworkInfo[result.size()]);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800698 }
699
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700700 /**
701 * Return LinkProperties for the active (i.e., connected) default
702 * network interface. It is assumed that at most one default network
703 * is active at a time. If more than one is active, it is indeterminate
704 * which will be returned.
705 * @return the ip properties for the active network, or {@code null} if
706 * none is active
707 */
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700708 @Override
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700709 public LinkProperties getActiveLinkProperties() {
Robert Greenwalte1544bb2011-05-20 12:23:41 -0700710 return getLinkProperties(mActiveDefaultNetwork);
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700711 }
712
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700713 @Override
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700714 public LinkProperties getLinkProperties(int networkType) {
715 enforceAccessPermission();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700716 if (isNetworkTypeValid(networkType)) {
717 final NetworkStateTracker tracker = mNetTrackers[networkType];
718 if (tracker != null) {
719 return tracker.getLinkProperties();
720 }
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700721 }
722 return null;
723 }
724
Jeff Sharkey21062e72011-05-28 20:56:34 -0700725 @Override
726 public NetworkState[] getAllNetworkState() {
727 enforceAccessPermission();
728 final int uid = Binder.getCallingUid();
729 final ArrayList<NetworkState> result = Lists.newArrayList();
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700730 synchronized (mRulesLock) {
Jeff Sharkey21062e72011-05-28 20:56:34 -0700731 for (NetworkStateTracker tracker : mNetTrackers) {
732 if (tracker != null) {
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700733 final NetworkInfo info = getFilteredNetworkInfo(tracker, uid);
Jeff Sharkey21062e72011-05-28 20:56:34 -0700734 result.add(new NetworkState(
735 info, tracker.getLinkProperties(), tracker.getLinkCapabilities()));
736 }
737 }
738 }
739 return result.toArray(new NetworkState[result.size()]);
740 }
741
Jeff Sharkey66fa9682011-08-02 17:22:34 -0700742 private NetworkState getNetworkStateUnchecked(int networkType) {
743 if (isNetworkTypeValid(networkType)) {
744 final NetworkStateTracker tracker = mNetTrackers[networkType];
745 if (tracker != null) {
746 return new NetworkState(tracker.getNetworkInfo(), tracker.getLinkProperties(),
747 tracker.getLinkCapabilities());
748 }
749 }
750 return null;
751 }
752
753 @Override
754 public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
755 enforceAccessPermission();
756 final NetworkState state = getNetworkStateUnchecked(mActiveDefaultNetwork);
757 if (state != null) {
758 try {
759 return mPolicyManager.getNetworkQuotaInfo(state);
760 } catch (RemoteException e) {
761 }
762 }
763 return null;
764 }
765
The Android Open Source Project28527d22009-03-03 19:31:44 -0800766 public boolean setRadios(boolean turnOn) {
767 boolean result = true;
768 enforceChangePermission();
769 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700770 if (t != null) result = t.setRadio(turnOn) && result;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800771 }
772 return result;
773 }
774
775 public boolean setRadio(int netType, boolean turnOn) {
776 enforceChangePermission();
777 if (!ConnectivityManager.isNetworkTypeValid(netType)) {
778 return false;
779 }
780 NetworkStateTracker tracker = mNetTrackers[netType];
781 return tracker != null && tracker.setRadio(turnOn);
782 }
783
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700784 /**
785 * Used to notice when the calling process dies so we can self-expire
786 *
787 * Also used to know if the process has cleaned up after itself when
788 * our auto-expire timer goes off. The timer has a link to an object.
789 *
790 */
Robert Greenwalt2034b912009-08-12 16:08:25 -0700791 private class FeatureUser implements IBinder.DeathRecipient {
792 int mNetworkType;
793 String mFeature;
794 IBinder mBinder;
795 int mPid;
796 int mUid;
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800797 long mCreateTime;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700798
799 FeatureUser(int type, String feature, IBinder binder) {
800 super();
801 mNetworkType = type;
802 mFeature = feature;
803 mBinder = binder;
804 mPid = getCallingPid();
805 mUid = getCallingUid();
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800806 mCreateTime = System.currentTimeMillis();
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700807
Robert Greenwalt2034b912009-08-12 16:08:25 -0700808 try {
809 mBinder.linkToDeath(this, 0);
810 } catch (RemoteException e) {
811 binderDied();
812 }
813 }
814
815 void unlinkDeathRecipient() {
816 mBinder.unlinkToDeath(this, 0);
817 }
818
819 public void binderDied() {
Wink Savillee70c6f52010-12-03 12:01:38 -0800820 log("ConnectivityService FeatureUser binderDied(" +
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800821 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
822 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700823 stopUsingNetworkFeature(this, false);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700824 }
825
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700826 public void expire() {
Robert Greenwalt78f28112011-08-02 17:18:41 -0700827 if (VDBG) {
828 log("ConnectivityService FeatureUser expire(" +
829 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
830 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
831 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700832 stopUsingNetworkFeature(this, false);
833 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800834
Kazuhiro Ondocae18f12011-07-19 11:23:37 -0500835 public boolean isSameUser(FeatureUser u) {
836 if (u == null) return false;
837
838 return isSameUser(u.mPid, u.mUid, u.mNetworkType, u.mFeature);
839 }
840
841 public boolean isSameUser(int pid, int uid, int networkType, String feature) {
842 if ((mPid == pid) && (mUid == uid) && (mNetworkType == networkType) &&
843 TextUtils.equals(mFeature, feature)) {
844 return true;
845 }
846 return false;
847 }
848
Robert Greenwalt3eeb6032009-12-21 18:24:07 -0800849 public String toString() {
850 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
851 (System.currentTimeMillis() - mCreateTime) + " mSec ago";
852 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700853 }
854
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700855 // javadoc from interface
Robert Greenwalt2034b912009-08-12 16:08:25 -0700856 public int startUsingNetworkFeature(int networkType, String feature,
857 IBinder binder) {
858 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800859 log("startUsingNetworkFeature for net " + networkType + ": " + feature);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700860 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800861 enforceChangePermission();
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700862 if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
Robert Greenwalt34848c02011-03-25 13:09:25 -0700863 mNetConfigs[networkType] == null) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700864 return Phone.APN_REQUEST_FAILED;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800865 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700866
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700867 FeatureUser f = new FeatureUser(networkType, feature, binder);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700868
repo syncf5de5572011-07-29 23:55:49 -0700869 // TODO - move this into individual networktrackers
870 int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
Robert Greenwalt6cac0742011-06-21 17:26:14 -0700871
872 if (mProtectedNetworks.contains(usedNetworkType)) {
873 enforceConnectivityInternalPermission();
874 }
875
Robert Greenwalt2034b912009-08-12 16:08:25 -0700876 NetworkStateTracker network = mNetTrackers[usedNetworkType];
877 if (network != null) {
Robert Greenwalt5364d752010-12-15 13:26:33 -0800878 Integer currentPid = new Integer(getCallingPid());
Robert Greenwalt2034b912009-08-12 16:08:25 -0700879 if (usedNetworkType != networkType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700880 NetworkInfo ni = network.getNetworkInfo();
881
882 if (ni.isAvailable() == false) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800883 if (DBG) log("special network not available");
Robert Greenwalt2cc87442010-12-29 14:35:21 -0800884 if (!TextUtils.equals(feature,Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
885 return Phone.APN_TYPE_NOT_AVAILABLE;
886 } else {
887 // else make the attempt anyway - probably giving REQUEST_STARTED below
888 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700889 }
890
Kazuhiro Ondocae18f12011-07-19 11:23:37 -0500891 int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
892
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700893 synchronized(this) {
Kazuhiro Ondocae18f12011-07-19 11:23:37 -0500894 boolean addToList = true;
895 if (restoreTimer < 0) {
896 // In case there is no timer is specified for the feature,
897 // make sure we don't add duplicate entry with the same request.
898 for (FeatureUser u : mFeatureUsers) {
899 if (u.isSameUser(f)) {
900 // Duplicate user is found. Do not add.
901 addToList = false;
902 break;
903 }
904 }
905 }
906
907 if (addToList) mFeatureUsers.add(f);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700908 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
909 // this gets used for per-pid dns when connected
910 mNetRequestersPids[usedNetworkType].add(currentPid);
911 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700912 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700913
Robert Greenwalt20f819c2011-05-03 19:02:44 -0700914 if (restoreTimer >= 0) {
915 mHandler.sendMessageDelayed(
916 mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer);
917 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700918
Robert Greenwalta52c75a2009-08-19 20:19:33 -0700919 if ((ni.isConnectedOrConnecting() == true) &&
920 !network.isTeardownRequested()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700921 if (ni.isConnected() == true) {
922 // add the pid-specific dns
repo sync3035f652011-08-02 13:39:06 -0700923 handleDnsConfigurationChange(usedNetworkType);
Wink Savillee70c6f52010-12-03 12:01:38 -0800924 if (DBG) log("special network already active");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700925 return Phone.APN_ALREADY_ACTIVE;
926 }
Wink Savillee70c6f52010-12-03 12:01:38 -0800927 if (DBG) log("special network already connecting");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700928 return Phone.APN_REQUEST_STARTED;
929 }
930
931 // check if the radio in play can make another contact
932 // assume if cannot for now
933
Wink Savillee70c6f52010-12-03 12:01:38 -0800934 if (DBG) log("reconnecting to special network");
Robert Greenwalt2034b912009-08-12 16:08:25 -0700935 network.reconnect();
936 return Phone.APN_REQUEST_STARTED;
937 } else {
Robert Greenwalt5364d752010-12-15 13:26:33 -0800938 // need to remember this unsupported request so we respond appropriately on stop
939 synchronized(this) {
940 mFeatureUsers.add(f);
941 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
942 // this gets used for per-pid dns when connected
943 mNetRequestersPids[usedNetworkType].add(currentPid);
944 }
945 }
Robert Greenwaltd391e892010-05-18 10:52:51 -0700946 return -1;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700947 }
948 }
949 return Phone.APN_TYPE_NOT_AVAILABLE;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800950 }
951
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700952 // javadoc from interface
The Android Open Source Project28527d22009-03-03 19:31:44 -0800953 public int stopUsingNetworkFeature(int networkType, String feature) {
Robert Greenwalt28f43012009-10-06 17:52:40 -0700954 enforceChangePermission();
955
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700956 int pid = getCallingPid();
957 int uid = getCallingUid();
958
959 FeatureUser u = null;
960 boolean found = false;
961
962 synchronized(this) {
Kazuhiro Ondocae18f12011-07-19 11:23:37 -0500963 for (FeatureUser x : mFeatureUsers) {
964 if (x.isSameUser(pid, uid, networkType, feature)) {
965 u = x;
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700966 found = true;
967 break;
968 }
969 }
970 }
971 if (found && u != null) {
972 // stop regardless of how many other time this proc had called start
973 return stopUsingNetworkFeature(u, true);
974 } else {
975 // none found!
Robert Greenwalt78f28112011-08-02 17:18:41 -0700976 if (VDBG) log("ignoring stopUsingNetworkFeature - not a live request");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700977 return 1;
978 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700979 }
980
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700981 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
982 int networkType = u.mNetworkType;
983 String feature = u.mFeature;
984 int pid = u.mPid;
985 int uid = u.mUid;
986
987 NetworkStateTracker tracker = null;
988 boolean callTeardown = false; // used to carry our decision outside of sync block
989
Robert Greenwalt2034b912009-08-12 16:08:25 -0700990 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800991 log("stopUsingNetworkFeature for net " + networkType +
Robert Greenwalt2034b912009-08-12 16:08:25 -0700992 ": " + feature);
993 }
Robert Greenwalt28f43012009-10-06 17:52:40 -0700994
The Android Open Source Project28527d22009-03-03 19:31:44 -0800995 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
996 return -1;
997 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700998
Robert Greenwaltaffc3a12009-09-27 17:27:04 -0700999 // need to link the mFeatureUsers list with the mNetRequestersPids state in this
1000 // sync block
1001 synchronized(this) {
1002 // check if this process still has an outstanding start request
1003 if (!mFeatureUsers.contains(u)) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001004 if (DBG) log("ignoring - this process has no outstanding requests");
Robert Greenwalt2034b912009-08-12 16:08:25 -07001005 return 1;
1006 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001007 u.unlinkDeathRecipient();
1008 mFeatureUsers.remove(mFeatureUsers.indexOf(u));
1009 // If we care about duplicate requests, check for that here.
1010 //
1011 // This is done to support the extension of a request - the app
1012 // can request we start the network feature again and renew the
1013 // auto-shutoff delay. Normal "stop" calls from the app though
1014 // do not pay attention to duplicate requests - in effect the
1015 // API does not refcount and a single stop will counter multiple starts.
1016 if (ignoreDups == false) {
Kazuhiro Ondocae18f12011-07-19 11:23:37 -05001017 for (FeatureUser x : mFeatureUsers) {
1018 if (x.isSameUser(u)) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001019 if (DBG) log("ignoring stopUsingNetworkFeature as dup is found");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001020 return 1;
1021 }
1022 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001023 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001024
repo syncf5de5572011-07-29 23:55:49 -07001025 // TODO - move to individual network trackers
1026 int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
1027
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001028 tracker = mNetTrackers[usedNetworkType];
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001029 if (tracker == null) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001030 if (DBG) log("ignoring - no known tracker for net type " + usedNetworkType);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001031 return -1;
1032 }
1033 if (usedNetworkType != networkType) {
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001034 Integer currentPid = new Integer(pid);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001035 mNetRequestersPids[usedNetworkType].remove(currentPid);
Robert Greenwalt0ca68a02009-12-17 14:54:59 -08001036 reassessPidDns(pid, true);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001037 if (mNetRequestersPids[usedNetworkType].size() != 0) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001038 if (DBG) log("not tearing down special network - " +
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001039 "others still using it");
1040 return 1;
1041 }
1042 callTeardown = true;
Robert Greenwalt9f3be4c2011-01-10 11:58:31 -08001043 } else {
1044 if (DBG) log("not a known feature - dropping");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001045 }
1046 }
Wink Savillee70c6f52010-12-03 12:01:38 -08001047 if (DBG) log("Doing network teardown");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001048 if (callTeardown) {
1049 tracker.teardown();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001050 return 1;
1051 } else {
Robert Greenwaltd391e892010-05-18 10:52:51 -07001052 return -1;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001053 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001054 }
1055
1056 /**
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -07001057 * @deprecated use requestRouteToHostAddress instead
1058 *
The Android Open Source Project28527d22009-03-03 19:31:44 -08001059 * Ensure that a network route exists to deliver traffic to the specified
1060 * host via the specified network interface.
Robert Greenwalt0659da32009-07-16 17:21:39 -07001061 * @param networkType the type of the network over which traffic to the
1062 * specified host is to be routed
1063 * @param hostAddress the IP address of the host to which the route is
1064 * desired
The Android Open Source Project28527d22009-03-03 19:31:44 -08001065 * @return {@code true} on success, {@code false} on failure
1066 */
1067 public boolean requestRouteToHost(int networkType, int hostAddress) {
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -07001068 InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
1069
1070 if (inetAddress == null) {
1071 return false;
1072 }
1073
1074 return requestRouteToHostAddress(networkType, inetAddress.getAddress());
1075 }
1076
1077 /**
1078 * Ensure that a network route exists to deliver traffic to the specified
1079 * host via the specified network interface.
1080 * @param networkType the type of the network over which traffic to the
1081 * specified host is to be routed
1082 * @param hostAddress the IP address of the host to which the route is
1083 * desired
1084 * @return {@code true} on success, {@code false} on failure
1085 */
1086 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001087 enforceChangePermission();
Robert Greenwalt6cac0742011-06-21 17:26:14 -07001088 if (mProtectedNetworks.contains(networkType)) {
1089 enforceConnectivityInternalPermission();
1090 }
1091
The Android Open Source Project28527d22009-03-03 19:31:44 -08001092 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
1093 return false;
1094 }
1095 NetworkStateTracker tracker = mNetTrackers[networkType];
Robert Greenwalt4666ed02009-09-10 15:06:20 -07001096
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001097 if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
1098 tracker.isTeardownRequested()) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001099 if (VDBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001100 log("requestRouteToHostAddress on down network " +
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -07001101 "(" + networkType + ") - dropped");
Robert Greenwalt4666ed02009-09-10 15:06:20 -07001102 }
1103 return false;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001104 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001105 try {
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -07001106 InetAddress addr = InetAddress.getByAddress(hostAddress);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001107 LinkProperties lp = tracker.getLinkProperties();
Robert Greenwalt98107422011-07-22 11:55:33 -07001108 return addRouteToAddress(lp, addr);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001109 } catch (UnknownHostException e) {}
1110 return false;
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001111 }
1112
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001113 private boolean addRoute(LinkProperties p, RouteInfo r) {
1114 return modifyRoute(p.getInterfaceName(), p, r, 0, true);
Robert Greenwaltbd492212011-05-06 17:10:53 -07001115 }
1116
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001117 private boolean removeRoute(LinkProperties p, RouteInfo r) {
1118 return modifyRoute(p.getInterfaceName(), p, r, 0, false);
1119 }
1120
Robert Greenwalt98107422011-07-22 11:55:33 -07001121 private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) {
1122 return modifyRouteToAddress(lp, addr, true);
1123 }
1124
1125 private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) {
1126 return modifyRouteToAddress(lp, addr, false);
1127 }
1128
1129 private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd) {
1130 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr);
1131 if (bestRoute == null) {
1132 bestRoute = RouteInfo.makeHostRoute(addr);
1133 } else {
1134 if (bestRoute.getGateway().equals(addr)) {
1135 // if there is no better route, add the implied hostroute for our gateway
1136 bestRoute = RouteInfo.makeHostRoute(addr);
1137 } else {
1138 // if we will connect to this through another route, add a direct route
1139 // to it's gateway
1140 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway());
1141 }
1142 }
1143 return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd);
1144 }
1145
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001146 private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount,
1147 boolean doAdd) {
1148 if ((ifaceName == null) || (lp == null) || (r == null)) return false;
1149
1150 if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
1151 loge("Error adding route - too much recursion");
1152 return false;
1153 }
1154
1155 if (r.isHostRoute() == false) {
1156 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), r.getGateway());
1157 if (bestRoute != null) {
Robert Greenwalt57c83bb2011-07-15 09:45:08 -07001158 if (bestRoute.getGateway().equals(r.getGateway())) {
1159 // if there is no better route, add the implied hostroute for our gateway
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001160 bestRoute = RouteInfo.makeHostRoute(r.getGateway());
Robert Greenwalt57c83bb2011-07-15 09:45:08 -07001161 } else {
1162 // if we will connect to our gateway through another route, add a direct
1163 // route to it's gateway
1164 bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway());
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001165 }
Robert Greenwalt57c83bb2011-07-15 09:45:08 -07001166 modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001167 }
1168 }
1169 if (doAdd) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001170 if (VDBG) log("Adding " + r + " for interface " + ifaceName);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001171 mAddedRoutes.add(r);
1172 try {
1173 mNetd.addRoute(ifaceName, r);
1174 } catch (Exception e) {
1175 // never crash - catch them all
Robert Greenwalt78f28112011-08-02 17:18:41 -07001176 if (VDBG) loge("Exception trying to add a route: " + e);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001177 return false;
1178 }
1179 } else {
1180 // if we remove this one and there are no more like it, then refcount==0 and
1181 // we can remove it from the table
1182 mAddedRoutes.remove(r);
1183 if (mAddedRoutes.contains(r) == false) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001184 if (VDBG) log("Removing " + r + " for interface " + ifaceName);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001185 try {
1186 mNetd.removeRoute(ifaceName, r);
1187 } catch (Exception e) {
1188 // never crash - catch them all
Robert Greenwalt78f28112011-08-02 17:18:41 -07001189 if (VDBG) loge("Exception trying to remove a route: " + e);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001190 return false;
1191 }
1192 } else {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001193 if (VDBG) log("not removing " + r + " as it's still in use");
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001194 }
1195 }
1196 return true;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001197 }
1198
1199 /**
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001200 * @see ConnectivityManager#getMobileDataEnabled()
1201 */
1202 public boolean getMobileDataEnabled() {
Wink Savilleb9024c62010-12-07 10:31:02 -08001203 // TODO: This detail should probably be in DataConnectionTracker's
1204 // which is where we store the value and maybe make this
1205 // asynchronous.
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001206 enforceAccessPermission();
1207 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(),
1208 Settings.Secure.MOBILE_DATA, 1) == 1;
Robert Greenwalt78f28112011-08-02 17:18:41 -07001209 if (VDBG) log("getMobileDataEnabled returning " + retVal);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001210 return retVal;
1211 }
1212
Robert Greenwalt34848c02011-03-25 13:09:25 -07001213 public void setDataDependency(int networkType, boolean met) {
Robert Greenwalt6cac0742011-06-21 17:26:14 -07001214 enforceConnectivityInternalPermission();
1215
Robert Greenwalt34848c02011-03-25 13:09:25 -07001216 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
1217 (met ? ENABLED : DISABLED), networkType));
1218 }
1219
1220 private void handleSetDependencyMet(int networkType, boolean met) {
1221 if (mNetTrackers[networkType] != null) {
1222 if (DBG) {
1223 log("handleSetDependencyMet(" + networkType + ", " + met + ")");
1224 }
1225 mNetTrackers[networkType].setDependencyMet(met);
1226 }
1227 }
1228
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001229 private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
1230 @Override
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001231 public void onUidRulesChanged(int uid, int uidRules) {
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001232 // only someone like NPMS should only be calling us
Jeff Sharkey4434b0b2011-06-16 13:04:20 -07001233 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001234
1235 if (LOGD_RULES) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001236 log("onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001237 }
1238
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001239 synchronized (mRulesLock) {
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001240 // skip update when we've already applied rules
1241 final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL);
1242 if (oldRules == uidRules) return;
1243
1244 mUidRules.put(uid, uidRules);
1245 }
1246
1247 // TODO: dispatch into NMS to push rules towards kernel module
1248 // TODO: notify UID when it has requested targeted updates
1249 }
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001250
1251 @Override
1252 public void onMeteredIfacesChanged(String[] meteredIfaces) {
1253 // only someone like NPMS should only be calling us
1254 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1255
1256 if (LOGD_RULES) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001257 log("onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001258 }
1259
1260 synchronized (mRulesLock) {
1261 mMeteredIfaces.clear();
1262 for (String iface : meteredIfaces) {
1263 mMeteredIfaces.add(iface);
1264 }
1265 }
1266 }
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001267 };
1268
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001269 /**
1270 * @see ConnectivityManager#setMobileDataEnabled(boolean)
1271 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001272 public void setMobileDataEnabled(boolean enabled) {
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001273 enforceChangePermission();
Wink Savillee70c6f52010-12-03 12:01:38 -08001274 if (DBG) log("setMobileDataEnabled(" + enabled + ")");
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001275
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001276 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
Robert Greenwalt34848c02011-03-25 13:09:25 -07001277 (enabled ? ENABLED : DISABLED), 0));
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001278 }
1279
1280 private void handleSetMobileData(boolean enabled) {
Wink Savilleb9024c62010-12-07 10:31:02 -08001281 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001282 if (VDBG) {
1283 log(mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001284 }
Wink Savilleb9024c62010-12-07 10:31:02 -08001285 mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001286 }
1287 }
1288
The Android Open Source Project28527d22009-03-03 19:31:44 -08001289 private void enforceAccessPermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001290 mContext.enforceCallingOrSelfPermission(
1291 android.Manifest.permission.ACCESS_NETWORK_STATE,
1292 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001293 }
1294
1295 private void enforceChangePermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001296 mContext.enforceCallingOrSelfPermission(
1297 android.Manifest.permission.CHANGE_NETWORK_STATE,
1298 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001299 }
1300
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001301 // TODO Make this a special check when it goes public
1302 private void enforceTetherChangePermission() {
1303 mContext.enforceCallingOrSelfPermission(
1304 android.Manifest.permission.CHANGE_NETWORK_STATE,
1305 "ConnectivityService");
1306 }
1307
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001308 private void enforceTetherAccessPermission() {
1309 mContext.enforceCallingOrSelfPermission(
1310 android.Manifest.permission.ACCESS_NETWORK_STATE,
1311 "ConnectivityService");
1312 }
1313
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001314 private void enforceConnectivityInternalPermission() {
1315 mContext.enforceCallingOrSelfPermission(
1316 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1317 "ConnectivityService");
1318 }
1319
The Android Open Source Project28527d22009-03-03 19:31:44 -08001320 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -07001321 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
1322 * network, we ignore it. If it is for the active network, we send out a
1323 * broadcast. But first, we check whether it might be possible to connect
1324 * to a different network.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001325 * @param info the {@code NetworkInfo} for the network
1326 */
1327 private void handleDisconnect(NetworkInfo info) {
1328
Robert Greenwalt2034b912009-08-12 16:08:25 -07001329 int prevNetType = info.getType();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001330
Robert Greenwalt2034b912009-08-12 16:08:25 -07001331 mNetTrackers[prevNetType].setTeardownRequested(false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001332 /*
1333 * If the disconnected network is not the active one, then don't report
1334 * this as a loss of connectivity. What probably happened is that we're
1335 * getting the disconnect for a network that we explicitly disabled
1336 * in accordance with network preference policies.
1337 */
Robert Greenwalt34848c02011-03-25 13:09:25 -07001338 if (!mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001339 List pids = mNetRequestersPids[prevNetType];
1340 for (int i = 0; i<pids.size(); i++) {
1341 Integer pid = (Integer)pids.get(i);
1342 // will remove them because the net's no longer connected
1343 // need to do this now as only now do we know the pids and
1344 // can properly null things that are no longer referenced.
1345 reassessPidDns(pid.intValue(), false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001346 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001347 }
1348
The Android Open Source Project28527d22009-03-03 19:31:44 -08001349 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1350 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1351 if (info.isFailover()) {
1352 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1353 info.setFailover(false);
1354 }
1355 if (info.getReason() != null) {
1356 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1357 }
1358 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001359 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1360 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001361 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001362
Robert Greenwalt34848c02011-03-25 13:09:25 -07001363 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001364 tryFailover(prevNetType);
1365 if (mActiveDefaultNetwork != -1) {
1366 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001367 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1368 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001369 mDefaultInetConditionPublished = 0; // we're not connected anymore
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001370 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1371 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001372 }
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001373 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001374
1375 // Reset interface if no other connections are using the same interface
1376 boolean doReset = true;
1377 LinkProperties linkProperties = mNetTrackers[prevNetType].getLinkProperties();
1378 if (linkProperties != null) {
1379 String oldIface = linkProperties.getInterfaceName();
1380 if (TextUtils.isEmpty(oldIface) == false) {
1381 for (NetworkStateTracker networkStateTracker : mNetTrackers) {
1382 if (networkStateTracker == null) continue;
1383 NetworkInfo networkInfo = networkStateTracker.getNetworkInfo();
1384 if (networkInfo.isConnected() && networkInfo.getType() != prevNetType) {
1385 LinkProperties l = networkStateTracker.getLinkProperties();
1386 if (l == null) continue;
1387 if (oldIface.equals(l.getInterfaceName())) {
1388 doReset = false;
1389 break;
1390 }
1391 }
1392 }
1393 }
1394 }
1395
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001396 // do this before we broadcast the change
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001397 handleConnectivityChange(prevNetType, doReset);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001398
Wink Saville4f0de1e2011-08-04 15:01:58 -07001399 sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001400 /*
1401 * If the failover network is already connected, then immediately send
1402 * out a followup broadcast indicating successful failover
1403 */
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001404 if (mActiveDefaultNetwork != -1) {
Wink Saville4f0de1e2011-08-04 15:01:58 -07001405 sendConnectedBroadcastDelayed(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(),
1406 getConnectivityChangeDelay());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001407 }
1408 }
1409
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001410 private void tryFailover(int prevNetType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001411 /*
Robert Greenwalt92564852011-01-06 15:41:07 -08001412 * If this is a default network, check if other defaults are available.
1413 * Try to reconnect on all available and let them hash it out when
1414 * more than one connects.
Robert Greenwalt2034b912009-08-12 16:08:25 -07001415 */
Robert Greenwalt34848c02011-03-25 13:09:25 -07001416 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001417 if (mActiveDefaultNetwork == prevNetType) {
1418 mActiveDefaultNetwork = -1;
1419 }
1420
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001421 // don't signal a reconnect for anything lower or equal priority than our
1422 // current connected default
1423 // TODO - don't filter by priority now - nice optimization but risky
1424// int currentPriority = -1;
1425// if (mActiveDefaultNetwork != -1) {
Robert Greenwalt34848c02011-03-25 13:09:25 -07001426// currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority;
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001427// }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001428 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001429 if (checkType == prevNetType) continue;
Robert Greenwalt34848c02011-03-25 13:09:25 -07001430 if (mNetConfigs[checkType] == null) continue;
1431 if (!mNetConfigs[checkType].isDefault()) continue;
Wink Saville72a95b92011-01-26 15:43:49 -08001432
1433// Enabling the isAvailable() optimization caused mobile to not get
1434// selected if it was in the middle of error handling. Specifically
1435// a moble connection that took 30 seconds to complete the DEACTIVATE_DATA_CALL
1436// would not be available and we wouldn't get connected to anything.
1437// So removing the isAvailable() optimization below for now. TODO: This
1438// optimization should work and we need to investigate why it doesn't work.
1439// This could be related to how DEACTIVATE_DATA_CALL is reporting its
1440// complete before it is really complete.
1441// if (!mNetTrackers[checkType].isAvailable()) continue;
1442
Robert Greenwalt34848c02011-03-25 13:09:25 -07001443// if (currentPriority >= mNetConfigs[checkType].mPriority) continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001444
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001445 NetworkStateTracker checkTracker = mNetTrackers[checkType];
1446 NetworkInfo checkInfo = checkTracker.getNetworkInfo();
1447 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
1448 checkInfo.setFailover(true);
1449 checkTracker.reconnect();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001450 }
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001451 if (DBG) log("Attempting to switch to " + checkInfo.getTypeName());
Robert Greenwalt2034b912009-08-12 16:08:25 -07001452 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001453 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001454 }
1455
1456 private void sendConnectedBroadcast(NetworkInfo info) {
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001457 sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION);
1458 }
1459
Wink Saville4f0de1e2011-08-04 15:01:58 -07001460 private void sendConnectedBroadcastDelayed(NetworkInfo info, int delayMs) {
1461 sendGeneralBroadcastDelayed(info, ConnectivityManager.CONNECTIVITY_ACTION, delayMs);
1462 }
1463
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001464 private void sendInetConditionBroadcast(NetworkInfo info) {
1465 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1466 }
1467
Wink Saville4f0de1e2011-08-04 15:01:58 -07001468 private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001469 Intent intent = new Intent(bcastType);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001470 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1471 if (info.isFailover()) {
1472 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1473 info.setFailover(false);
1474 }
1475 if (info.getReason() != null) {
1476 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1477 }
1478 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001479 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1480 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001481 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07001482 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Wink Saville4f0de1e2011-08-04 15:01:58 -07001483 return intent;
1484 }
1485
1486 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1487 sendStickyBroadcast(makeGeneralIntent(info, bcastType));
1488 }
1489
1490 private void sendGeneralBroadcastDelayed(NetworkInfo info, String bcastType, int delayMs) {
1491 sendStickyBroadcastDelayed(makeGeneralIntent(info, bcastType), delayMs);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001492 }
1493
1494 /**
1495 * Called when an attempt to fail over to another network has failed.
1496 * @param info the {@link NetworkInfo} for the failed network
1497 */
1498 private void handleConnectionFailure(NetworkInfo info) {
1499 mNetTrackers[info.getType()].setTeardownRequested(false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001500
Robert Greenwalt2034b912009-08-12 16:08:25 -07001501 String reason = info.getReason();
1502 String extraInfo = info.getExtraInfo();
Robert Greenwalt0659da32009-07-16 17:21:39 -07001503
Robert Greenwalte981bc52010-10-08 16:35:52 -07001504 String reasonText;
1505 if (reason == null) {
1506 reasonText = ".";
1507 } else {
1508 reasonText = " (" + reason + ").";
The Android Open Source Project28527d22009-03-03 19:31:44 -08001509 }
Wink Savillee70c6f52010-12-03 12:01:38 -08001510 loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001511
1512 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
1513 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
1514 if (getActiveNetworkInfo() == null) {
1515 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1516 }
1517 if (reason != null) {
1518 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
1519 }
1520 if (extraInfo != null) {
1521 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
1522 }
1523 if (info.isFailover()) {
1524 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1525 info.setFailover(false);
1526 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001527
Robert Greenwalt34848c02011-03-25 13:09:25 -07001528 if (mNetConfigs[info.getType()].isDefault()) {
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001529 tryFailover(info.getType());
1530 if (mActiveDefaultNetwork != -1) {
1531 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001532 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1533 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001534 mDefaultInetConditionPublished = 0;
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001535 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1536 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001537 }
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001538
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001539 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001540 sendStickyBroadcast(intent);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001541 /*
1542 * If the failover network is already connected, then immediately send
1543 * out a followup broadcast indicating successful failover
1544 */
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001545 if (mActiveDefaultNetwork != -1) {
1546 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001547 }
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001548 }
1549
1550 private void sendStickyBroadcast(Intent intent) {
1551 synchronized(this) {
Dianne Hackborna417ff82009-12-08 19:45:14 -08001552 if (!mSystemReady) {
1553 mInitialBroadcast = new Intent(intent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001554 }
Dianne Hackborna417ff82009-12-08 19:45:14 -08001555 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Wink Saville4f0de1e2011-08-04 15:01:58 -07001556 if (DBG) {
1557 log("sendStickyBroadcast: NetworkInfo=" +
1558 intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
1559 }
1560
Dianne Hackborna417ff82009-12-08 19:45:14 -08001561 mContext.sendStickyBroadcast(intent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001562 }
1563 }
1564
Wink Saville4f0de1e2011-08-04 15:01:58 -07001565 private void sendStickyBroadcastDelayed(Intent intent, int delayMs) {
1566 if (delayMs <= 0) {
1567 sendStickyBroadcast(intent);
1568 } else {
1569 if (DBG) log("sendStickyBroadcastDelayed: delayMs=" + delayMs + " intent=" + intent);
1570 mHandler.sendMessageDelayed(mHandler.obtainMessage(
1571 EVENT_SEND_STICKY_BROADCAST_INTENT, intent), delayMs);
1572 }
1573 }
1574
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001575 void systemReady() {
1576 synchronized(this) {
1577 mSystemReady = true;
Dianne Hackborna417ff82009-12-08 19:45:14 -08001578 if (mInitialBroadcast != null) {
1579 mContext.sendStickyBroadcast(mInitialBroadcast);
1580 mInitialBroadcast = null;
Mike Lockwoodfde2b762009-08-14 14:18:49 -04001581 }
1582 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07001583 // load the global proxy at startup
1584 mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
The Android Open Source Project28527d22009-03-03 19:31:44 -08001585 }
1586
1587 private void handleConnect(NetworkInfo info) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001588 int type = info.getType();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001589
1590 // snapshot isFailover, because sendConnectedBroadcast() resets it
1591 boolean isFailover = info.isFailover();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001592 NetworkStateTracker thisNet = mNetTrackers[type];
The Android Open Source Project28527d22009-03-03 19:31:44 -08001593
Robert Greenwalt2034b912009-08-12 16:08:25 -07001594 // if this is a default net and other default is running
1595 // kill the one not preferred
Robert Greenwalt34848c02011-03-25 13:09:25 -07001596 if (mNetConfigs[type].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001597 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
1598 if ((type != mNetworkPreference &&
Wink Savillef2a62832011-04-07 14:23:45 -07001599 mNetConfigs[mActiveDefaultNetwork].priority >
1600 mNetConfigs[type].priority) ||
Robert Greenwalt2034b912009-08-12 16:08:25 -07001601 mNetworkPreference == mActiveDefaultNetwork) {
1602 // don't accept this one
Robert Greenwalt78f28112011-08-02 17:18:41 -07001603 if (VDBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001604 log("Not broadcasting CONNECT_ACTION " +
Robert Greenwalt2034b912009-08-12 16:08:25 -07001605 "to torn down network " + info.getTypeName());
Wink Savillee70c6f52010-12-03 12:01:38 -08001606 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001607 teardown(thisNet);
1608 return;
1609 } else {
1610 // tear down the other
1611 NetworkStateTracker otherNet =
1612 mNetTrackers[mActiveDefaultNetwork];
Wink Savillee70c6f52010-12-03 12:01:38 -08001613 if (DBG) {
1614 log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
Robert Greenwalt2034b912009-08-12 16:08:25 -07001615 " teardown");
Wink Savillee70c6f52010-12-03 12:01:38 -08001616 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001617 if (!teardown(otherNet)) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001618 loge("Network declined teardown request");
Robert Greenwalt99910172011-03-29 11:36:28 -07001619 teardown(thisNet);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001620 return;
1621 }
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001622 }
1623 }
1624 synchronized (ConnectivityService.this) {
1625 // have a new default network, release the transition wakelock in a second
1626 // if it's held. The second pause is to allow apps to reconnect over the
1627 // new network
1628 if (mNetTransitionWakeLock.isHeld()) {
1629 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltccb36f92010-09-24 14:32:21 -07001630 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001631 mNetTransitionWakeLockSerialNumber, 0),
1632 1000);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001633 }
1634 }
1635 mActiveDefaultNetwork = type;
Robert Greenwalt986c7412010-09-08 15:24:47 -07001636 // this will cause us to come up initially as unconnected and switching
1637 // to connected after our normal pause unless somebody reports us as reall
1638 // disconnected
1639 mDefaultInetConditionPublished = 0;
1640 mDefaultConnectionSequence++;
1641 mInetConditionChangeInFlight = false;
1642 // Don't do this - if we never sign in stay, grey
1643 //reportNetworkCondition(mActiveDefaultNetwork, 100);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001644 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001645 thisNet.setTeardownRequested(false);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001646 updateNetworkSettings(thisNet);
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001647 handleConnectivityChange(type, false);
Wink Saville4f0de1e2011-08-04 15:01:58 -07001648 sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001649 }
1650
The Android Open Source Project28527d22009-03-03 19:31:44 -08001651 /**
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001652 * After a change in the connectivity state of a network. We're mainly
1653 * concerned with making sure that the list of DNS servers is set up
1654 * according to which networks are connected, and ensuring that the
1655 * right routing table entries exist.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001656 */
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001657 private void handleConnectivityChange(int netType, boolean doReset) {
Wink Saville051a6642011-07-13 13:44:13 -07001658 int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0;
1659
The Android Open Source Project28527d22009-03-03 19:31:44 -08001660 /*
Robert Greenwalt2034b912009-08-12 16:08:25 -07001661 * If a non-default network is enabled, add the host routes that
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001662 * will allow it's DNS servers to be accessed.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001663 */
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001664 handleDnsConfigurationChange(netType);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001665
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001666 LinkProperties curLp = mCurrentLinkProperties[netType];
1667 LinkProperties newLp = null;
1668
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001669 if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001670 newLp = mNetTrackers[netType].getLinkProperties();
Wink Saville051a6642011-07-13 13:44:13 -07001671 if (VDBG) {
1672 log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
1673 " doReset=" + doReset + " resetMask=" + resetMask +
1674 "\n curLp=" + curLp +
1675 "\n newLp=" + newLp);
1676 }
1677
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001678 if (curLp != null) {
1679 if (curLp.isIdenticalInterfaceName(newLp)) {
1680 CompareResult<LinkAddress> car = curLp.compareAddresses(newLp);
1681 if ((car.removed.size() != 0) || (car.added.size() != 0)) {
1682 for (LinkAddress linkAddr : car.removed) {
1683 if (linkAddr.getAddress() instanceof Inet4Address) {
1684 resetMask |= NetworkUtils.RESET_IPV4_ADDRESSES;
1685 }
1686 if (linkAddr.getAddress() instanceof Inet6Address) {
1687 resetMask |= NetworkUtils.RESET_IPV6_ADDRESSES;
1688 }
Wink Saville051a6642011-07-13 13:44:13 -07001689 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001690 if (DBG) {
1691 log("handleConnectivityChange: addresses changed" +
1692 " linkProperty[" + netType + "]:" + " resetMask=" + resetMask +
1693 "\n car=" + car);
Wink Saville051a6642011-07-13 13:44:13 -07001694 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001695 } else {
1696 if (DBG) {
1697 log("handleConnectivityChange: address are the same reset per doReset" +
1698 " linkProperty[" + netType + "]:" +
1699 " resetMask=" + resetMask);
1700 }
Wink Saville051a6642011-07-13 13:44:13 -07001701 }
1702 } else {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001703 resetMask = NetworkUtils.RESET_ALL_ADDRESSES;
Robert Greenwalt78f28112011-08-02 17:18:41 -07001704 if (DBG) {
1705 log("handleConnectivityChange: interface not not equivalent reset both" +
1706 " linkProperty[" + netType + "]:" +
1707 " resetMask=" + resetMask);
1708 }
Wink Saville051a6642011-07-13 13:44:13 -07001709 }
Wink Saville051a6642011-07-13 13:44:13 -07001710 }
Robert Greenwalt34848c02011-03-25 13:09:25 -07001711 if (mNetConfigs[netType].isDefault()) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07001712 handleApplyDefaultProxy(netType);
Robert Greenwalt3afbead2010-07-23 15:46:26 -07001713 }
1714 } else {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001715 if (VDBG) {
1716 log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
1717 " doReset=" + doReset + " resetMask=" + resetMask +
1718 "\n curLp=" + curLp +
1719 "\n newLp= null");
Robert Greenwalt2034b912009-08-12 16:08:25 -07001720 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001721 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001722 mCurrentLinkProperties[netType] = newLp;
Robert Greenwalt8d777252011-08-15 12:31:55 -07001723 boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault());
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001724
Chia-chi Yeh4a243f52011-08-15 15:19:40 -07001725 if (resetMask != 0 || resetDns) {
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001726 LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties();
1727 if (linkProperties != null) {
1728 String iface = linkProperties.getInterfaceName();
1729 if (TextUtils.isEmpty(iface) == false) {
Chia-chi Yeh4a243f52011-08-15 15:19:40 -07001730 if (resetMask != 0) {
Robert Greenwalt8d777252011-08-15 12:31:55 -07001731 if (DBG) log("resetConnections(" + iface + ", " + resetMask + ")");
1732 NetworkUtils.resetConnections(iface, resetMask);
Chia-chi Yeh4a243f52011-08-15 15:19:40 -07001733
1734 // Tell VPN the interface is down. It is a temporary
1735 // but effective fix to make VPN aware of the change.
1736 if ((resetMask & NetworkUtils.RESET_IPV4_ADDRESSES) != 0) {
1737 mVpn.interfaceStatusChanged(iface, false);
1738 }
Robert Greenwalt8d777252011-08-15 12:31:55 -07001739 }
1740 if (resetDns) {
1741 if (DBG) log("resetting DNS cache for " + iface);
1742 try {
1743 mNetd.flushInterfaceDnsCache(iface);
1744 } catch (Exception e) {
1745 // never crash - catch them all
1746 loge("Exception resetting dns cache: " + e);
1747 }
1748 }
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001749 }
1750 }
1751 }
Kazuhiro Ondo07680062011-06-22 21:10:34 -05001752
1753 // TODO: Temporary notifying upstread change to Tethering.
1754 // @see bug/4455071
1755 /** Notify TetheringService if interface name has been changed. */
1756 if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
1757 Phone.REASON_LINK_PROPERTIES_CHANGED)) {
1758 if (isTetheringSupported()) {
1759 mTethering.handleTetherIfaceChange();
1760 }
1761 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001762 }
1763
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001764 /**
1765 * Add and remove routes using the old properties (null if not previously connected),
1766 * new properties (null if becoming disconnected). May even be double null, which
1767 * is a noop.
1768 * Uses isLinkDefault to determine if default routes should be set or conversely if
1769 * host routes should be set to the dns servers
Robert Greenwalt8d777252011-08-15 12:31:55 -07001770 * returns a boolean indicating the routes changed
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001771 */
Robert Greenwalt8d777252011-08-15 12:31:55 -07001772 private boolean updateRoutes(LinkProperties newLp, LinkProperties curLp,
1773 boolean isLinkDefault) {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001774 Collection<RouteInfo> routesToAdd = null;
Robert Greenwalt98107422011-07-22 11:55:33 -07001775 CompareResult<InetAddress> dnsDiff = new CompareResult<InetAddress>();
1776 CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>();
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001777 if (curLp != null) {
1778 // check for the delta between the current set and the new
Robert Greenwalt98107422011-07-22 11:55:33 -07001779 routeDiff = curLp.compareRoutes(newLp);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001780 dnsDiff = curLp.compareDnses(newLp);
Robert Greenwalt98107422011-07-22 11:55:33 -07001781 } else if (newLp != null) {
1782 routeDiff.added = newLp.getRoutes();
1783 dnsDiff.added = newLp.getDnses();
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001784 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001785
Robert Greenwalt8d777252011-08-15 12:31:55 -07001786 boolean routesChanged = (routeDiff.removed.size() != 0 || routeDiff.added.size() != 0);
1787
Robert Greenwalt98107422011-07-22 11:55:33 -07001788 for (RouteInfo r : routeDiff.removed) {
1789 if (isLinkDefault || ! r.isDefaultRoute()) {
1790 removeRoute(curLp, r);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001791 }
Robert Greenwalt98107422011-07-22 11:55:33 -07001792 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001793
Robert Greenwalt98107422011-07-22 11:55:33 -07001794 for (RouteInfo r : routeDiff.added) {
1795 if (isLinkDefault || ! r.isDefaultRoute()) {
1796 addRoute(newLp, r);
Robert Greenwalt08ae9bc2011-08-09 16:52:58 -07001797 } else {
1798 // many radios add a default route even when we don't want one.
1799 // remove the default route unless somebody else has asked for it
1800 String ifaceName = newLp.getInterfaceName();
1801 if (TextUtils.isEmpty(ifaceName) == false && mAddedRoutes.contains(r) == false) {
1802 if (DBG) log("Removing " + r + " for interface " + ifaceName);
1803 try {
1804 mNetd.removeRoute(ifaceName, r);
1805 } catch (Exception e) {
1806 // never crash - catch them all
1807 loge("Exception trying to remove a route: " + e);
1808 }
1809 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001810 }
1811 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001812
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001813 if (!isLinkDefault) {
1814 // handle DNS routes
Robert Greenwalt8d777252011-08-15 12:31:55 -07001815 if (routesChanged) {
Robert Greenwalt98107422011-07-22 11:55:33 -07001816 // routes changed - remove all old dns entries and add new
1817 if (curLp != null) {
1818 for (InetAddress oldDns : curLp.getDnses()) {
1819 removeRouteToAddress(curLp, oldDns);
1820 }
1821 }
1822 if (newLp != null) {
1823 for (InetAddress newDns : newLp.getDnses()) {
1824 addRouteToAddress(newLp, newDns);
1825 }
Robert Greenwalt03d53da2011-03-22 18:47:42 -07001826 }
Robert Greenwalt8d777252011-08-15 12:31:55 -07001827 } else {
1828 // no change in routes, check for change in dns themselves
1829 for (InetAddress oldDns : dnsDiff.removed) {
1830 removeRouteToAddress(curLp, oldDns);
1831 }
1832 for (InetAddress newDns : dnsDiff.added) {
1833 addRouteToAddress(newLp, newDns);
1834 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001835 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001836 }
Robert Greenwalt8d777252011-08-15 12:31:55 -07001837 return routesChanged;
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001838 }
1839
1840
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001841 /**
1842 * Reads the network specific TCP buffer sizes from SystemProperties
1843 * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
1844 * wide use
1845 */
1846 public void updateNetworkSettings(NetworkStateTracker nt) {
1847 String key = nt.getTcpBufferSizesPropName();
1848 String bufferSizes = SystemProperties.get(key);
1849
1850 if (bufferSizes.length() == 0) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001851 if (VDBG) log(key + " not found in system properties. Using defaults");
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001852
1853 // Setting to default values so we won't be stuck to previous values
1854 key = "net.tcp.buffersize.default";
1855 bufferSizes = SystemProperties.get(key);
1856 }
1857
1858 // Set values in kernel
1859 if (bufferSizes.length() != 0) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001860 if (VDBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001861 log("Setting TCP values: [" + bufferSizes
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001862 + "] which comes from [" + key + "]");
1863 }
1864 setBufferSize(bufferSizes);
1865 }
1866 }
1867
1868 /**
1869 * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max]
1870 * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem
1871 *
1872 * @param bufferSizes in the format of "readMin, readInitial, readMax,
1873 * writeMin, writeInitial, writeMax"
1874 */
1875 private void setBufferSize(String bufferSizes) {
1876 try {
1877 String[] values = bufferSizes.split(",");
1878
1879 if (values.length == 6) {
1880 final String prefix = "/sys/kernel/ipv4/tcp_";
Mike Lockwood0d5916c2011-05-28 13:24:04 -04001881 FileUtils.stringToFile(prefix + "rmem_min", values[0]);
1882 FileUtils.stringToFile(prefix + "rmem_def", values[1]);
1883 FileUtils.stringToFile(prefix + "rmem_max", values[2]);
1884 FileUtils.stringToFile(prefix + "wmem_min", values[3]);
1885 FileUtils.stringToFile(prefix + "wmem_def", values[4]);
1886 FileUtils.stringToFile(prefix + "wmem_max", values[5]);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001887 } else {
Wink Savillee70c6f52010-12-03 12:01:38 -08001888 loge("Invalid buffersize string: " + bufferSizes);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001889 }
1890 } catch (IOException e) {
Wink Savillee70c6f52010-12-03 12:01:38 -08001891 loge("Can't set tcp buffer sizes:" + e);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001892 }
1893 }
1894
Robert Greenwalt2034b912009-08-12 16:08:25 -07001895 /**
1896 * Adjust the per-process dns entries (net.dns<x>.<pid>) based
1897 * on the highest priority active net which this process requested.
1898 * If there aren't any, clear it out
1899 */
1900 private void reassessPidDns(int myPid, boolean doBump)
1901 {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001902 if (VDBG) log("reassessPidDns for pid " + myPid);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001903 for(int i : mPriorityList) {
Robert Greenwalt34848c02011-03-25 13:09:25 -07001904 if (mNetConfigs[i].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001905 continue;
1906 }
1907 NetworkStateTracker nt = mNetTrackers[i];
Robert Greenwalt0659da32009-07-16 17:21:39 -07001908 if (nt.getNetworkInfo().isConnected() &&
1909 !nt.isTeardownRequested()) {
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001910 LinkProperties p = nt.getLinkProperties();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001911 if (p == null) continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001912 List pids = mNetRequestersPids[i];
1913 for (int j=0; j<pids.size(); j++) {
1914 Integer pid = (Integer)pids.get(j);
1915 if (pid.intValue() == myPid) {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001916 Collection<InetAddress> dnses = p.getDnses();
1917 writePidDns(dnses, myPid);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001918 if (doBump) {
1919 bumpDns();
1920 }
1921 return;
1922 }
1923 }
1924 }
1925 }
1926 // nothing found - delete
1927 for (int i = 1; ; i++) {
1928 String prop = "net.dns" + i + "." + myPid;
1929 if (SystemProperties.get(prop).length() == 0) {
1930 if (doBump) {
1931 bumpDns();
1932 }
1933 return;
1934 }
1935 SystemProperties.set(prop, "");
1936 }
1937 }
1938
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001939 // return true if results in a change
1940 private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001941 int j = 1;
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001942 boolean changed = false;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001943 for (InetAddress dns : dnses) {
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001944 String dnsString = dns.getHostAddress();
1945 if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
1946 changed = true;
1947 SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
1948 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001949 }
Robert Greenwalt8ca88762010-12-17 15:20:36 -08001950 return changed;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001951 }
1952
1953 private void bumpDns() {
1954 /*
1955 * Bump the property that tells the name resolver library to reread
1956 * the DNS server list from the properties.
1957 */
1958 String propVal = SystemProperties.get("net.dnschange");
1959 int n = 0;
1960 if (propVal.length() != 0) {
1961 try {
1962 n = Integer.parseInt(propVal);
1963 } catch (NumberFormatException e) {}
1964 }
1965 SystemProperties.set("net.dnschange", "" + (n+1));
Robert Greenwalt051642b2010-11-02 14:08:23 -07001966 /*
1967 * Tell the VMs to toss their DNS caches
1968 */
1969 Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
1970 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Stan Chesnuttf444f502011-01-05 17:14:03 -08001971 /*
1972 * Connectivity events can happen before boot has completed ...
1973 */
1974 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt051642b2010-11-02 14:08:23 -07001975 mContext.sendBroadcast(intent);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001976 }
1977
Chia-chi Yehcc844502011-07-14 18:01:57 -07001978 // Caller must grab mDnsLock.
Robert Greenwaltfce71862011-07-25 16:06:25 -07001979 private boolean updateDns(String network, String iface,
1980 Collection<InetAddress> dnses, String domains) {
Chia-chi Yehcc844502011-07-14 18:01:57 -07001981 boolean changed = false;
1982 int last = 0;
1983 if (dnses.size() == 0 && mDefaultDns != null) {
1984 ++last;
1985 String value = mDefaultDns.getHostAddress();
1986 if (!value.equals(SystemProperties.get("net.dns1"))) {
1987 if (DBG) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001988 loge("no dns provided for " + network + " - using " + value);
Chia-chi Yehcc844502011-07-14 18:01:57 -07001989 }
1990 changed = true;
1991 SystemProperties.set("net.dns1", value);
1992 }
1993 } else {
1994 for (InetAddress dns : dnses) {
1995 ++last;
1996 String key = "net.dns" + last;
1997 String value = dns.getHostAddress();
1998 if (!changed && value.equals(SystemProperties.get(key))) {
1999 continue;
2000 }
Robert Greenwalt78f28112011-08-02 17:18:41 -07002001 if (VDBG) {
Chia-chi Yehcc844502011-07-14 18:01:57 -07002002 log("adding dns " + value + " for " + network);
2003 }
2004 changed = true;
2005 SystemProperties.set(key, value);
2006 }
2007 }
2008 for (int i = last + 1; i <= mNumDnsEntries; ++i) {
2009 String key = "net.dns" + i;
Robert Greenwalt78f28112011-08-02 17:18:41 -07002010 if (VDBG) log("erasing " + key);
Chia-chi Yehcc844502011-07-14 18:01:57 -07002011 changed = true;
2012 SystemProperties.set(key, "");
2013 }
2014 mNumDnsEntries = last;
2015
Robert Greenwaltfce71862011-07-25 16:06:25 -07002016 if (changed) {
2017 try {
2018 mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses));
2019 mNetd.setDefaultInterfaceForDns(iface);
2020 } catch (Exception e) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002021 loge("exception setting default dns interface: " + e);
Robert Greenwaltfce71862011-07-25 16:06:25 -07002022 }
2023 }
Chia-chi Yehcc844502011-07-14 18:01:57 -07002024 if (!domains.equals(SystemProperties.get("net.dns.search"))) {
2025 SystemProperties.set("net.dns.search", domains);
2026 changed = true;
2027 }
2028 return changed;
2029 }
2030
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002031 private void handleDnsConfigurationChange(int netType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07002032 // add default net's dns entries
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002033 NetworkStateTracker nt = mNetTrackers[netType];
2034 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07002035 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002036 if (p == null) return;
2037 Collection<InetAddress> dnses = p.getDnses();
Robert Greenwalt8ca88762010-12-17 15:20:36 -08002038 boolean changed = false;
Robert Greenwalt34848c02011-03-25 13:09:25 -07002039 if (mNetConfigs[netType].isDefault()) {
Chia-chi Yehcc844502011-07-14 18:01:57 -07002040 String network = nt.getNetworkInfo().getTypeName();
2041 synchronized (mDnsLock) {
2042 if (!mDnsOverridden) {
Robert Greenwaltfce71862011-07-25 16:06:25 -07002043 changed = updateDns(network, p.getInterfaceName(), dnses, "");
Robert Greenwalt94daa182010-09-01 11:34:05 -07002044 }
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002045 }
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002046 } else {
Robert Greenwaltfce71862011-07-25 16:06:25 -07002047 try {
Robert Greenwalt49f762e2011-07-27 10:00:36 -07002048 mNetd.setDnsServersForInterface(p.getInterfaceName(),
Robert Greenwaltfce71862011-07-25 16:06:25 -07002049 NetworkUtils.makeStrings(dnses));
2050 } catch (Exception e) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002051 loge("exception setting dns servers: " + e);
Robert Greenwaltfce71862011-07-25 16:06:25 -07002052 }
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002053 // set per-pid dns for attached secondary nets
2054 List pids = mNetRequestersPids[netType];
2055 for (int y=0; y< pids.size(); y++) {
2056 Integer pid = (Integer)pids.get(y);
Robert Greenwalt8ca88762010-12-17 15:20:36 -08002057 changed = writePidDns(dnses, pid.intValue());
The Android Open Source Project28527d22009-03-03 19:31:44 -08002058 }
2059 }
Robert Greenwalt8ca88762010-12-17 15:20:36 -08002060 if (changed) bumpDns();
The Android Open Source Project28527d22009-03-03 19:31:44 -08002061 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07002062 }
2063
Robert Greenwalt20f819c2011-05-03 19:02:44 -07002064 private int getRestoreDefaultNetworkDelay(int networkType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07002065 String restoreDefaultNetworkDelayStr = SystemProperties.get(
2066 NETWORK_RESTORE_DELAY_PROP_NAME);
2067 if(restoreDefaultNetworkDelayStr != null &&
2068 restoreDefaultNetworkDelayStr.length() != 0) {
2069 try {
2070 return Integer.valueOf(restoreDefaultNetworkDelayStr);
2071 } catch (NumberFormatException e) {
2072 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002073 }
Robert Greenwalt20f819c2011-05-03 19:02:44 -07002074 // if the system property isn't set, use the value for the apn type
2075 int ret = RESTORE_DEFAULT_NETWORK_DELAY;
2076
2077 if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
2078 (mNetConfigs[networkType] != null)) {
2079 ret = mNetConfigs[networkType].restoreTime;
2080 }
2081 return ret;
The Android Open Source Project28527d22009-03-03 19:31:44 -08002082 }
2083
2084 @Override
2085 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07002086 if (mContext.checkCallingOrSelfPermission(
2087 android.Manifest.permission.DUMP)
The Android Open Source Project28527d22009-03-03 19:31:44 -08002088 != PackageManager.PERMISSION_GRANTED) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07002089 pw.println("Permission Denial: can't dump ConnectivityService " +
2090 "from from pid=" + Binder.getCallingPid() + ", uid=" +
2091 Binder.getCallingUid());
The Android Open Source Project28527d22009-03-03 19:31:44 -08002092 return;
2093 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002094 pw.println();
2095 for (NetworkStateTracker nst : mNetTrackers) {
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002096 if (nst != null) {
2097 if (nst.getNetworkInfo().isConnected()) {
2098 pw.println("Active network: " + nst.getNetworkInfo().
2099 getTypeName());
2100 }
2101 pw.println(nst.getNetworkInfo());
2102 pw.println(nst);
2103 pw.println();
Robert Greenwalt2034b912009-08-12 16:08:25 -07002104 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002105 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002106
2107 pw.println("Network Requester Pids:");
2108 for (int net : mPriorityList) {
2109 String pidString = net + ": ";
2110 for (Object pid : mNetRequestersPids[net]) {
2111 pidString = pidString + pid.toString() + ", ";
2112 }
2113 pw.println(pidString);
2114 }
2115 pw.println();
2116
2117 pw.println("FeatureUsers:");
2118 for (Object requester : mFeatureUsers) {
2119 pw.println(requester.toString());
2120 }
2121 pw.println();
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002122
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002123 synchronized (this) {
2124 pw.println("NetworkTranstionWakeLock is currently " +
2125 (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held.");
2126 pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy);
2127 }
2128 pw.println();
2129
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002130 mTethering.dump(fd, pw, args);
Robert Greenwalt0e80be12010-09-20 14:35:25 -07002131
2132 if (mInetLog != null) {
2133 pw.println();
2134 pw.println("Inet condition reports:");
2135 for(int i = 0; i < mInetLog.size(); i++) {
2136 pw.println(mInetLog.get(i));
2137 }
2138 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002139 }
2140
Robert Greenwalt2034b912009-08-12 16:08:25 -07002141 // must be stateless - things change under us.
The Android Open Source Project28527d22009-03-03 19:31:44 -08002142 private class MyHandler extends Handler {
Wink Saville775aad62010-09-02 19:23:52 -07002143 public MyHandler(Looper looper) {
2144 super(looper);
2145 }
2146
The Android Open Source Project28527d22009-03-03 19:31:44 -08002147 @Override
2148 public void handleMessage(Message msg) {
2149 NetworkInfo info;
2150 switch (msg.what) {
2151 case NetworkStateTracker.EVENT_STATE_CHANGED:
2152 info = (NetworkInfo) msg.obj;
Robert Greenwalt12c44552009-12-07 11:33:18 -08002153 int type = info.getType();
2154 NetworkInfo.State state = info.getState();
Robert Greenwalt12c44552009-12-07 11:33:18 -08002155
Wink Savillee70c6f52010-12-03 12:01:38 -08002156 if (DBG) log("ConnectivityChange for " +
Robert Greenwalt0659da32009-07-16 17:21:39 -07002157 info.getTypeName() + ": " +
Robert Greenwalt12c44552009-12-07 11:33:18 -08002158 state + "/" + info.getDetailedState());
The Android Open Source Project28527d22009-03-03 19:31:44 -08002159
2160 // Connectivity state changed:
2161 // [31-13] Reserved for future use
Robert Greenwalt0659da32009-07-16 17:21:39 -07002162 // [12-9] Network subtype (for mobile network, as defined
2163 // by TelephonyManager)
2164 // [8-3] Detailed state ordinal (as defined by
2165 // NetworkInfo.DetailedState)
The Android Open Source Project28527d22009-03-03 19:31:44 -08002166 // [2-0] Network type (as defined by ConnectivityManager)
2167 int eventLogParam = (info.getType() & 0x7) |
2168 ((info.getDetailedState().ordinal() & 0x3f) << 3) |
2169 (info.getSubtype() << 9);
Doug Zongker2fc96232009-12-04 10:31:43 -08002170 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
Robert Greenwalt0659da32009-07-16 17:21:39 -07002171 eventLogParam);
2172
2173 if (info.getDetailedState() ==
2174 NetworkInfo.DetailedState.FAILED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002175 handleConnectionFailure(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08002176 } else if (state == NetworkInfo.State.DISCONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002177 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08002178 } else if (state == NetworkInfo.State.SUSPENDED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002179 // TODO: need to think this over.
Robert Greenwalt0659da32009-07-16 17:21:39 -07002180 // the logic here is, handle SUSPENDED the same as
2181 // DISCONNECTED. The only difference being we are
2182 // broadcasting an intent with NetworkInfo that's
2183 // suspended. This allows the applications an
2184 // opportunity to handle DISCONNECTED and SUSPENDED
2185 // differently, or not.
The Android Open Source Project28527d22009-03-03 19:31:44 -08002186 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08002187 } else if (state == NetworkInfo.State.CONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002188 handleConnect(info);
2189 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002190 break;
The Android Open Source Project28527d22009-03-03 19:31:44 -08002191 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002192 info = (NetworkInfo) msg.obj;
Kazuhiro Ondo07680062011-06-22 21:10:34 -05002193 // TODO: Temporary allowing network configuration
2194 // change not resetting sockets.
2195 // @see bug/4455071
2196 handleConnectivityChange(info.getType(), false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08002197 break;
Robert Greenwaltccb36f92010-09-24 14:32:21 -07002198 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002199 String causedBy = null;
2200 synchronized (ConnectivityService.this) {
2201 if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
2202 mNetTransitionWakeLock.isHeld()) {
2203 mNetTransitionWakeLock.release();
2204 causedBy = mNetTransitionWakeLockCausedBy;
2205 }
2206 }
2207 if (causedBy != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002208 log("NetTransition Wakelock for " + causedBy + " released by timeout");
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002209 }
Robert Greenwaltcf1a56c2010-09-09 14:05:10 -07002210 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002211 case EVENT_RESTORE_DEFAULT_NETWORK:
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07002212 FeatureUser u = (FeatureUser)msg.obj;
2213 u.expire();
Robert Greenwalt986c7412010-09-08 15:24:47 -07002214 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002215 case EVENT_INET_CONDITION_CHANGE:
2216 {
2217 int netType = msg.arg1;
2218 int condition = msg.arg2;
2219 handleInetConditionChange(netType, condition);
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002220 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002221 }
2222 case EVENT_INET_CONDITION_HOLD_END:
2223 {
2224 int netType = msg.arg1;
2225 int sequence = msg.arg2;
2226 handleInetConditionHoldEnd(netType, sequence);
Robert Greenwalt986c7412010-09-08 15:24:47 -07002227 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002228 }
2229 case EVENT_SET_NETWORK_PREFERENCE:
2230 {
2231 int preference = msg.arg1;
2232 handleSetNetworkPreference(preference);
2233 break;
2234 }
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002235 case EVENT_SET_MOBILE_DATA:
2236 {
2237 boolean enabled = (msg.arg1 == ENABLED);
2238 handleSetMobileData(enabled);
2239 break;
2240 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002241 case EVENT_APPLY_GLOBAL_HTTP_PROXY:
2242 {
2243 handleDeprecatedGlobalHttpProxy();
Robert Greenwalt34848c02011-03-25 13:09:25 -07002244 break;
2245 }
2246 case EVENT_SET_DEPENDENCY_MET:
2247 {
2248 boolean met = (msg.arg1 == ENABLED);
2249 handleSetDependencyMet(msg.arg2, met);
2250 break;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002251 }
Chia-chi Yehcc844502011-07-14 18:01:57 -07002252 case EVENT_RESTORE_DNS:
2253 {
2254 if (mActiveDefaultNetwork != -1) {
2255 handleDnsConfigurationChange(mActiveDefaultNetwork);
2256 }
2257 break;
2258 }
Wink Saville4f0de1e2011-08-04 15:01:58 -07002259 case EVENT_SEND_STICKY_BROADCAST_INTENT:
2260 {
2261 Intent intent = (Intent)msg.obj;
2262 log("EVENT_SEND_STICKY_BROADCAST_INTENT: sendStickyBroadcast intent=" + intent);
2263 sendStickyBroadcast(intent);
2264 break;
2265 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002266 }
2267 }
2268 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002269
2270 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002271 public int tether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002272 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002273
2274 if (isTetheringSupported()) {
2275 return mTethering.tether(iface);
2276 } else {
2277 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2278 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002279 }
2280
2281 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002282 public int untether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002283 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002284
2285 if (isTetheringSupported()) {
2286 return mTethering.untether(iface);
2287 } else {
2288 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2289 }
2290 }
2291
2292 // javadoc from interface
2293 public int getLastTetherError(String iface) {
2294 enforceTetherAccessPermission();
2295
2296 if (isTetheringSupported()) {
2297 return mTethering.getLastTetherError(iface);
2298 } else {
2299 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2300 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002301 }
2302
2303 // TODO - proper iface API for selection by property, inspection, etc
2304 public String[] getTetherableUsbRegexs() {
2305 enforceTetherAccessPermission();
2306 if (isTetheringSupported()) {
2307 return mTethering.getTetherableUsbRegexs();
2308 } else {
2309 return new String[0];
2310 }
2311 }
2312
2313 public String[] getTetherableWifiRegexs() {
2314 enforceTetherAccessPermission();
2315 if (isTetheringSupported()) {
2316 return mTethering.getTetherableWifiRegexs();
2317 } else {
2318 return new String[0];
2319 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002320 }
2321
Danica Chang96567052010-08-11 14:54:43 -07002322 public String[] getTetherableBluetoothRegexs() {
2323 enforceTetherAccessPermission();
2324 if (isTetheringSupported()) {
2325 return mTethering.getTetherableBluetoothRegexs();
2326 } else {
2327 return new String[0];
2328 }
2329 }
2330
Mike Lockwooded4a1742011-07-19 13:04:47 -07002331 public int setUsbTethering(boolean enable) {
2332 enforceTetherAccessPermission();
2333 if (isTetheringSupported()) {
2334 return mTethering.setUsbTethering(enable);
2335 } else {
2336 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2337 }
2338 }
2339
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002340 // TODO - move iface listing, queries, etc to new module
2341 // javadoc from interface
2342 public String[] getTetherableIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002343 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002344 return mTethering.getTetherableIfaces();
2345 }
2346
2347 public String[] getTetheredIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002348 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002349 return mTethering.getTetheredIfaces();
2350 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002351
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002352 public String[] getTetheringErroredIfaces() {
2353 enforceTetherAccessPermission();
2354 return mTethering.getErroredIfaces();
2355 }
2356
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002357 // if ro.tether.denied = true we default to no tethering
2358 // gservices could set the secure setting to 1 though to enable it on a build where it
2359 // had previously been turned off.
2360 public boolean isTetheringSupported() {
2361 enforceTetherAccessPermission();
2362 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
Robert Greenwaltf1b66e12010-02-25 12:29:30 -08002363 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(),
2364 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
2365 return tetherEnabledInSettings && mTetheringConfigValid;
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002366 }
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002367
2368 // An API NetworkStateTrackers can call when they lose their network.
2369 // This will automatically be cleared after X seconds or a network becomes CONNECTED,
2370 // whichever happens first. The timer is started by the first caller and not
2371 // restarted by subsequent callers.
2372 public void requestNetworkTransitionWakelock(String forWhom) {
2373 enforceConnectivityInternalPermission();
2374 synchronized (this) {
2375 if (mNetTransitionWakeLock.isHeld()) return;
2376 mNetTransitionWakeLockSerialNumber++;
2377 mNetTransitionWakeLock.acquire();
2378 mNetTransitionWakeLockCausedBy = forWhom;
2379 }
2380 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltccb36f92010-09-24 14:32:21 -07002381 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002382 mNetTransitionWakeLockSerialNumber, 0),
2383 mNetTransitionWakeLockTimeout);
2384 return;
2385 }
Robert Greenwalt24118e82010-09-09 13:15:32 -07002386
Robert Greenwalt986c7412010-09-08 15:24:47 -07002387 // 100 percent is full good, 0 is full bad.
2388 public void reportInetCondition(int networkType, int percentage) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002389 if (VDBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")");
Robert Greenwalt986c7412010-09-08 15:24:47 -07002390 mContext.enforceCallingOrSelfPermission(
2391 android.Manifest.permission.STATUS_BAR,
2392 "ConnectivityService");
2393
Robert Greenwalt0e80be12010-09-20 14:35:25 -07002394 if (DBG) {
2395 int pid = getCallingPid();
2396 int uid = getCallingUid();
2397 String s = pid + "(" + uid + ") reports inet is " +
2398 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
2399 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
2400 mInetLog.add(s);
2401 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
2402 mInetLog.remove(0);
2403 }
2404 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07002405 mHandler.sendMessage(mHandler.obtainMessage(
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002406 EVENT_INET_CONDITION_CHANGE, networkType, percentage));
2407 }
2408
2409 private void handleInetConditionChange(int netType, int condition) {
2410 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002411 log("Inet connectivity change, net=" +
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002412 netType + ", condition=" + condition +
2413 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
2414 }
2415 if (mActiveDefaultNetwork == -1) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002416 if (DBG) log("no active default network - aborting");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002417 return;
2418 }
2419 if (mActiveDefaultNetwork != netType) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002420 if (DBG) log("given net not default - aborting");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002421 return;
2422 }
2423 mDefaultInetCondition = condition;
2424 int delay;
2425 if (mInetConditionChangeInFlight == false) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002426 if (VDBG) log("starting a change hold");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002427 // setup a new hold to debounce this
2428 if (mDefaultInetCondition > 50) {
2429 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2430 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
2431 } else {
2432 delay = Settings.Secure.getInt(mContext.getContentResolver(),
2433 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
2434 }
2435 mInetConditionChangeInFlight = true;
2436 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
2437 mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
2438 } else {
2439 // we've set the new condition, when this hold ends that will get
2440 // picked up
Robert Greenwalt78f28112011-08-02 17:18:41 -07002441 if (VDBG) log("currently in hold - not setting new end evt");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002442 }
2443 }
2444
2445 private void handleInetConditionHoldEnd(int netType, int sequence) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002446 if (VDBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002447 log("Inet hold end, net=" + netType +
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002448 ", condition =" + mDefaultInetCondition +
2449 ", published condition =" + mDefaultInetConditionPublished);
2450 }
2451 mInetConditionChangeInFlight = false;
2452
2453 if (mActiveDefaultNetwork == -1) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002454 if (DBG) log("no active default network - aborting");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002455 return;
2456 }
2457 if (mDefaultConnectionSequence != sequence) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002458 if (DBG) log("event hold for obsolete network - aborting");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002459 return;
2460 }
Wink Saville4f0de1e2011-08-04 15:01:58 -07002461 // TODO: Figure out why this optimization sometimes causes a
2462 // change in mDefaultInetCondition to be missed and the
2463 // UI to not be updated.
2464 //if (mDefaultInetConditionPublished == mDefaultInetCondition) {
2465 // if (DBG) log("no change in condition - aborting");
2466 // return;
2467 //}
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002468 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
2469 if (networkInfo.isConnected() == false) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002470 if (DBG) log("default network not connected - aborting");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002471 return;
2472 }
2473 mDefaultInetConditionPublished = mDefaultInetCondition;
2474 sendInetConditionBroadcast(networkInfo);
2475 return;
Robert Greenwalt986c7412010-09-08 15:24:47 -07002476 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002477
2478 public synchronized ProxyProperties getProxy() {
2479 if (mGlobalProxy != null) return mGlobalProxy;
2480 if (mDefaultProxy != null) return mDefaultProxy;
2481 return null;
2482 }
2483
2484 public void setGlobalProxy(ProxyProperties proxyProperties) {
2485 enforceChangePermission();
2486 synchronized (mGlobalProxyLock) {
2487 if (proxyProperties == mGlobalProxy) return;
2488 if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
2489 if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
2490
2491 String host = "";
2492 int port = 0;
2493 String exclList = "";
2494 if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) {
2495 mGlobalProxy = new ProxyProperties(proxyProperties);
2496 host = mGlobalProxy.getHost();
2497 port = mGlobalProxy.getPort();
2498 exclList = mGlobalProxy.getExclusionList();
2499 } else {
2500 mGlobalProxy = null;
2501 }
2502 ContentResolver res = mContext.getContentResolver();
2503 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host);
2504 Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port);
Robert Greenwalt6f7c6092010-12-02 11:31:00 -08002505 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002506 exclList);
2507 }
2508
2509 if (mGlobalProxy == null) {
2510 proxyProperties = mDefaultProxy;
2511 }
2512 sendProxyBroadcast(proxyProperties);
2513 }
2514
Robert Greenwalt6f7c6092010-12-02 11:31:00 -08002515 private void loadGlobalProxy() {
2516 ContentResolver res = mContext.getContentResolver();
2517 String host = Settings.Secure.getString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST);
2518 int port = Settings.Secure.getInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, 0);
2519 String exclList = Settings.Secure.getString(res,
2520 Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
2521 if (!TextUtils.isEmpty(host)) {
2522 ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList);
2523 synchronized (mGlobalProxyLock) {
2524 mGlobalProxy = proxyProperties;
2525 }
2526 }
2527 }
2528
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002529 public ProxyProperties getGlobalProxy() {
2530 synchronized (mGlobalProxyLock) {
2531 return mGlobalProxy;
2532 }
2533 }
2534
2535 private void handleApplyDefaultProxy(int type) {
2536 // check if new default - push it out to all VM if so
2537 ProxyProperties proxy = mNetTrackers[type].getLinkProperties().getHttpProxy();
2538 synchronized (this) {
2539 if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
2540 if (mDefaultProxy == proxy) return;
Robert Greenwalt027f5052011-07-29 10:03:37 -07002541 if (proxy != null && !TextUtils.isEmpty(proxy.getHost())) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002542 mDefaultProxy = proxy;
2543 } else {
2544 mDefaultProxy = null;
2545 }
2546 }
Robert Greenwalt78f28112011-08-02 17:18:41 -07002547 if (VDBG) log("changing default proxy to " + proxy);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002548 if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return;
2549 if (mGlobalProxy != null) return;
2550 sendProxyBroadcast(proxy);
2551 }
2552
2553 private void handleDeprecatedGlobalHttpProxy() {
2554 String proxy = Settings.Secure.getString(mContext.getContentResolver(),
2555 Settings.Secure.HTTP_PROXY);
2556 if (!TextUtils.isEmpty(proxy)) {
2557 String data[] = proxy.split(":");
2558 String proxyHost = data[0];
2559 int proxyPort = 8080;
2560 if (data.length > 1) {
2561 try {
2562 proxyPort = Integer.parseInt(data[1]);
2563 } catch (NumberFormatException e) {
2564 return;
2565 }
2566 }
2567 ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
2568 setGlobalProxy(p);
2569 }
2570 }
2571
2572 private void sendProxyBroadcast(ProxyProperties proxy) {
Robert Greenwalt611291c2010-12-23 15:51:10 -08002573 if (proxy == null) proxy = new ProxyProperties("", 0, "");
Robert Greenwalt78f28112011-08-02 17:18:41 -07002574 if (DBG) log("sending Proxy Broadcast for " + proxy);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002575 Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
Stan Chesnutt1f2a2ac2011-01-06 11:00:19 -08002576 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
2577 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002578 intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
Robert Greenwaltd93dc8f2010-12-06 11:29:17 -08002579 mContext.sendStickyBroadcast(intent);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002580 }
2581
2582 private static class SettingsObserver extends ContentObserver {
2583 private int mWhat;
2584 private Handler mHandler;
2585 SettingsObserver(Handler handler, int what) {
2586 super(handler);
2587 mHandler = handler;
2588 mWhat = what;
2589 }
2590
2591 void observe(Context context) {
2592 ContentResolver resolver = context.getContentResolver();
2593 resolver.registerContentObserver(Settings.Secure.getUriFor(
2594 Settings.Secure.HTTP_PROXY), false, this);
2595 }
2596
2597 @Override
2598 public void onChange(boolean selfChange) {
2599 mHandler.obtainMessage(mWhat).sendToTarget();
2600 }
2601 }
Wink Savillee70c6f52010-12-03 12:01:38 -08002602
2603 private void log(String s) {
2604 Slog.d(TAG, s);
2605 }
2606
2607 private void loge(String s) {
2608 Slog.e(TAG, s);
2609 }
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002610
repo syncf5de5572011-07-29 23:55:49 -07002611 int convertFeatureToNetworkType(int networkType, String feature) {
2612 int usedNetworkType = networkType;
2613
2614 if(networkType == ConnectivityManager.TYPE_MOBILE) {
2615 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
2616 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
2617 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
2618 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
2619 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
2620 TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
2621 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
2622 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
2623 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
2624 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
2625 usedNetworkType = ConnectivityManager.TYPE_MOBILE_FOTA;
2626 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
2627 usedNetworkType = ConnectivityManager.TYPE_MOBILE_IMS;
2628 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
2629 usedNetworkType = ConnectivityManager.TYPE_MOBILE_CBS;
2630 } else {
2631 Slog.e(TAG, "Can't match any mobile netTracker!");
2632 }
2633 } else if (networkType == ConnectivityManager.TYPE_WIFI) {
2634 if (TextUtils.equals(feature, "p2p")) {
2635 usedNetworkType = ConnectivityManager.TYPE_WIFI_P2P;
2636 } else {
2637 Slog.e(TAG, "Can't match any wifi netTracker!");
2638 }
2639 } else {
2640 Slog.e(TAG, "Unexpected network type");
Wink Savillef6b76692011-02-24 17:58:51 -08002641 }
repo syncf5de5572011-07-29 23:55:49 -07002642 return usedNetworkType;
Wink Savillef6b76692011-02-24 17:58:51 -08002643 }
Jeff Sharkey921ebf22011-05-19 17:12:49 -07002644
2645 private static <T> T checkNotNull(T value, String message) {
2646 if (value == null) {
2647 throw new NullPointerException(message);
2648 }
2649 return value;
2650 }
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002651
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002652 /**
2653 * Protect a socket from VPN routing rules. This method is used by
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07002654 * VpnBuilder and not available in ConnectivityManager. Permissions
2655 * are checked in Vpn class.
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002656 * @hide
2657 */
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002658 @Override
Chia-chi Yeh9e4ff6e2011-07-14 16:19:19 -07002659 public boolean protectVpn(ParcelFileDescriptor socket) {
2660 try {
2661 int type = mActiveDefaultNetwork;
2662 if (ConnectivityManager.isNetworkTypeValid(type)) {
2663 mVpn.protect(socket, mNetTrackers[type].getLinkProperties().getInterfaceName());
2664 return true;
2665 }
2666 } catch (Exception e) {
2667 // ignore
2668 } finally {
2669 try {
2670 socket.close();
2671 } catch (Exception e) {
2672 // ignore
2673 }
2674 }
2675 return false;
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002676 }
2677
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002678 /**
2679 * Prepare for a VPN application. This method is used by VpnDialogs
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07002680 * and not available in ConnectivityManager. Permissions are checked
2681 * in Vpn class.
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002682 * @hide
2683 */
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002684 @Override
Chia-chi Yeh3e2e1da2011-07-03 16:52:38 -07002685 public boolean prepareVpn(String oldPackage, String newPackage) {
2686 return mVpn.prepare(oldPackage, newPackage);
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002687 }
2688
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002689 /**
2690 * Configure a TUN interface and return its file descriptor. Parameters
2691 * are encoded and opaque to this class. This method is used by VpnBuilder
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07002692 * and not available in ConnectivityManager. Permissions are checked in
2693 * Vpn class.
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002694 * @hide
2695 */
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002696 @Override
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07002697 public ParcelFileDescriptor establishVpn(VpnConfig config) {
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002698 return mVpn.establish(config);
2699 }
2700
Chia-chi Yeh7e026b32011-07-02 17:15:00 -07002701 /**
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07002702 * Start legacy VPN and return an intent to VpnDialogs. This method is
2703 * used by VpnSettings and not available in ConnectivityManager.
2704 * Permissions are checked in Vpn class.
Chia-chi Yeh7e026b32011-07-02 17:15:00 -07002705 * @hide
2706 */
2707 @Override
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07002708 public void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
2709 mVpn.startLegacyVpn(config, racoon, mtpd);
2710 }
2711
2712 /**
2713 * Return the information of the ongoing legacy VPN. This method is used
2714 * by VpnSettings and not available in ConnectivityManager. Permissions
2715 * are checked in Vpn class.
2716 * @hide
2717 */
2718 @Override
2719 public LegacyVpnInfo getLegacyVpnInfo() {
2720 return mVpn.getLegacyVpnInfo();
Chia-chi Yeh7e026b32011-07-02 17:15:00 -07002721 }
2722
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002723 /**
2724 * Callback for VPN subsystem. Currently VPN is not adapted to the service
2725 * through NetworkStateTracker since it works differently. For example, it
2726 * needs to override DNS servers but never takes the default routes. It
2727 * relies on another data network, and it could keep existing connections
2728 * alive after reconnecting, switching between networks, or even resuming
2729 * from deep sleep. Calls from applications should be done synchronously
2730 * to avoid race conditions. As these are all hidden APIs, refactoring can
2731 * be done whenever a better abstraction is developed.
2732 */
2733 public class VpnCallback {
2734
2735 private VpnCallback() {
2736 }
2737
Chia-chi Yehcc844502011-07-14 18:01:57 -07002738 public void override(List<String> dnsServers, List<String> searchDomains) {
2739 if (dnsServers == null) {
2740 restore();
2741 return;
2742 }
2743
2744 // Convert DNS servers into addresses.
2745 List<InetAddress> addresses = new ArrayList<InetAddress>();
2746 for (String address : dnsServers) {
2747 // Double check the addresses and remove invalid ones.
2748 try {
2749 addresses.add(InetAddress.parseNumericAddress(address));
2750 } catch (Exception e) {
2751 // ignore
2752 }
2753 }
2754 if (addresses.isEmpty()) {
2755 restore();
2756 return;
2757 }
2758
2759 // Concatenate search domains into a string.
2760 StringBuilder buffer = new StringBuilder();
2761 if (searchDomains != null) {
2762 for (String domain : searchDomains) {
2763 buffer.append(domain).append(' ');
2764 }
2765 }
2766 String domains = buffer.toString().trim();
2767
2768 // Apply DNS changes.
2769 boolean changed = false;
2770 synchronized (mDnsLock) {
Robert Greenwaltfce71862011-07-25 16:06:25 -07002771 changed = updateDns("VPN", "VPN", addresses, domains);
Chia-chi Yehcc844502011-07-14 18:01:57 -07002772 mDnsOverridden = true;
2773 }
2774 if (changed) {
2775 bumpDns();
2776 }
2777
2778 // TODO: temporarily remove http proxy?
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002779 }
2780
Chia-chi Yehcc844502011-07-14 18:01:57 -07002781 public void restore() {
2782 synchronized (mDnsLock) {
2783 if (!mDnsOverridden) {
2784 return;
2785 }
2786 mDnsOverridden = false;
2787 }
2788 mHandler.sendEmptyMessage(EVENT_RESTORE_DNS);
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07002789 }
2790 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002791}