blob: af9fdffe881220b368a5890be7a7b95129fa83f3 [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;
Haoyu Baib5da5752012-06-20 14:29:57 -070020import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
Jeff Sharkey971cd162011-08-29 16:02:57 -070021import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
22import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
Jeff Sharkey6b9021d2012-07-26 18:32:30 -070023import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
24import static android.net.ConnectivityManager.TYPE_DUMMY;
25import static android.net.ConnectivityManager.TYPE_ETHERNET;
26import static android.net.ConnectivityManager.TYPE_MOBILE;
27import static android.net.ConnectivityManager.TYPE_WIFI;
28import static android.net.ConnectivityManager.TYPE_WIMAX;
29import static android.net.ConnectivityManager.getNetworkTypeName;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070030import static android.net.ConnectivityManager.isNetworkTypeValid;
31import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -070032import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070033
Wink Saville32506bc2013-06-29 21:10:57 -070034import android.app.Notification;
35import android.app.NotificationManager;
36import android.app.PendingIntent;
Jaikumar Ganesh0db51a02010-12-21 22:31:44 -080037import android.bluetooth.BluetoothTetheringDataTracker;
Jeff Sharkeyebcc7972012-08-25 00:05:46 -070038import android.content.BroadcastReceiver;
The Android Open Source Project28527d22009-03-03 19:31:44 -080039import android.content.ContentResolver;
40import android.content.Context;
tk.mun093f55c2011-10-13 22:51:57 +090041import android.content.ContextWrapper;
The Android Open Source Project28527d22009-03-03 19:31:44 -080042import android.content.Intent;
Jeff Sharkeyebcc7972012-08-25 00:05:46 -070043import android.content.IntentFilter;
The Android Open Source Project28527d22009-03-03 19:31:44 -080044import android.content.pm.PackageManager;
Robert Greenwalt39d56012013-07-16 12:06:09 -070045import android.content.res.Configuration;
tk.mun093f55c2011-10-13 22:51:57 +090046import android.content.res.Resources;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -070047import android.database.ContentObserver;
Irfan Sheriff0ad0d132012-08-16 12:49:23 -070048import android.net.CaptivePortalTracker;
The Android Open Source Project28527d22009-03-03 19:31:44 -080049import android.net.ConnectivityManager;
Robert Greenwalteb123ac2010-12-06 13:56:24 -080050import android.net.DummyDataStateTracker;
Benoit Goby211b5692010-12-22 14:29:40 -080051import android.net.EthernetDataTracker;
The Android Open Source Project28527d22009-03-03 19:31:44 -080052import android.net.IConnectivityManager;
Haoyu Baib5da5752012-06-20 14:29:57 -070053import android.net.INetworkManagementEventObserver;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070054import android.net.INetworkPolicyListener;
55import android.net.INetworkPolicyManager;
Jeff Sharkeyb6188a12011-09-22 14:59:51 -070056import android.net.INetworkStatsService;
Wink Savilledc5d1ba2011-07-14 12:23:28 -070057import android.net.LinkAddress;
Jaikumar Ganesh0db51a02010-12-21 22:31:44 -080058import android.net.LinkProperties;
Wink Saville32506bc2013-06-29 21:10:57 -070059import android.net.Uri;
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -070060import android.net.LinkProperties.CompareResult;
The Android Open Source Project28527d22009-03-03 19:31:44 -080061import android.net.MobileDataStateTracker;
Robert Greenwalt34848c02011-03-25 13:09:25 -070062import android.net.NetworkConfig;
The Android Open Source Project28527d22009-03-03 19:31:44 -080063import android.net.NetworkInfo;
Jeff Sharkey921ebf22011-05-19 17:12:49 -070064import android.net.NetworkInfo.DetailedState;
Wink Saville32506bc2013-06-29 21:10:57 -070065import android.net.NetworkInfo.State;
Jeff Sharkey66fa9682011-08-02 17:22:34 -070066import android.net.NetworkQuotaInfo;
Jeff Sharkey21062e72011-05-28 20:56:34 -070067import android.net.NetworkState;
The Android Open Source Project28527d22009-03-03 19:31:44 -080068import android.net.NetworkStateTracker;
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -070069import android.net.NetworkUtils;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -070070import android.net.Proxy;
71import android.net.ProxyProperties;
Robert Greenwalt5a901292011-04-28 14:28:50 -070072import android.net.RouteInfo;
The Android Open Source Project28527d22009-03-03 19:31:44 -080073import android.net.wifi.WifiStateTracker;
tk.mun093f55c2011-10-13 22:51:57 +090074import android.net.wimax.WimaxManagerConstants;
Wink Saville32506bc2013-06-29 21:10:57 -070075import android.os.AsyncTask;
The Android Open Source Project28527d22009-03-03 19:31:44 -080076import android.os.Binder;
Mike Lockwood0d5916c2011-05-28 13:24:04 -040077import android.os.FileUtils;
The Android Open Source Project28527d22009-03-03 19:31:44 -080078import android.os.Handler;
Wink Saville775aad62010-09-02 19:23:52 -070079import android.os.HandlerThread;
Robert Greenwalt2034b912009-08-12 16:08:25 -070080import android.os.IBinder;
Chia-chi Yeh4df51322011-05-11 16:35:13 -070081import android.os.INetworkManagementService;
The Android Open Source Project28527d22009-03-03 19:31:44 -080082import android.os.Looper;
83import android.os.Message;
Robert Greenwalt15a41532012-08-21 19:27:00 -070084import android.os.Messenger;
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -070085import android.os.ParcelFileDescriptor;
Robert Greenwalt93dc1042010-06-15 12:19:37 -070086import android.os.PowerManager;
Jeff Sharkey69fc5f82012-09-06 17:54:29 -070087import android.os.Process;
Robert Greenwalt2034b912009-08-12 16:08:25 -070088import android.os.RemoteException;
Wink Saville32506bc2013-06-29 21:10:57 -070089import android.os.ResultReceiver;
The Android Open Source Project28527d22009-03-03 19:31:44 -080090import android.os.ServiceManager;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -070091import android.os.SystemClock;
The Android Open Source Project28527d22009-03-03 19:31:44 -080092import android.os.SystemProperties;
Dianne Hackborn22986892012-08-29 18:32:08 -070093import android.os.UserHandle;
The Android Open Source Project28527d22009-03-03 19:31:44 -080094import android.provider.Settings;
Jeff Sharkeyebcc7972012-08-25 00:05:46 -070095import android.security.Credentials;
Jeff Sharkey64d8b3b2012-08-24 11:17:25 -070096import android.security.KeyStore;
Wink Saville32506bc2013-06-29 21:10:57 -070097import android.telephony.TelephonyManager;
Robert Greenwalt2034b912009-08-12 16:08:25 -070098import android.text.TextUtils;
Joe Onoratoc2386bb2010-02-26 18:56:32 -080099import android.util.Slog;
Chad Brubakerb7652cd2013-06-14 11:16:51 -0700100import android.util.SparseArray;
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700101import android.util.SparseIntArray;
Robert Greenwalt39d56012013-07-16 12:06:09 -0700102import android.util.Xml;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800103
Wink Saville32506bc2013-06-29 21:10:57 -0700104import com.android.internal.R;
Chia-chi Yehbded3eb2011-07-04 03:23:12 -0700105import com.android.internal.net.LegacyVpnInfo;
Chia-chi Yeh75cacd52011-06-15 17:07:27 -0700106import com.android.internal.net.VpnConfig;
Jeff Sharkey64d8b3b2012-08-24 11:17:25 -0700107import com.android.internal.net.VpnProfile;
Wink Saville32506bc2013-06-29 21:10:57 -0700108import com.android.internal.telephony.DctConstants;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700109import com.android.internal.telephony.Phone;
Wink Saville64e3f782012-07-10 12:37:54 -0700110import com.android.internal.telephony.PhoneConstants;
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -0700111import com.android.internal.util.IndentingPrintWriter;
Robert Greenwalt39d56012013-07-16 12:06:09 -0700112import com.android.internal.util.XmlUtils;
Jeff Sharkeyaac2c502011-10-04 16:54:49 -0700113import com.android.server.am.BatteryStatsService;
John Spurlock1f5cec72013-06-24 14:20:23 -0400114import com.android.server.connectivity.DataConnectionStats;
Lorenzo Colitti7a9d7972013-03-15 04:22:37 +0900115import com.android.server.connectivity.Nat464Xlat;
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800116import com.android.server.connectivity.Tethering;
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -0700117import com.android.server.connectivity.Vpn;
Jeff Sharkey60e6c1a2012-08-05 14:29:23 -0700118import com.android.server.net.BaseNetworkObserver;
Jeff Sharkeyebcc7972012-08-25 00:05:46 -0700119import com.android.server.net.LockdownVpnTracker;
Jeff Sharkey21062e72011-05-28 20:56:34 -0700120import com.google.android.collect.Lists;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700121import com.google.android.collect.Sets;
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700122
Chad Brubakerb7652cd2013-06-14 11:16:51 -0700123import com.android.internal.annotations.GuardedBy;
124
tk.mun093f55c2011-10-13 22:51:57 +0900125import dalvik.system.DexClassLoader;
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700126
Robert Greenwalt39d56012013-07-16 12:06:09 -0700127import org.xmlpull.v1.XmlPullParser;
128import org.xmlpull.v1.XmlPullParserException;
129
130import java.io.File;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800131import java.io.FileDescriptor;
Robert Greenwalt39d56012013-07-16 12:06:09 -0700132import java.io.FileNotFoundException;
133import java.io.FileReader;
Irfan Sheriff7f132d92010-06-09 15:39:36 -0700134import java.io.IOException;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800135import java.io.PrintWriter;
tk.mun093f55c2011-10-13 22:51:57 +0900136import java.lang.reflect.Constructor;
Wink Saville32506bc2013-06-29 21:10:57 -0700137import java.net.HttpURLConnection;
Wink Savilledc5d1ba2011-07-14 12:23:28 -0700138import java.net.Inet4Address;
Wink Saville051a6642011-07-13 13:44:13 -0700139import java.net.Inet6Address;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700140import java.net.InetAddress;
Wink Saville32506bc2013-06-29 21:10:57 -0700141import java.net.URL;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700142import java.net.UnknownHostException;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700143import java.util.ArrayList;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700144import java.util.Arrays;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700145import java.util.Collection;
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700146import java.util.GregorianCalendar;
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700147import java.util.HashSet;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700148import java.util.List;
Wink Saville32506bc2013-06-29 21:10:57 -0700149import java.util.Random;
150import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800151
152/**
153 * @hide
154 */
155public class ConnectivityService extends IConnectivityManager.Stub {
Jeff Sharkey366e0b72012-08-04 15:24:58 -0700156 private static final String TAG = "ConnectivityService";
The Android Open Source Project28527d22009-03-03 19:31:44 -0800157
Robert Greenwalt063dc7d2010-10-05 19:12:26 -0700158 private static final boolean DBG = true;
Wink Savillea7d56572011-09-21 11:05:43 -0700159 private static final boolean VDBG = false;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800160
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700161 private static final boolean LOGD_RULES = false;
162
Jeff Sharkey366e0b72012-08-04 15:24:58 -0700163 // TODO: create better separation between radio types and network types
164
Robert Greenwalt2034b912009-08-12 16:08:25 -0700165 // how long to wait before switching back to a radio's default network
166 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
167 // system property that can override the above value
168 private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
169 "android.telephony.apn-restore";
170
Wink Saville32506bc2013-06-29 21:10:57 -0700171 // Default value if FAIL_FAST_TIME_MS is not set
172 private static final int DEFAULT_FAIL_FAST_TIME_MS = 1 * 60 * 1000;
173 // system property that can override DEFAULT_FAIL_FAST_TIME_MS
174 private static final String FAIL_FAST_TIME_MS =
175 "persist.radio.fail_fast_time_ms";
176
Robert Greenwaltbd492212011-05-06 17:10:53 -0700177 // used in recursive route setting to add gateways for the host for which
178 // a host route was requested.
179 private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10;
180
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800181 private Tethering mTethering;
182
Jeff Sharkeyebcc7972012-08-25 00:05:46 -0700183 private KeyStore mKeyStore;
Jeff Sharkey64d8b3b2012-08-24 11:17:25 -0700184
Chad Brubakerb7652cd2013-06-14 11:16:51 -0700185 @GuardedBy("mVpns")
186 private final SparseArray<Vpn> mVpns = new SparseArray<Vpn>();
Jeff Sharkey366e0b72012-08-04 15:24:58 -0700187 private VpnCallback mVpnCallback = new VpnCallback();
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -0700188
Jeff Sharkeyebcc7972012-08-25 00:05:46 -0700189 private boolean mLockdownEnabled;
190 private LockdownVpnTracker mLockdownTracker;
191
Lorenzo Colitti7a9d7972013-03-15 04:22:37 +0900192 private Nat464Xlat mClat;
193
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700194 /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
195 private Object mRulesLock = new Object();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700196 /** Currently active network rules by UID. */
197 private SparseIntArray mUidRules = new SparseIntArray();
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700198 /** Set of ifaces that are costly. */
199 private HashSet<String> mMeteredIfaces = Sets.newHashSet();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700200
The Android Open Source Project28527d22009-03-03 19:31:44 -0800201 /**
202 * Sometimes we want to refer to the individual network state
203 * trackers separately, and sometimes we just want to treat them
204 * abstractly.
205 */
206 private NetworkStateTracker mNetTrackers[];
Robert Greenwalt2034b912009-08-12 16:08:25 -0700207
Irfan Sheriff0ad0d132012-08-16 12:49:23 -0700208 /* Handles captive portal check on a network */
209 private CaptivePortalTracker mCaptivePortalTracker;
210
Robert Greenwalt2034b912009-08-12 16:08:25 -0700211 /**
Wink Saville051a6642011-07-13 13:44:13 -0700212 * The link properties that define the current links
213 */
214 private LinkProperties mCurrentLinkProperties[];
215
216 /**
Robert Greenwalt2034b912009-08-12 16:08:25 -0700217 * A per Net list of the PID's that requested access to the net
218 * used both as a refcount and for per-PID DNS selection
219 */
Mattias Falkd697aa22011-08-23 14:15:13 +0200220 private List<Integer> mNetRequestersPids[];
Robert Greenwalt2034b912009-08-12 16:08:25 -0700221
Robert Greenwalt2034b912009-08-12 16:08:25 -0700222 // priority order of the nettrackers
223 // (excluding dynamically set mNetworkPreference)
224 // TODO - move mNetworkTypePreference into this
225 private int[] mPriorityList;
226
The Android Open Source Project28527d22009-03-03 19:31:44 -0800227 private Context mContext;
228 private int mNetworkPreference;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700229 private int mActiveDefaultNetwork = -1;
Robert Greenwalt986c7412010-09-08 15:24:47 -0700230 // 0 is full bad, 100 is full good
Wink Saville151eaa62013-01-31 00:30:13 +0000231 private int mDefaultInetCondition = 0;
Robert Greenwalt986c7412010-09-08 15:24:47 -0700232 private int mDefaultInetConditionPublished = 0;
233 private boolean mInetConditionChangeInFlight = false;
234 private int mDefaultConnectionSequence = 0;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800235
Chia-chi Yehcc844502011-07-14 18:01:57 -0700236 private Object mDnsLock = new Object();
Robert Greenwalte41e3b32013-02-11 15:25:10 -0800237 private int mNumDnsEntries;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800238
239 private boolean mTestMode;
Joe Onorato56023ad2010-09-01 21:18:22 -0700240 private static ConnectivityService sServiceInstance;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800241
Robert Greenwalt355205c2011-05-10 15:05:02 -0700242 private INetworkManagementService mNetd;
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700243 private INetworkPolicyManager mPolicyManager;
Robert Greenwalt355205c2011-05-10 15:05:02 -0700244
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700245 private static final int ENABLED = 1;
246 private static final int DISABLED = 0;
247
Robert Greenwalt49c75d32011-11-02 14:37:19 -0700248 private static final boolean ADD = true;
249 private static final boolean REMOVE = false;
250
251 private static final boolean TO_DEFAULT_TABLE = true;
252 private static final boolean TO_SECONDARY_TABLE = false;
253
Chad Brubaker49db4222013-07-15 16:34:04 -0700254 private static final boolean EXEMPT = true;
255 private static final boolean UNEXEMPT = false;
256
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700257 /**
258 * used internally as a delayed event to make us switch back to the
259 * default network
260 */
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700261 private static final int EVENT_RESTORE_DEFAULT_NETWORK = 1;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700262
263 /**
264 * used internally to change our mobile data enabled flag
265 */
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700266 private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 2;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700267
268 /**
269 * used internally to change our network preference setting
270 * arg1 = networkType to prefer
271 */
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700272 private static final int EVENT_SET_NETWORK_PREFERENCE = 3;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700273
274 /**
275 * used internally to synchronize inet condition reports
276 * arg1 = networkType
277 * arg2 = condition (0 bad, 100 good)
278 */
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700279 private static final int EVENT_INET_CONDITION_CHANGE = 4;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700280
281 /**
282 * used internally to mark the end of inet condition hold periods
283 * arg1 = networkType
284 */
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700285 private static final int EVENT_INET_CONDITION_HOLD_END = 5;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700286
287 /**
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700288 * used internally to set enable/disable cellular data
289 * arg1 = ENBALED or DISABLED
290 */
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700291 private static final int EVENT_SET_MOBILE_DATA = 7;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700292
Robert Greenwaltccb36f92010-09-24 14:32:21 -0700293 /**
294 * used internally to clear a wakelock when transitioning
295 * from one net to another
296 */
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700297 private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 8;
Robert Greenwaltccb36f92010-09-24 14:32:21 -0700298
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700299 /**
300 * used internally to reload global proxy settings
301 */
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700302 private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700303
Robert Greenwalt34848c02011-03-25 13:09:25 -0700304 /**
305 * used internally to set external dependency met/unmet
306 * arg1 = ENABLED (met) or DISABLED (unmet)
307 * arg2 = NetworkType
308 */
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700309 private static final int EVENT_SET_DEPENDENCY_MET = 10;
Robert Greenwalt34848c02011-03-25 13:09:25 -0700310
Chia-chi Yehcc844502011-07-14 18:01:57 -0700311 /**
Wink Saville4f0de1e2011-08-04 15:01:58 -0700312 * used internally to send a sticky broadcast delayed.
313 */
Chad Brubaker5fdc1462013-07-23 17:44:41 -0700314 private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = 11;
Wink Saville4f0de1e2011-08-04 15:01:58 -0700315
Jeff Sharkey805662d2011-08-19 02:24:24 -0700316 /**
317 * Used internally to
318 * {@link NetworkStateTracker#setPolicyDataEnable(boolean)}.
319 */
Chad Brubaker5fdc1462013-07-23 17:44:41 -0700320 private static final int EVENT_SET_POLICY_DATA_ENABLE = 12;
Jeff Sharkey805662d2011-08-19 02:24:24 -0700321
Chad Brubaker5fdc1462013-07-23 17:44:41 -0700322 private static final int EVENT_VPN_STATE_CHANGED = 13;
Jeff Sharkeyebcc7972012-08-25 00:05:46 -0700323
Wink Saville32506bc2013-06-29 21:10:57 -0700324 /**
325 * Used internally to disable fail fast of mobile data
326 */
Chad Brubaker5fdc1462013-07-23 17:44:41 -0700327 private static final int EVENT_ENABLE_FAIL_FAST_MOBILE_DATA = 14;
Wink Saville32506bc2013-06-29 21:10:57 -0700328
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700329 /** Handler used for internal events. */
330 private InternalHandler mHandler;
331 /** Handler used for incoming {@link NetworkStateTracker} events. */
332 private NetworkStateTrackerHandler mTrackerHandler;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700333
334 // list of DeathRecipients used to make sure features are turned off when
335 // a process dies
Kazuhiro Ondocae18f12011-07-19 11:23:37 -0500336 private List<FeatureUser> mFeatureUsers;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700337
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400338 private boolean mSystemReady;
Dianne Hackborna417ff82009-12-08 19:45:14 -0800339 private Intent mInitialBroadcast;
Mike Lockwoodfde2b762009-08-14 14:18:49 -0400340
Robert Greenwalt93dc1042010-06-15 12:19:37 -0700341 private PowerManager.WakeLock mNetTransitionWakeLock;
342 private String mNetTransitionWakeLockCausedBy = "";
343 private int mNetTransitionWakeLockSerialNumber;
344 private int mNetTransitionWakeLockTimeout;
345
Robert Greenwalt94daa182010-09-01 11:34:05 -0700346 private InetAddress mDefaultDns;
347
Chad Brubaker49db4222013-07-15 16:34:04 -0700348 // Lock for protecting access to mAddedRoutes and mExemptAddresses
349 private final Object mRoutesLock = new Object();
350
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700351 // this collection is used to refcount the added routes - if there are none left
352 // it's time to remove the route from the route table
Chad Brubaker49db4222013-07-15 16:34:04 -0700353 @GuardedBy("mRoutesLock")
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700354 private Collection<RouteInfo> mAddedRoutes = new ArrayList<RouteInfo>();
355
Chad Brubaker49db4222013-07-15 16:34:04 -0700356 // this collection corresponds to the entries of mAddedRoutes that have routing exemptions
357 // used to handle cleanup of exempt rules
358 @GuardedBy("mRoutesLock")
359 private Collection<LinkAddress> mExemptAddresses = new ArrayList<LinkAddress>();
360
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700361 // used in DBG mode to track inet condition reports
362 private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
363 private ArrayList mInetLog;
364
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700365 // track the current default http proxy - tell the world if we get a new one (real change)
366 private ProxyProperties mDefaultProxy = null;
Robert Greenwaltf9661d32013-04-05 17:14:19 -0700367 private Object mProxyLock = new Object();
Chia-chi Yeh763a11c2011-10-03 15:34:04 -0700368 private boolean mDefaultProxyDisabled = false;
369
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700370 // track the global proxy.
371 private ProxyProperties mGlobalProxy = null;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700372
373 private SettingsObserver mSettingsObserver;
374
Robert Greenwalt34848c02011-03-25 13:09:25 -0700375 NetworkConfig[] mNetConfigs;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700376 int mNetworksDefined;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700377
Robert Greenwalt12c44552009-12-07 11:33:18 -0800378 private static class RadioAttributes {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700379 public int mSimultaneity;
380 public int mType;
381 public RadioAttributes(String init) {
382 String fragments[] = init.split(",");
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700383 mType = Integer.parseInt(fragments[0]);
384 mSimultaneity = Integer.parseInt(fragments[1]);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700385 }
386 }
387 RadioAttributes[] mRadioAttributes;
388
Robert Greenwalt6cac0742011-06-21 17:26:14 -0700389 // the set of network types that can only be enabled by system/sig apps
390 List mProtectedNetworks;
391
John Spurlock1f5cec72013-06-24 14:20:23 -0400392 private DataConnectionStats mDataConnectionStats;
Wink Saville32506bc2013-06-29 21:10:57 -0700393 private AtomicInteger mEnableFailFastMobileDataTag = new AtomicInteger(0);
394
395 TelephonyManager mTelephonyManager;
John Spurlock1f5cec72013-06-24 14:20:23 -0400396
Wink Savillef0e9c7f2013-07-16 17:16:37 -0700397 // We only want one checkMobileProvisioning after booting.
398 volatile boolean mFirstProvisioningCheckStarted = false;
399
Jeff Sharkeyb6188a12011-09-22 14:59:51 -0700400 public ConnectivityService(Context context, INetworkManagementService netd,
401 INetworkStatsService statsService, INetworkPolicyManager policyManager) {
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700402 // Currently, omitting a NetworkFactory will create one internally
403 // TODO: create here when we have cleaner WiMAX support
404 this(context, netd, statsService, policyManager, null);
405 }
406
Jeff Sharkey366e0b72012-08-04 15:24:58 -0700407 public ConnectivityService(Context context, INetworkManagementService netManager,
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700408 INetworkStatsService statsService, INetworkPolicyManager policyManager,
409 NetworkFactory netFactory) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800410 if (DBG) log("ConnectivityService starting up");
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800411
Wink Saville775aad62010-09-02 19:23:52 -0700412 HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
413 handlerThread.start();
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700414 mHandler = new InternalHandler(handlerThread.getLooper());
415 mTrackerHandler = new NetworkStateTrackerHandler(handlerThread.getLooper());
Wink Saville775aad62010-09-02 19:23:52 -0700416
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700417 if (netFactory == null) {
418 netFactory = new DefaultNetworkFactory(context, mTrackerHandler);
419 }
420
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800421 // setup our unique device name
Robert Greenwalt82cde132010-12-06 09:30:17 -0800422 if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
423 String id = Settings.Secure.getString(context.getContentResolver(),
424 Settings.Secure.ANDROID_ID);
425 if (id != null && id.length() > 0) {
Irfan Sheriff4aa0b2e2011-09-20 15:17:07 -0700426 String name = new String("android-").concat(id);
Robert Greenwalt82cde132010-12-06 09:30:17 -0800427 SystemProperties.set("net.hostname", name);
428 }
Robert Greenwaltd48f8ee2010-01-14 17:47:58 -0800429 }
430
Robert Greenwalt94daa182010-09-01 11:34:05 -0700431 // read our default dns server ip
Jeff Sharkey8c870452012-09-26 22:03:49 -0700432 String dns = Settings.Global.getString(context.getContentResolver(),
433 Settings.Global.DEFAULT_DNS_SERVER);
Robert Greenwalt94daa182010-09-01 11:34:05 -0700434 if (dns == null || dns.length() == 0) {
435 dns = context.getResources().getString(
436 com.android.internal.R.string.config_default_dns_server);
437 }
438 try {
Robert Greenwalt35e34d12011-02-22 16:00:42 -0800439 mDefaultDns = NetworkUtils.numericToInetAddress(dns);
440 } catch (IllegalArgumentException e) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800441 loge("Error setting defaultDns using " + dns);
Robert Greenwalt94daa182010-09-01 11:34:05 -0700442 }
443
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700444 mContext = checkNotNull(context, "missing Context");
Jeff Sharkey366e0b72012-08-04 15:24:58 -0700445 mNetd = checkNotNull(netManager, "missing INetworkManagementService");
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700446 mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
Jeff Sharkey64d8b3b2012-08-24 11:17:25 -0700447 mKeyStore = KeyStore.getInstance();
Wink Saville32506bc2013-06-29 21:10:57 -0700448 mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
Robert Greenwalt93dc1042010-06-15 12:19:37 -0700449
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700450 try {
451 mPolicyManager.registerListener(mPolicyListener);
452 } catch (RemoteException e) {
453 // ouch, no rules updates means some processes may never get network
Robert Greenwalt78f28112011-08-02 17:18:41 -0700454 loge("unable to register INetworkPolicyListener" + e.toString());
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700455 }
456
457 final PowerManager powerManager = (PowerManager) context.getSystemService(
458 Context.POWER_SERVICE);
Robert Greenwalt93dc1042010-06-15 12:19:37 -0700459 mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
460 mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
461 com.android.internal.R.integer.config_networkTransitionTimeout);
462
Robert Greenwalt2034b912009-08-12 16:08:25 -0700463 mNetTrackers = new NetworkStateTracker[
464 ConnectivityManager.MAX_NETWORK_TYPE+1];
Wink Saville051a6642011-07-13 13:44:13 -0700465 mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwalt0659da32009-07-16 17:21:39 -0700466
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700467 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
Robert Greenwalt34848c02011-03-25 13:09:25 -0700468 mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700469
Robert Greenwalt2034b912009-08-12 16:08:25 -0700470 // Load device network attributes from resources
Robert Greenwalt2034b912009-08-12 16:08:25 -0700471 String[] raStrings = context.getResources().getStringArray(
472 com.android.internal.R.array.radioAttributes);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700473 for (String raString : raStrings) {
474 RadioAttributes r = new RadioAttributes(raString);
Wink Saville512c2202013-07-29 15:00:57 -0700475 if (VDBG) log("raString=" + raString + " r=" + r);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700476 if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800477 loge("Error in radioAttributes - ignoring attempt to define type " + r.mType);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700478 continue;
479 }
480 if (mRadioAttributes[r.mType] != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800481 loge("Error in radioAttributes - ignoring attempt to redefine type " +
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700482 r.mType);
483 continue;
484 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700485 mRadioAttributes[r.mType] = r;
486 }
487
Wink Saville00fe5092013-04-23 14:26:51 -0700488 // TODO: What is the "correct" way to do determine if this is a wifi only device?
489 boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false);
490 log("wifiOnly=" + wifiOnly);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700491 String[] naStrings = context.getResources().getStringArray(
492 com.android.internal.R.array.networkAttributes);
493 for (String naString : naStrings) {
494 try {
Robert Greenwalt34848c02011-03-25 13:09:25 -0700495 NetworkConfig n = new NetworkConfig(naString);
Wink Saville512c2202013-07-29 15:00:57 -0700496 if (VDBG) log("naString=" + naString + " config=" + n);
Wink Savillef2a62832011-04-07 14:23:45 -0700497 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800498 loge("Error in networkAttributes - ignoring attempt to define type " +
Wink Savillef2a62832011-04-07 14:23:45 -0700499 n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700500 continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -0700501 }
Wink Saville00fe5092013-04-23 14:26:51 -0700502 if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) {
503 log("networkAttributes - ignoring mobile as this dev is wifiOnly " +
504 n.type);
505 continue;
506 }
Wink Savillef2a62832011-04-07 14:23:45 -0700507 if (mNetConfigs[n.type] != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800508 loge("Error in networkAttributes - ignoring attempt to redefine type " +
Wink Savillef2a62832011-04-07 14:23:45 -0700509 n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700510 continue;
511 }
Wink Savillef2a62832011-04-07 14:23:45 -0700512 if (mRadioAttributes[n.radio] == null) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800513 loge("Error in networkAttributes - ignoring attempt to use undefined " +
Wink Savillef2a62832011-04-07 14:23:45 -0700514 "radio " + n.radio + " in network type " + n.type);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700515 continue;
516 }
Wink Savillef2a62832011-04-07 14:23:45 -0700517 mNetConfigs[n.type] = n;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700518 mNetworksDefined++;
519 } catch(Exception e) {
520 // ignore it - leave the entry null
Robert Greenwalt2034b912009-08-12 16:08:25 -0700521 }
522 }
Wink Saville512c2202013-07-29 15:00:57 -0700523 if (VDBG) log("mNetworksDefined=" + mNetworksDefined);
Robert Greenwalt2034b912009-08-12 16:08:25 -0700524
Robert Greenwalt6cac0742011-06-21 17:26:14 -0700525 mProtectedNetworks = new ArrayList<Integer>();
526 int[] protectedNetworks = context.getResources().getIntArray(
527 com.android.internal.R.array.config_protectedNetworks);
528 for (int p : protectedNetworks) {
529 if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
530 mProtectedNetworks.add(p);
531 } else {
532 if (DBG) loge("Ignoring protectedNetwork " + p);
533 }
534 }
535
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700536 // high priority first
537 mPriorityList = new int[mNetworksDefined];
538 {
539 int insertionPoint = mNetworksDefined-1;
540 int currentLowest = 0;
541 int nextLowest = 0;
542 while (insertionPoint > -1) {
Robert Greenwalt34848c02011-03-25 13:09:25 -0700543 for (NetworkConfig na : mNetConfigs) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700544 if (na == null) continue;
Wink Savillef2a62832011-04-07 14:23:45 -0700545 if (na.priority < currentLowest) continue;
546 if (na.priority > currentLowest) {
547 if (na.priority < nextLowest || nextLowest == 0) {
548 nextLowest = na.priority;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700549 }
550 continue;
551 }
Wink Savillef2a62832011-04-07 14:23:45 -0700552 mPriorityList[insertionPoint--] = na.type;
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700553 }
554 currentLowest = nextLowest;
555 nextLowest = 0;
556 }
557 }
558
Jianzheng Zhou028d2032012-11-16 13:45:20 +0800559 // Update mNetworkPreference according to user mannually first then overlay config.xml
560 mNetworkPreference = getPersistedNetworkPreference();
561 if (mNetworkPreference == -1) {
562 for (int n : mPriorityList) {
563 if (mNetConfigs[n].isDefault() && ConnectivityManager.isNetworkTypeValid(n)) {
564 mNetworkPreference = n;
565 break;
566 }
567 }
568 if (mNetworkPreference == -1) {
569 throw new IllegalStateException(
570 "You should set at least one default Network in config.xml!");
571 }
572 }
573
Mattias Falkd697aa22011-08-23 14:15:13 +0200574 mNetRequestersPids =
575 (List<Integer> [])new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700576 for (int i : mPriorityList) {
Mattias Falkd697aa22011-08-23 14:15:13 +0200577 mNetRequestersPids[i] = new ArrayList<Integer>();
Robert Greenwalt2034b912009-08-12 16:08:25 -0700578 }
579
Kazuhiro Ondocae18f12011-07-19 11:23:37 -0500580 mFeatureUsers = new ArrayList<FeatureUser>();
Robert Greenwalt2034b912009-08-12 16:08:25 -0700581
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700582 mTestMode = SystemProperties.get("cm.test.mode").equals("true")
583 && SystemProperties.get("ro.build.type").equals("eng");
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700584
585 // Create and start trackers for hard-coded networks
586 for (int targetNetworkType : mPriorityList) {
587 final NetworkConfig config = mNetConfigs[targetNetworkType];
588 final NetworkStateTracker tracker;
589 try {
590 tracker = netFactory.createTracker(targetNetworkType, config);
591 mNetTrackers[targetNetworkType] = tracker;
592 } catch (IllegalArgumentException e) {
593 Slog.e(TAG, "Problem creating " + getNetworkTypeName(targetNetworkType)
594 + " tracker: " + e);
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700595 continue;
596 }
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700597
598 tracker.startMonitoring(context, mTrackerHandler);
599 if (config.isDefault()) {
600 tracker.reconnect();
Robert Greenwaltcafd8582011-11-10 16:55:20 -0800601 }
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700602 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -0800603
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700604 mTethering = new Tethering(mContext, mNetd, statsService, this, mHandler.getLooper());
Robert Greenwaltf1b66e12010-02-25 12:29:30 -0800605
Robert Greenwaltf68291a2013-07-19 14:30:49 -0700606 //set up the listener for user state for creating user VPNs
Chad Brubakerb7652cd2013-06-14 11:16:51 -0700607 IntentFilter intentFilter = new IntentFilter();
608 intentFilter.addAction(Intent.ACTION_USER_STARTING);
609 intentFilter.addAction(Intent.ACTION_USER_STOPPING);
610 mContext.registerReceiverAsUser(
611 mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
Lorenzo Colitti7a9d7972013-03-15 04:22:37 +0900612 mClat = new Nat464Xlat(mContext, mNetd, this, mTrackerHandler);
613
Chia-chi Yehf3204aa2011-05-23 15:08:29 -0700614 try {
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700615 mNetd.registerObserver(mTethering);
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700616 mNetd.registerObserver(mDataActivityObserver);
Lorenzo Colitti7a9d7972013-03-15 04:22:37 +0900617 mNetd.registerObserver(mClat);
Chia-chi Yehf3204aa2011-05-23 15:08:29 -0700618 } catch (RemoteException e) {
619 loge("Error registering observer :" + e);
620 }
621
Robert Greenwalt0e80be12010-09-20 14:35:25 -0700622 if (DBG) {
623 mInetLog = new ArrayList();
624 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700625
626 mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
627 mSettingsObserver.observe(mContext);
Robert Greenwalt6f7c6092010-12-02 11:31:00 -0800628
Irfan Sheriff32bed2c2012-09-20 09:32:41 -0700629 mCaptivePortalTracker = CaptivePortalTracker.makeCaptivePortalTracker(mContext, this);
Robert Greenwalt6f7c6092010-12-02 11:31:00 -0800630 loadGlobalProxy();
John Spurlock1f5cec72013-06-24 14:20:23 -0400631
632 mDataConnectionStats = new DataConnectionStats(mContext);
633 mDataConnectionStats.startMonitoring();
The Android Open Source Project28527d22009-03-03 19:31:44 -0800634 }
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700635
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700636 /**
637 * Factory that creates {@link NetworkStateTracker} instances using given
638 * {@link NetworkConfig}.
639 */
640 public interface NetworkFactory {
641 public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config);
642 }
643
644 private static class DefaultNetworkFactory implements NetworkFactory {
645 private final Context mContext;
646 private final Handler mTrackerHandler;
647
648 public DefaultNetworkFactory(Context context, Handler trackerHandler) {
649 mContext = context;
650 mTrackerHandler = trackerHandler;
651 }
652
653 @Override
654 public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config) {
655 switch (config.radio) {
656 case TYPE_WIFI:
657 return new WifiStateTracker(targetNetworkType, config.name);
658 case TYPE_MOBILE:
659 return new MobileDataStateTracker(targetNetworkType, config.name);
660 case TYPE_DUMMY:
661 return new DummyDataStateTracker(targetNetworkType, config.name);
662 case TYPE_BLUETOOTH:
663 return BluetoothTetheringDataTracker.getInstance();
664 case TYPE_WIMAX:
665 return makeWimaxStateTracker(mContext, mTrackerHandler);
666 case TYPE_ETHERNET:
667 return EthernetDataTracker.getInstance();
668 default:
669 throw new IllegalArgumentException(
670 "Trying to create a NetworkStateTracker for an unknown radio type: "
671 + config.radio);
672 }
673 }
674 }
675
676 /**
677 * Loads external WiMAX library and registers as system service, returning a
678 * {@link NetworkStateTracker} for WiMAX. Caller is still responsible for
679 * invoking {@link NetworkStateTracker#startMonitoring(Context, Handler)}.
680 */
681 private static NetworkStateTracker makeWimaxStateTracker(
682 Context context, Handler trackerHandler) {
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700683 // Initialize Wimax
tk.mun093f55c2011-10-13 22:51:57 +0900684 DexClassLoader wimaxClassLoader;
685 Class wimaxStateTrackerClass = null;
686 Class wimaxServiceClass = null;
687 Class wimaxManagerClass;
688 String wimaxJarLocation;
689 String wimaxLibLocation;
690 String wimaxManagerClassName;
691 String wimaxServiceClassName;
692 String wimaxStateTrackerClassName;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800693
tk.mun093f55c2011-10-13 22:51:57 +0900694 NetworkStateTracker wimaxStateTracker = null;
695
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700696 boolean isWimaxEnabled = context.getResources().getBoolean(
tk.mun093f55c2011-10-13 22:51:57 +0900697 com.android.internal.R.bool.config_wimaxEnabled);
698
699 if (isWimaxEnabled) {
700 try {
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700701 wimaxJarLocation = context.getResources().getString(
tk.mun093f55c2011-10-13 22:51:57 +0900702 com.android.internal.R.string.config_wimaxServiceJarLocation);
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700703 wimaxLibLocation = context.getResources().getString(
tk.mun093f55c2011-10-13 22:51:57 +0900704 com.android.internal.R.string.config_wimaxNativeLibLocation);
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700705 wimaxManagerClassName = context.getResources().getString(
tk.mun093f55c2011-10-13 22:51:57 +0900706 com.android.internal.R.string.config_wimaxManagerClassname);
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700707 wimaxServiceClassName = context.getResources().getString(
tk.mun093f55c2011-10-13 22:51:57 +0900708 com.android.internal.R.string.config_wimaxServiceClassname);
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700709 wimaxStateTrackerClassName = context.getResources().getString(
tk.mun093f55c2011-10-13 22:51:57 +0900710 com.android.internal.R.string.config_wimaxStateTrackerClassname);
711
Dianne Hackborndc456a62012-11-08 11:12:09 -0800712 if (DBG) log("wimaxJarLocation: " + wimaxJarLocation);
tk.mun093f55c2011-10-13 22:51:57 +0900713 wimaxClassLoader = new DexClassLoader(wimaxJarLocation,
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700714 new ContextWrapper(context).getCacheDir().getAbsolutePath(),
tk.mun093f55c2011-10-13 22:51:57 +0900715 wimaxLibLocation, ClassLoader.getSystemClassLoader());
716
717 try {
718 wimaxManagerClass = wimaxClassLoader.loadClass(wimaxManagerClassName);
719 wimaxStateTrackerClass = wimaxClassLoader.loadClass(wimaxStateTrackerClassName);
720 wimaxServiceClass = wimaxClassLoader.loadClass(wimaxServiceClassName);
721 } catch (ClassNotFoundException ex) {
722 loge("Exception finding Wimax classes: " + ex.toString());
723 return null;
724 }
725 } catch(Resources.NotFoundException ex) {
726 loge("Wimax Resources does not exist!!! ");
727 return null;
728 }
729
730 try {
Dianne Hackborndc456a62012-11-08 11:12:09 -0800731 if (DBG) log("Starting Wimax Service... ");
tk.mun093f55c2011-10-13 22:51:57 +0900732
733 Constructor wmxStTrkrConst = wimaxStateTrackerClass.getConstructor
734 (new Class[] {Context.class, Handler.class});
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700735 wimaxStateTracker = (NetworkStateTracker) wmxStTrkrConst.newInstance(
736 context, trackerHandler);
tk.mun093f55c2011-10-13 22:51:57 +0900737
738 Constructor wmxSrvConst = wimaxServiceClass.getDeclaredConstructor
739 (new Class[] {Context.class, wimaxStateTrackerClass});
740 wmxSrvConst.setAccessible(true);
Jeff Sharkey6b9021d2012-07-26 18:32:30 -0700741 IBinder svcInvoker = (IBinder)wmxSrvConst.newInstance(context, wimaxStateTracker);
tk.mun093f55c2011-10-13 22:51:57 +0900742 wmxSrvConst.setAccessible(false);
743
744 ServiceManager.addService(WimaxManagerConstants.WIMAX_SERVICE, svcInvoker);
745
746 } catch(Exception ex) {
747 loge("Exception creating Wimax classes: " + ex.toString());
748 return null;
749 }
750 } else {
751 loge("Wimax is not enabled or not added to the network attributes!!! ");
752 return null;
753 }
754
755 return wimaxStateTracker;
756 }
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700757
The Android Open Source Project28527d22009-03-03 19:31:44 -0800758 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700759 * Sets the preferred network.
The Android Open Source Project28527d22009-03-03 19:31:44 -0800760 * @param preference the new preference
761 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700762 public void setNetworkPreference(int preference) {
The Android Open Source Project28527d22009-03-03 19:31:44 -0800763 enforceChangePermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700764
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -0700765 mHandler.sendMessage(
766 mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
The Android Open Source Project28527d22009-03-03 19:31:44 -0800767 }
768
769 public int getNetworkPreference() {
770 enforceAccessPermission();
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700771 int preference;
772 synchronized(this) {
773 preference = mNetworkPreference;
774 }
775 return preference;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800776 }
777
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700778 private void handleSetNetworkPreference(int preference) {
779 if (ConnectivityManager.isNetworkTypeValid(preference) &&
Robert Greenwalt34848c02011-03-25 13:09:25 -0700780 mNetConfigs[preference] != null &&
781 mNetConfigs[preference].isDefault()) {
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700782 if (mNetworkPreference != preference) {
783 final ContentResolver cr = mContext.getContentResolver();
Jeff Brownc67cf562012-09-25 15:03:20 -0700784 Settings.Global.putInt(cr, Settings.Global.NETWORK_PREFERENCE, preference);
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -0700785 synchronized(this) {
786 mNetworkPreference = preference;
787 }
788 enforcePreference();
789 }
790 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800791 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700792
Wink Saville4f0de1e2011-08-04 15:01:58 -0700793 private int getConnectivityChangeDelay() {
794 final ContentResolver cr = mContext.getContentResolver();
795
796 /** Check system properties for the default value then use secure settings value, if any. */
797 int defaultDelay = SystemProperties.getInt(
Jeff Sharkey8c870452012-09-26 22:03:49 -0700798 "conn." + Settings.Global.CONNECTIVITY_CHANGE_DELAY,
799 ConnectivityManager.CONNECTIVITY_CHANGE_DELAY_DEFAULT);
800 return Settings.Global.getInt(cr, Settings.Global.CONNECTIVITY_CHANGE_DELAY,
Wink Saville4f0de1e2011-08-04 15:01:58 -0700801 defaultDelay);
802 }
803
The Android Open Source Project28527d22009-03-03 19:31:44 -0800804 private int getPersistedNetworkPreference() {
805 final ContentResolver cr = mContext.getContentResolver();
806
Jeff Brownc67cf562012-09-25 15:03:20 -0700807 final int networkPrefSetting = Settings.Global
808 .getInt(cr, Settings.Global.NETWORK_PREFERENCE, -1);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800809
Jianzheng Zhou028d2032012-11-16 13:45:20 +0800810 return networkPrefSetting;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800811 }
Robert Greenwalt0659da32009-07-16 17:21:39 -0700812
The Android Open Source Project28527d22009-03-03 19:31:44 -0800813 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -0700814 * Make the state of network connectivity conform to the preference settings
The Android Open Source Project28527d22009-03-03 19:31:44 -0800815 * In this method, we only tear down a non-preferred network. Establishing
816 * a connection to the preferred network is taken care of when we handle
817 * the disconnect event from the non-preferred network
818 * (see {@link #handleDisconnect(NetworkInfo)}).
819 */
820 private void enforcePreference() {
Robert Greenwalt2034b912009-08-12 16:08:25 -0700821 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
The Android Open Source Project28527d22009-03-03 19:31:44 -0800822 return;
823
Robert Greenwalt2034b912009-08-12 16:08:25 -0700824 if (!mNetTrackers[mNetworkPreference].isAvailable())
825 return;
The Android Open Source Project28527d22009-03-03 19:31:44 -0800826
Robert Greenwalt2034b912009-08-12 16:08:25 -0700827 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -0700828 if (t != mNetworkPreference && mNetTrackers[t] != null &&
Robert Greenwalt2034b912009-08-12 16:08:25 -0700829 mNetTrackers[t].getNetworkInfo().isConnected()) {
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700830 if (DBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -0800831 log("tearing down " + mNetTrackers[t].getNetworkInfo() +
Robert Greenwaltf3f045b2009-08-20 15:25:14 -0700832 " in enforcePreference");
833 }
Robert Greenwalt2034b912009-08-12 16:08:25 -0700834 teardown(mNetTrackers[t]);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800835 }
836 }
837 }
838
839 private boolean teardown(NetworkStateTracker netTracker) {
840 if (netTracker.teardown()) {
841 netTracker.setTeardownRequested(true);
842 return true;
843 } else {
844 return false;
845 }
846 }
847
848 /**
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700849 * Check if UID should be blocked from using the network represented by the
850 * given {@link NetworkStateTracker}.
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700851 */
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700852 private boolean isNetworkBlocked(NetworkStateTracker tracker, int uid) {
853 final String iface = tracker.getLinkProperties().getInterfaceName();
Jeff Sharkey21062e72011-05-28 20:56:34 -0700854
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700855 final boolean networkCostly;
856 final int uidRules;
857 synchronized (mRulesLock) {
858 networkCostly = mMeteredIfaces.contains(iface);
859 uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700860 }
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700861
862 if (networkCostly && (uidRules & RULE_REJECT_METERED) != 0) {
863 return true;
864 }
865
866 // no restrictive rules; network is visible
867 return false;
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700868 }
869
870 /**
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700871 * Return a filtered {@link NetworkInfo}, potentially marked
872 * {@link DetailedState#BLOCKED} based on
873 * {@link #isNetworkBlocked(NetworkStateTracker, int)}.
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700874 */
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700875 private NetworkInfo getFilteredNetworkInfo(NetworkStateTracker tracker, int uid) {
876 NetworkInfo info = tracker.getNetworkInfo();
877 if (isNetworkBlocked(tracker, uid)) {
Jeff Sharkey21062e72011-05-28 20:56:34 -0700878 // network is blocked; clone and override state
879 info = new NetworkInfo(info);
880 info.setDetailedState(DetailedState.BLOCKED, null, null);
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700881 }
Jeff Sharkeyebcc7972012-08-25 00:05:46 -0700882 if (mLockdownTracker != null) {
883 info = mLockdownTracker.augmentNetworkInfo(info);
884 }
Jeff Sharkey21062e72011-05-28 20:56:34 -0700885 return info;
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700886 }
887
888 /**
The Android Open Source Project28527d22009-03-03 19:31:44 -0800889 * Return NetworkInfo for the active (i.e., connected) network interface.
890 * It is assumed that at most one network is active at a time. If more
891 * than one is active, it is indeterminate which will be returned.
Robert Greenwalt0659da32009-07-16 17:21:39 -0700892 * @return the info for the active network, or {@code null} if none is
893 * active
The Android Open Source Project28527d22009-03-03 19:31:44 -0800894 */
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700895 @Override
The Android Open Source Project28527d22009-03-03 19:31:44 -0800896 public NetworkInfo getActiveNetworkInfo() {
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700897 enforceAccessPermission();
898 final int uid = Binder.getCallingUid();
899 return getNetworkInfo(mActiveDefaultNetwork, uid);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800900 }
901
Jeff Sharkeyebcc7972012-08-25 00:05:46 -0700902 public NetworkInfo getActiveNetworkInfoUnfiltered() {
903 enforceAccessPermission();
904 if (isNetworkTypeValid(mActiveDefaultNetwork)) {
905 final NetworkStateTracker tracker = mNetTrackers[mActiveDefaultNetwork];
906 if (tracker != null) {
907 return tracker.getNetworkInfo();
908 }
909 }
910 return null;
911 }
912
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700913 @Override
914 public NetworkInfo getActiveNetworkInfoForUid(int uid) {
915 enforceConnectivityInternalPermission();
916 return getNetworkInfo(mActiveDefaultNetwork, uid);
917 }
918
919 @Override
The Android Open Source Project28527d22009-03-03 19:31:44 -0800920 public NetworkInfo getNetworkInfo(int networkType) {
921 enforceAccessPermission();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700922 final int uid = Binder.getCallingUid();
923 return getNetworkInfo(networkType, uid);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800924 }
925
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700926 private NetworkInfo getNetworkInfo(int networkType, int uid) {
927 NetworkInfo info = null;
928 if (isNetworkTypeValid(networkType)) {
929 final NetworkStateTracker tracker = mNetTrackers[networkType];
930 if (tracker != null) {
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700931 info = getFilteredNetworkInfo(tracker, uid);
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700932 }
933 }
934 return info;
935 }
936
937 @Override
The Android Open Source Project28527d22009-03-03 19:31:44 -0800938 public NetworkInfo[] getAllNetworkInfo() {
939 enforceAccessPermission();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700940 final int uid = Binder.getCallingUid();
Jeff Sharkey21062e72011-05-28 20:56:34 -0700941 final ArrayList<NetworkInfo> result = Lists.newArrayList();
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700942 synchronized (mRulesLock) {
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700943 for (NetworkStateTracker tracker : mNetTrackers) {
944 if (tracker != null) {
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700945 result.add(getFilteredNetworkInfo(tracker, uid));
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700946 }
947 }
The Android Open Source Project28527d22009-03-03 19:31:44 -0800948 }
Jeff Sharkey21062e72011-05-28 20:56:34 -0700949 return result.toArray(new NetworkInfo[result.size()]);
The Android Open Source Project28527d22009-03-03 19:31:44 -0800950 }
951
Robert Greenwalt0114f6e2011-08-31 11:46:42 -0700952 @Override
953 public boolean isNetworkSupported(int networkType) {
954 enforceAccessPermission();
955 return (isNetworkTypeValid(networkType) && (mNetTrackers[networkType] != null));
956 }
957
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700958 /**
959 * Return LinkProperties for the active (i.e., connected) default
960 * network interface. It is assumed that at most one default network
961 * is active at a time. If more than one is active, it is indeterminate
962 * which will be returned.
963 * @return the ip properties for the active network, or {@code null} if
964 * none is active
965 */
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700966 @Override
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700967 public LinkProperties getActiveLinkProperties() {
Robert Greenwalte1544bb2011-05-20 12:23:41 -0700968 return getLinkProperties(mActiveDefaultNetwork);
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700969 }
970
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700971 @Override
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700972 public LinkProperties getLinkProperties(int networkType) {
973 enforceAccessPermission();
Jeff Sharkey921ebf22011-05-19 17:12:49 -0700974 if (isNetworkTypeValid(networkType)) {
975 final NetworkStateTracker tracker = mNetTrackers[networkType];
976 if (tracker != null) {
977 return tracker.getLinkProperties();
978 }
Robert Greenwalt9f0ee4f2010-09-14 09:18:02 -0700979 }
980 return null;
981 }
982
Jeff Sharkey21062e72011-05-28 20:56:34 -0700983 @Override
984 public NetworkState[] getAllNetworkState() {
985 enforceAccessPermission();
986 final int uid = Binder.getCallingUid();
987 final ArrayList<NetworkState> result = Lists.newArrayList();
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700988 synchronized (mRulesLock) {
Jeff Sharkey21062e72011-05-28 20:56:34 -0700989 for (NetworkStateTracker tracker : mNetTrackers) {
990 if (tracker != null) {
Jeff Sharkeya47d7a12011-06-16 15:07:48 -0700991 final NetworkInfo info = getFilteredNetworkInfo(tracker, uid);
Jeff Sharkey21062e72011-05-28 20:56:34 -0700992 result.add(new NetworkState(
993 info, tracker.getLinkProperties(), tracker.getLinkCapabilities()));
994 }
995 }
996 }
997 return result.toArray(new NetworkState[result.size()]);
998 }
999
Jeff Sharkey66fa9682011-08-02 17:22:34 -07001000 private NetworkState getNetworkStateUnchecked(int networkType) {
1001 if (isNetworkTypeValid(networkType)) {
1002 final NetworkStateTracker tracker = mNetTrackers[networkType];
1003 if (tracker != null) {
1004 return new NetworkState(tracker.getNetworkInfo(), tracker.getLinkProperties(),
1005 tracker.getLinkCapabilities());
1006 }
1007 }
1008 return null;
1009 }
1010
1011 @Override
1012 public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
1013 enforceAccessPermission();
Jeff Sharkey3022ee12012-04-17 12:23:40 -07001014
1015 final long token = Binder.clearCallingIdentity();
1016 try {
1017 final NetworkState state = getNetworkStateUnchecked(mActiveDefaultNetwork);
1018 if (state != null) {
1019 try {
1020 return mPolicyManager.getNetworkQuotaInfo(state);
1021 } catch (RemoteException e) {
1022 }
Jeff Sharkey66fa9682011-08-02 17:22:34 -07001023 }
Jeff Sharkey3022ee12012-04-17 12:23:40 -07001024 return null;
1025 } finally {
1026 Binder.restoreCallingIdentity(token);
Jeff Sharkey66fa9682011-08-02 17:22:34 -07001027 }
Jeff Sharkey66fa9682011-08-02 17:22:34 -07001028 }
1029
Jeff Sharkeyd00b1302012-04-12 18:34:54 -07001030 @Override
1031 public boolean isActiveNetworkMetered() {
1032 enforceAccessPermission();
Jeff Sharkey3022ee12012-04-17 12:23:40 -07001033 final long token = Binder.clearCallingIdentity();
1034 try {
Jeff Sharkeyedf85d42012-04-30 15:47:05 -07001035 return isNetworkMeteredUnchecked(mActiveDefaultNetwork);
Jeff Sharkey3022ee12012-04-17 12:23:40 -07001036 } finally {
1037 Binder.restoreCallingIdentity(token);
Jeff Sharkeyd00b1302012-04-12 18:34:54 -07001038 }
Jeff Sharkeyd00b1302012-04-12 18:34:54 -07001039 }
1040
Jeff Sharkeyedf85d42012-04-30 15:47:05 -07001041 private boolean isNetworkMeteredUnchecked(int networkType) {
1042 final NetworkState state = getNetworkStateUnchecked(networkType);
1043 if (state != null) {
1044 try {
1045 return mPolicyManager.isNetworkMetered(state);
1046 } catch (RemoteException e) {
1047 }
1048 }
1049 return false;
1050 }
1051
The Android Open Source Project28527d22009-03-03 19:31:44 -08001052 public boolean setRadios(boolean turnOn) {
1053 boolean result = true;
1054 enforceChangePermission();
1055 for (NetworkStateTracker t : mNetTrackers) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001056 if (t != null) result = t.setRadio(turnOn) && result;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001057 }
1058 return result;
1059 }
1060
1061 public boolean setRadio(int netType, boolean turnOn) {
1062 enforceChangePermission();
1063 if (!ConnectivityManager.isNetworkTypeValid(netType)) {
1064 return false;
1065 }
1066 NetworkStateTracker tracker = mNetTrackers[netType];
1067 return tracker != null && tracker.setRadio(turnOn);
1068 }
1069
Jeff Sharkey60e6c1a2012-08-05 14:29:23 -07001070 private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
1071 @Override
Haoyu Baib5da5752012-06-20 14:29:57 -07001072 public void interfaceClassDataActivityChanged(String label, boolean active) {
1073 int deviceType = Integer.parseInt(label);
1074 sendDataActivityBroadcast(deviceType, active);
1075 }
Jeff Sharkey60e6c1a2012-08-05 14:29:23 -07001076 };
Haoyu Baib5da5752012-06-20 14:29:57 -07001077
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001078 /**
1079 * Used to notice when the calling process dies so we can self-expire
1080 *
1081 * Also used to know if the process has cleaned up after itself when
1082 * our auto-expire timer goes off. The timer has a link to an object.
1083 *
1084 */
Robert Greenwalt2034b912009-08-12 16:08:25 -07001085 private class FeatureUser implements IBinder.DeathRecipient {
1086 int mNetworkType;
1087 String mFeature;
1088 IBinder mBinder;
1089 int mPid;
1090 int mUid;
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08001091 long mCreateTime;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001092
1093 FeatureUser(int type, String feature, IBinder binder) {
1094 super();
1095 mNetworkType = type;
1096 mFeature = feature;
1097 mBinder = binder;
1098 mPid = getCallingPid();
1099 mUid = getCallingUid();
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08001100 mCreateTime = System.currentTimeMillis();
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001101
Robert Greenwalt2034b912009-08-12 16:08:25 -07001102 try {
1103 mBinder.linkToDeath(this, 0);
1104 } catch (RemoteException e) {
1105 binderDied();
1106 }
1107 }
1108
1109 void unlinkDeathRecipient() {
1110 mBinder.unlinkToDeath(this, 0);
1111 }
1112
1113 public void binderDied() {
Wink Savillee70c6f52010-12-03 12:01:38 -08001114 log("ConnectivityService FeatureUser binderDied(" +
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08001115 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " +
1116 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001117 stopUsingNetworkFeature(this, false);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001118 }
1119
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001120 public void expire() {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001121 if (VDBG) {
1122 log("ConnectivityService FeatureUser expire(" +
1123 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " +
1124 (System.currentTimeMillis() - mCreateTime) + " mSec ago");
1125 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001126 stopUsingNetworkFeature(this, false);
1127 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08001128
Kazuhiro Ondocae18f12011-07-19 11:23:37 -05001129 public boolean isSameUser(FeatureUser u) {
1130 if (u == null) return false;
1131
1132 return isSameUser(u.mPid, u.mUid, u.mNetworkType, u.mFeature);
1133 }
1134
1135 public boolean isSameUser(int pid, int uid, int networkType, String feature) {
1136 if ((mPid == pid) && (mUid == uid) && (mNetworkType == networkType) &&
1137 TextUtils.equals(mFeature, feature)) {
1138 return true;
1139 }
1140 return false;
1141 }
1142
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08001143 public String toString() {
1144 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
1145 (System.currentTimeMillis() - mCreateTime) + " mSec ago";
1146 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001147 }
1148
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001149 // javadoc from interface
Robert Greenwalt2034b912009-08-12 16:08:25 -07001150 public int startUsingNetworkFeature(int networkType, String feature,
1151 IBinder binder) {
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001152 long startTime = 0;
1153 if (DBG) {
1154 startTime = SystemClock.elapsedRealtime();
1155 }
Wink Savillea7d56572011-09-21 11:05:43 -07001156 if (VDBG) {
Jeff Sharkeyedf85d42012-04-30 15:47:05 -07001157 log("startUsingNetworkFeature for net " + networkType + ": " + feature + ", uid="
1158 + Binder.getCallingUid());
Robert Greenwalt2034b912009-08-12 16:08:25 -07001159 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001160 enforceChangePermission();
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001161 try {
1162 if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
1163 mNetConfigs[networkType] == null) {
Wink Saville64e3f782012-07-10 12:37:54 -07001164 return PhoneConstants.APN_REQUEST_FAILED;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001165 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001166
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001167 FeatureUser f = new FeatureUser(networkType, feature, binder);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001168
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001169 // TODO - move this into individual networktrackers
1170 int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
Robert Greenwalt6cac0742011-06-21 17:26:14 -07001171
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07001172 if (mLockdownEnabled) {
1173 // Since carrier APNs usually aren't available from VPN
1174 // endpoint, mark them as unavailable.
1175 return PhoneConstants.APN_TYPE_NOT_AVAILABLE;
1176 }
1177
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001178 if (mProtectedNetworks.contains(usedNetworkType)) {
1179 enforceConnectivityInternalPermission();
1180 }
Robert Greenwalt6cac0742011-06-21 17:26:14 -07001181
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001182 // if UID is restricted, don't allow them to bring up metered APNs
1183 final boolean networkMetered = isNetworkMeteredUnchecked(usedNetworkType);
1184 final int uidRules;
1185 synchronized (mRulesLock) {
1186 uidRules = mUidRules.get(Binder.getCallingUid(), RULE_ALLOW_ALL);
1187 }
1188 if (networkMetered && (uidRules & RULE_REJECT_METERED) != 0) {
Wink Saville64e3f782012-07-10 12:37:54 -07001189 return PhoneConstants.APN_REQUEST_FAILED;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001190 }
Jeff Sharkeyedf85d42012-04-30 15:47:05 -07001191
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001192 NetworkStateTracker network = mNetTrackers[usedNetworkType];
1193 if (network != null) {
1194 Integer currentPid = new Integer(getCallingPid());
1195 if (usedNetworkType != networkType) {
1196 NetworkInfo ni = network.getNetworkInfo();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001197
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001198 if (ni.isAvailable() == false) {
1199 if (!TextUtils.equals(feature,Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
1200 if (DBG) log("special network not available ni=" + ni.getTypeName());
Wink Saville64e3f782012-07-10 12:37:54 -07001201 return PhoneConstants.APN_TYPE_NOT_AVAILABLE;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001202 } else {
1203 // else make the attempt anyway - probably giving REQUEST_STARTED below
1204 if (DBG) {
1205 log("special network not available, but try anyway ni=" +
1206 ni.getTypeName());
Kazuhiro Ondocae18f12011-07-19 11:23:37 -05001207 }
1208 }
1209 }
1210
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001211 int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001212
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001213 synchronized(this) {
1214 boolean addToList = true;
1215 if (restoreTimer < 0) {
1216 // In case there is no timer is specified for the feature,
1217 // make sure we don't add duplicate entry with the same request.
1218 for (FeatureUser u : mFeatureUsers) {
1219 if (u.isSameUser(f)) {
1220 // Duplicate user is found. Do not add.
1221 addToList = false;
1222 break;
1223 }
1224 }
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001225 }
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001226
1227 if (addToList) mFeatureUsers.add(f);
1228 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
1229 // this gets used for per-pid dns when connected
1230 mNetRequestersPids[usedNetworkType].add(currentPid);
1231 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001232 }
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001233
1234 if (restoreTimer >= 0) {
1235 mHandler.sendMessageDelayed(mHandler.obtainMessage(
1236 EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer);
1237 }
1238
1239 if ((ni.isConnectedOrConnecting() == true) &&
1240 !network.isTeardownRequested()) {
1241 if (ni.isConnected() == true) {
1242 final long token = Binder.clearCallingIdentity();
1243 try {
1244 // add the pid-specific dns
1245 handleDnsConfigurationChange(usedNetworkType);
1246 if (VDBG) log("special network already active");
1247 } finally {
1248 Binder.restoreCallingIdentity(token);
1249 }
Wink Saville64e3f782012-07-10 12:37:54 -07001250 return PhoneConstants.APN_ALREADY_ACTIVE;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001251 }
1252 if (VDBG) log("special network already connecting");
Wink Saville64e3f782012-07-10 12:37:54 -07001253 return PhoneConstants.APN_REQUEST_STARTED;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001254 }
1255
1256 // check if the radio in play can make another contact
1257 // assume if cannot for now
1258
1259 if (DBG) {
1260 log("startUsingNetworkFeature reconnecting to " + networkType + ": " +
1261 feature);
1262 }
Mikael Hedegrenc6534b52012-12-14 15:52:52 +01001263 if (network.reconnect()) {
1264 return PhoneConstants.APN_REQUEST_STARTED;
1265 } else {
1266 return PhoneConstants.APN_REQUEST_FAILED;
1267 }
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001268 } else {
1269 // need to remember this unsupported request so we respond appropriately on stop
1270 synchronized(this) {
1271 mFeatureUsers.add(f);
1272 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
1273 // this gets used for per-pid dns when connected
1274 mNetRequestersPids[usedNetworkType].add(currentPid);
1275 }
Robert Greenwalt5364d752010-12-15 13:26:33 -08001276 }
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001277 return -1;
Robert Greenwalt5364d752010-12-15 13:26:33 -08001278 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001279 }
Wink Saville64e3f782012-07-10 12:37:54 -07001280 return PhoneConstants.APN_TYPE_NOT_AVAILABLE;
Robert Greenwalt1e6991e2012-05-22 16:07:46 -07001281 } finally {
1282 if (DBG) {
1283 final long execTime = SystemClock.elapsedRealtime() - startTime;
1284 if (execTime > 250) {
1285 loge("startUsingNetworkFeature took too long: " + execTime + "ms");
1286 } else {
1287 if (VDBG) log("startUsingNetworkFeature took " + execTime + "ms");
1288 }
1289 }
1290 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001291 }
1292
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001293 // javadoc from interface
The Android Open Source Project28527d22009-03-03 19:31:44 -08001294 public int stopUsingNetworkFeature(int networkType, String feature) {
Robert Greenwalt28f43012009-10-06 17:52:40 -07001295 enforceChangePermission();
1296
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001297 int pid = getCallingPid();
1298 int uid = getCallingUid();
1299
1300 FeatureUser u = null;
1301 boolean found = false;
1302
1303 synchronized(this) {
Kazuhiro Ondocae18f12011-07-19 11:23:37 -05001304 for (FeatureUser x : mFeatureUsers) {
1305 if (x.isSameUser(pid, uid, networkType, feature)) {
1306 u = x;
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001307 found = true;
1308 break;
1309 }
1310 }
1311 }
1312 if (found && u != null) {
1313 // stop regardless of how many other time this proc had called start
1314 return stopUsingNetworkFeature(u, true);
1315 } else {
1316 // none found!
Wink Savillea7d56572011-09-21 11:05:43 -07001317 if (VDBG) log("stopUsingNetworkFeature - not a live request, ignoring");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001318 return 1;
1319 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001320 }
1321
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001322 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
1323 int networkType = u.mNetworkType;
1324 String feature = u.mFeature;
1325 int pid = u.mPid;
1326 int uid = u.mUid;
1327
1328 NetworkStateTracker tracker = null;
1329 boolean callTeardown = false; // used to carry our decision outside of sync block
1330
Wink Savillea7d56572011-09-21 11:05:43 -07001331 if (VDBG) {
1332 log("stopUsingNetworkFeature: net " + networkType + ": " + feature);
Robert Greenwalt2034b912009-08-12 16:08:25 -07001333 }
Robert Greenwalt28f43012009-10-06 17:52:40 -07001334
The Android Open Source Project28527d22009-03-03 19:31:44 -08001335 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
Wink Savillea7d56572011-09-21 11:05:43 -07001336 if (DBG) {
1337 log("stopUsingNetworkFeature: net " + networkType + ": " + feature +
1338 ", net is invalid");
1339 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001340 return -1;
1341 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001342
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001343 // need to link the mFeatureUsers list with the mNetRequestersPids state in this
1344 // sync block
1345 synchronized(this) {
1346 // check if this process still has an outstanding start request
1347 if (!mFeatureUsers.contains(u)) {
Wink Savillea7d56572011-09-21 11:05:43 -07001348 if (VDBG) {
1349 log("stopUsingNetworkFeature: this process has no outstanding requests" +
1350 ", ignoring");
1351 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001352 return 1;
1353 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001354 u.unlinkDeathRecipient();
1355 mFeatureUsers.remove(mFeatureUsers.indexOf(u));
1356 // If we care about duplicate requests, check for that here.
1357 //
1358 // This is done to support the extension of a request - the app
1359 // can request we start the network feature again and renew the
1360 // auto-shutoff delay. Normal "stop" calls from the app though
1361 // do not pay attention to duplicate requests - in effect the
1362 // API does not refcount and a single stop will counter multiple starts.
1363 if (ignoreDups == false) {
Kazuhiro Ondocae18f12011-07-19 11:23:37 -05001364 for (FeatureUser x : mFeatureUsers) {
1365 if (x.isSameUser(u)) {
Wink Savillea7d56572011-09-21 11:05:43 -07001366 if (VDBG) log("stopUsingNetworkFeature: dup is found, ignoring");
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001367 return 1;
1368 }
1369 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001370 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001371
repo syncf5de5572011-07-29 23:55:49 -07001372 // TODO - move to individual network trackers
1373 int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
1374
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001375 tracker = mNetTrackers[usedNetworkType];
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001376 if (tracker == null) {
Wink Savillea7d56572011-09-21 11:05:43 -07001377 if (DBG) {
1378 log("stopUsingNetworkFeature: net " + networkType + ": " + feature +
1379 " no known tracker for used net type " + usedNetworkType);
1380 }
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001381 return -1;
1382 }
1383 if (usedNetworkType != networkType) {
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001384 Integer currentPid = new Integer(pid);
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001385 mNetRequestersPids[usedNetworkType].remove(currentPid);
Robert Greenwalte767d812013-02-12 17:18:25 -08001386
1387 final long token = Binder.clearCallingIdentity();
1388 try {
1389 reassessPidDns(pid, true);
1390 } finally {
1391 Binder.restoreCallingIdentity(token);
1392 }
Mattias Falkd697aa22011-08-23 14:15:13 +02001393 flushVmDnsCache();
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001394 if (mNetRequestersPids[usedNetworkType].size() != 0) {
Wink Savillea7d56572011-09-21 11:05:43 -07001395 if (VDBG) {
1396 log("stopUsingNetworkFeature: net " + networkType + ": " + feature +
1397 " others still using it");
1398 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001399 return 1;
1400 }
1401 callTeardown = true;
Robert Greenwalt9f3be4c2011-01-10 11:58:31 -08001402 } else {
Wink Savillea7d56572011-09-21 11:05:43 -07001403 if (DBG) {
1404 log("stopUsingNetworkFeature: net " + networkType + ": " + feature +
1405 " not a known feature - dropping");
1406 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001407 }
1408 }
Wink Savillea7d56572011-09-21 11:05:43 -07001409
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001410 if (callTeardown) {
Wink Savillea7d56572011-09-21 11:05:43 -07001411 if (DBG) {
1412 log("stopUsingNetworkFeature: teardown net " + networkType + ": " + feature);
1413 }
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07001414 tracker.teardown();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001415 return 1;
1416 } else {
Robert Greenwaltd391e892010-05-18 10:52:51 -07001417 return -1;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001418 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001419 }
1420
1421 /**
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -07001422 * @deprecated use requestRouteToHostAddress instead
1423 *
The Android Open Source Project28527d22009-03-03 19:31:44 -08001424 * Ensure that a network route exists to deliver traffic to the specified
1425 * host via the specified network interface.
Robert Greenwalt0659da32009-07-16 17:21:39 -07001426 * @param networkType the type of the network over which traffic to the
1427 * specified host is to be routed
1428 * @param hostAddress the IP address of the host to which the route is
1429 * desired
The Android Open Source Project28527d22009-03-03 19:31:44 -08001430 * @return {@code true} on success, {@code false} on failure
1431 */
1432 public boolean requestRouteToHost(int networkType, int hostAddress) {
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -07001433 InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
1434
1435 if (inetAddress == null) {
1436 return false;
1437 }
1438
1439 return requestRouteToHostAddress(networkType, inetAddress.getAddress());
1440 }
1441
1442 /**
1443 * Ensure that a network route exists to deliver traffic to the specified
1444 * host via the specified network interface.
1445 * @param networkType the type of the network over which traffic to the
1446 * specified host is to be routed
1447 * @param hostAddress the IP address of the host to which the route is
1448 * desired
1449 * @return {@code true} on success, {@code false} on failure
1450 */
1451 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08001452 enforceChangePermission();
Robert Greenwalt6cac0742011-06-21 17:26:14 -07001453 if (mProtectedNetworks.contains(networkType)) {
1454 enforceConnectivityInternalPermission();
1455 }
1456
The Android Open Source Project28527d22009-03-03 19:31:44 -08001457 if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001458 if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001459 return false;
1460 }
1461 NetworkStateTracker tracker = mNetTrackers[networkType];
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07001462 DetailedState netState = tracker.getNetworkInfo().getDetailedState();
Robert Greenwalt4666ed02009-09-10 15:06:20 -07001463
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07001464 if (tracker == null || (netState != DetailedState.CONNECTED &&
1465 netState != DetailedState.CAPTIVE_PORTAL_CHECK) ||
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001466 tracker.isTeardownRequested()) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001467 if (VDBG) {
Wink Saville32506bc2013-06-29 21:10:57 -07001468 log("requestRouteToHostAddress on down network "
1469 + "(" + networkType + ") - dropped"
1470 + " tracker=" + tracker
1471 + " netState=" + netState
1472 + " isTeardownRequested="
1473 + ((tracker != null) ? tracker.isTeardownRequested() : "tracker:null"));
Robert Greenwalt4666ed02009-09-10 15:06:20 -07001474 }
1475 return false;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001476 }
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001477 final long token = Binder.clearCallingIdentity();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001478 try {
Robert Greenwalt7fe44cb2010-08-27 09:24:29 -07001479 InetAddress addr = InetAddress.getByAddress(hostAddress);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001480 LinkProperties lp = tracker.getLinkProperties();
Chad Brubaker49db4222013-07-15 16:34:04 -07001481 boolean ok = addRouteToAddress(lp, addr, EXEMPT);
Wink Saville32506bc2013-06-29 21:10:57 -07001482 if (DBG) log("requestRouteToHostAddress ok=" + ok);
1483 return ok;
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001484 } catch (UnknownHostException e) {
1485 if (DBG) log("requestRouteToHostAddress got " + e.toString());
1486 } finally {
1487 Binder.restoreCallingIdentity(token);
1488 }
Wink Saville32506bc2013-06-29 21:10:57 -07001489 if (DBG) log("requestRouteToHostAddress X bottom return false");
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001490 return false;
Irfan Sheriff7f132d92010-06-09 15:39:36 -07001491 }
1492
Chad Brubaker49db4222013-07-15 16:34:04 -07001493 private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable,
1494 boolean exempt) {
1495 return modifyRoute(p, r, 0, ADD, toDefaultTable, exempt);
Robert Greenwaltbd492212011-05-06 17:10:53 -07001496 }
1497
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001498 private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
Chad Brubaker49db4222013-07-15 16:34:04 -07001499 return modifyRoute(p, r, 0, REMOVE, toDefaultTable, UNEXEMPT);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001500 }
1501
Chad Brubaker49db4222013-07-15 16:34:04 -07001502 private boolean addRouteToAddress(LinkProperties lp, InetAddress addr, boolean exempt) {
1503 return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE, exempt);
Robert Greenwalt98107422011-07-22 11:55:33 -07001504 }
1505
1506 private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) {
Chad Brubaker49db4222013-07-15 16:34:04 -07001507 return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE, UNEXEMPT);
Robert Greenwalt98107422011-07-22 11:55:33 -07001508 }
1509
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001510 private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd,
Chad Brubaker49db4222013-07-15 16:34:04 -07001511 boolean toDefaultTable, boolean exempt) {
Lorenzo Colittie43b6c42013-03-15 13:58:38 +09001512 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), addr);
Robert Greenwalt98107422011-07-22 11:55:33 -07001513 if (bestRoute == null) {
Lorenzo Colittie43b6c42013-03-15 13:58:38 +09001514 bestRoute = RouteInfo.makeHostRoute(addr, lp.getInterfaceName());
Robert Greenwalt98107422011-07-22 11:55:33 -07001515 } else {
Lorenzo Colittie43b6c42013-03-15 13:58:38 +09001516 String iface = bestRoute.getInterface();
Robert Greenwalt98107422011-07-22 11:55:33 -07001517 if (bestRoute.getGateway().equals(addr)) {
1518 // if there is no better route, add the implied hostroute for our gateway
Lorenzo Colitti7a43b0f2013-03-08 12:30:44 -08001519 bestRoute = RouteInfo.makeHostRoute(addr, iface);
Robert Greenwalt98107422011-07-22 11:55:33 -07001520 } else {
1521 // if we will connect to this through another route, add a direct route
1522 // to it's gateway
Lorenzo Colitti7a43b0f2013-03-08 12:30:44 -08001523 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
Robert Greenwalt98107422011-07-22 11:55:33 -07001524 }
1525 }
Chad Brubaker49db4222013-07-15 16:34:04 -07001526 return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable, exempt);
Robert Greenwalt98107422011-07-22 11:55:33 -07001527 }
1528
Lorenzo Colitti53de3362013-03-12 07:39:59 +09001529 private boolean modifyRoute(LinkProperties lp, RouteInfo r, int cycleCount, boolean doAdd,
Chad Brubaker49db4222013-07-15 16:34:04 -07001530 boolean toDefaultTable, boolean exempt) {
Lorenzo Colittie43b6c42013-03-15 13:58:38 +09001531 if ((lp == null) || (r == null)) {
1532 if (DBG) log("modifyRoute got unexpected null: " + lp + ", " + r);
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001533 return false;
1534 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001535
1536 if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001537 loge("Error modifying route - too much recursion");
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001538 return false;
1539 }
1540
Lorenzo Colittie43b6c42013-03-15 13:58:38 +09001541 String ifaceName = r.getInterface();
1542 if(ifaceName == null) {
1543 loge("Error modifying route - no interface name");
1544 return false;
1545 }
Robert Greenwalt59070cf2013-04-11 13:48:16 -07001546 if (r.hasGateway()) {
Lorenzo Colittie43b6c42013-03-15 13:58:38 +09001547 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getAllRoutes(), r.getGateway());
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001548 if (bestRoute != null) {
Robert Greenwalt57c83bb2011-07-15 09:45:08 -07001549 if (bestRoute.getGateway().equals(r.getGateway())) {
1550 // if there is no better route, add the implied hostroute for our gateway
Lorenzo Colitti7a43b0f2013-03-08 12:30:44 -08001551 bestRoute = RouteInfo.makeHostRoute(r.getGateway(), ifaceName);
Robert Greenwalt57c83bb2011-07-15 09:45:08 -07001552 } else {
1553 // if we will connect to our gateway through another route, add a direct
1554 // route to it's gateway
Lorenzo Colitti7a43b0f2013-03-08 12:30:44 -08001555 bestRoute = RouteInfo.makeHostRoute(r.getGateway(),
1556 bestRoute.getGateway(),
1557 ifaceName);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001558 }
Chad Brubaker49db4222013-07-15 16:34:04 -07001559 modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable, exempt);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001560 }
1561 }
1562 if (doAdd) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001563 if (VDBG) log("Adding " + r + " for interface " + ifaceName);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001564 try {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001565 if (toDefaultTable) {
Chad Brubaker49db4222013-07-15 16:34:04 -07001566 synchronized (mRoutesLock) {
1567 // only track default table - only one apps can effect
1568 mAddedRoutes.add(r);
1569 mNetd.addRoute(ifaceName, r);
1570 if (exempt) {
1571 LinkAddress dest = r.getDestination();
1572 if (!mExemptAddresses.contains(dest)) {
1573 mNetd.setHostExemption(dest);
1574 mExemptAddresses.add(dest);
1575 }
1576 }
1577 }
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001578 } else {
1579 mNetd.addSecondaryRoute(ifaceName, r);
1580 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001581 } catch (Exception e) {
1582 // never crash - catch them all
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08001583 if (DBG) loge("Exception trying to add a route: " + e);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001584 return false;
1585 }
1586 } else {
1587 // if we remove this one and there are no more like it, then refcount==0 and
1588 // we can remove it from the table
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001589 if (toDefaultTable) {
Chad Brubaker49db4222013-07-15 16:34:04 -07001590 synchronized (mRoutesLock) {
1591 mAddedRoutes.remove(r);
1592 if (mAddedRoutes.contains(r) == false) {
1593 if (VDBG) log("Removing " + r + " for interface " + ifaceName);
1594 try {
1595 mNetd.removeRoute(ifaceName, r);
1596 LinkAddress dest = r.getDestination();
1597 if (mExemptAddresses.contains(dest)) {
1598 mNetd.clearHostExemption(dest);
1599 mExemptAddresses.remove(dest);
1600 }
1601 } catch (Exception e) {
1602 // never crash - catch them all
1603 if (VDBG) loge("Exception trying to remove a route: " + e);
1604 return false;
1605 }
1606 } else {
1607 if (VDBG) log("not removing " + r + " as it's still in use");
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001608 }
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001609 }
1610 } else {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001611 if (VDBG) log("Removing " + r + " for interface " + ifaceName);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001612 try {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07001613 mNetd.removeSecondaryRoute(ifaceName, r);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001614 } catch (Exception e) {
1615 // never crash - catch them all
Robert Greenwalt436db352012-04-23 18:00:37 -07001616 if (VDBG) loge("Exception trying to remove a route: " + e);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001617 return false;
1618 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07001619 }
1620 }
1621 return true;
The Android Open Source Project28527d22009-03-03 19:31:44 -08001622 }
1623
1624 /**
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001625 * @see ConnectivityManager#getMobileDataEnabled()
1626 */
1627 public boolean getMobileDataEnabled() {
Wink Savilleb9024c62010-12-07 10:31:02 -08001628 // TODO: This detail should probably be in DataConnectionTracker's
1629 // which is where we store the value and maybe make this
1630 // asynchronous.
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001631 enforceAccessPermission();
Jeff Sharkey8b361572012-09-26 15:54:06 -07001632 boolean retVal = Settings.Global.getInt(mContext.getContentResolver(),
1633 Settings.Global.MOBILE_DATA, 1) == 1;
Robert Greenwalt78f28112011-08-02 17:18:41 -07001634 if (VDBG) log("getMobileDataEnabled returning " + retVal);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001635 return retVal;
1636 }
1637
Robert Greenwalt34848c02011-03-25 13:09:25 -07001638 public void setDataDependency(int networkType, boolean met) {
Robert Greenwalt6cac0742011-06-21 17:26:14 -07001639 enforceConnectivityInternalPermission();
1640
Robert Greenwalt34848c02011-03-25 13:09:25 -07001641 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET,
1642 (met ? ENABLED : DISABLED), networkType));
1643 }
1644
1645 private void handleSetDependencyMet(int networkType, boolean met) {
1646 if (mNetTrackers[networkType] != null) {
1647 if (DBG) {
1648 log("handleSetDependencyMet(" + networkType + ", " + met + ")");
1649 }
1650 mNetTrackers[networkType].setDependencyMet(met);
1651 }
1652 }
1653
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001654 private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
1655 @Override
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001656 public void onUidRulesChanged(int uid, int uidRules) {
Jeff Sharkeyb1b6ccd2012-02-07 12:05:43 -08001657 // caller is NPMS, since we only register with them
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001658 if (LOGD_RULES) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001659 log("onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001660 }
1661
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001662 synchronized (mRulesLock) {
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001663 // skip update when we've already applied rules
1664 final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL);
1665 if (oldRules == uidRules) return;
1666
1667 mUidRules.put(uid, uidRules);
1668 }
1669
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001670 // TODO: notify UID when it has requested targeted updates
1671 }
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001672
1673 @Override
1674 public void onMeteredIfacesChanged(String[] meteredIfaces) {
Jeff Sharkeyb1b6ccd2012-02-07 12:05:43 -08001675 // caller is NPMS, since we only register with them
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001676 if (LOGD_RULES) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001677 log("onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
Jeff Sharkeya47d7a12011-06-16 15:07:48 -07001678 }
1679
1680 synchronized (mRulesLock) {
1681 mMeteredIfaces.clear();
1682 for (String iface : meteredIfaces) {
1683 mMeteredIfaces.add(iface);
1684 }
1685 }
1686 }
Jeff Sharkeyb1b6ccd2012-02-07 12:05:43 -08001687
1688 @Override
1689 public void onRestrictBackgroundChanged(boolean restrictBackground) {
1690 // caller is NPMS, since we only register with them
1691 if (LOGD_RULES) {
1692 log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
1693 }
1694
1695 // kick off connectivity change broadcast for active network, since
1696 // global background policy change is radical.
1697 final int networkType = mActiveDefaultNetwork;
1698 if (isNetworkTypeValid(networkType)) {
1699 final NetworkStateTracker tracker = mNetTrackers[networkType];
1700 if (tracker != null) {
1701 final NetworkInfo info = tracker.getNetworkInfo();
1702 if (info != null && info.isConnected()) {
1703 sendConnectedBroadcast(info);
1704 }
1705 }
1706 }
1707 }
Jeff Sharkey921ebf22011-05-19 17:12:49 -07001708 };
1709
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001710 /**
1711 * @see ConnectivityManager#setMobileDataEnabled(boolean)
1712 */
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001713 public void setMobileDataEnabled(boolean enabled) {
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001714 enforceChangePermission();
Wink Savillee70c6f52010-12-03 12:01:38 -08001715 if (DBG) log("setMobileDataEnabled(" + enabled + ")");
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001716
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001717 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
Robert Greenwalt34848c02011-03-25 13:09:25 -07001718 (enabled ? ENABLED : DISABLED), 0));
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07001719 }
1720
1721 private void handleSetMobileData(boolean enabled) {
Wink Savilleb9024c62010-12-07 10:31:02 -08001722 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07001723 if (VDBG) {
1724 log(mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001725 }
Jeff Sharkey805662d2011-08-19 02:24:24 -07001726 mNetTrackers[ConnectivityManager.TYPE_MOBILE].setUserDataEnable(enabled);
1727 }
tk.mun5eee1042012-01-06 10:43:52 +09001728 if (mNetTrackers[ConnectivityManager.TYPE_WIMAX] != null) {
1729 if (VDBG) {
1730 log(mNetTrackers[ConnectivityManager.TYPE_WIMAX].toString() + enabled);
1731 }
1732 mNetTrackers[ConnectivityManager.TYPE_WIMAX].setUserDataEnable(enabled);
1733 }
Jeff Sharkey805662d2011-08-19 02:24:24 -07001734 }
1735
1736 @Override
1737 public void setPolicyDataEnable(int networkType, boolean enabled) {
1738 // only someone like NPMS should only be calling us
1739 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1740
1741 mHandler.sendMessage(mHandler.obtainMessage(
1742 EVENT_SET_POLICY_DATA_ENABLE, networkType, (enabled ? ENABLED : DISABLED)));
1743 }
1744
1745 private void handleSetPolicyDataEnable(int networkType, boolean enabled) {
1746 if (isNetworkTypeValid(networkType)) {
1747 final NetworkStateTracker tracker = mNetTrackers[networkType];
1748 if (tracker != null) {
1749 tracker.setPolicyDataEnable(enabled);
1750 }
Robert Greenwalt1b21f6c2010-02-23 18:58:05 -08001751 }
1752 }
1753
The Android Open Source Project28527d22009-03-03 19:31:44 -08001754 private void enforceAccessPermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001755 mContext.enforceCallingOrSelfPermission(
1756 android.Manifest.permission.ACCESS_NETWORK_STATE,
1757 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001758 }
1759
1760 private void enforceChangePermission() {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001761 mContext.enforceCallingOrSelfPermission(
1762 android.Manifest.permission.CHANGE_NETWORK_STATE,
1763 "ConnectivityService");
The Android Open Source Project28527d22009-03-03 19:31:44 -08001764 }
1765
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08001766 // TODO Make this a special check when it goes public
1767 private void enforceTetherChangePermission() {
1768 mContext.enforceCallingOrSelfPermission(
1769 android.Manifest.permission.CHANGE_NETWORK_STATE,
1770 "ConnectivityService");
1771 }
1772
Robert Greenwalt8e87f122010-02-11 18:18:40 -08001773 private void enforceTetherAccessPermission() {
1774 mContext.enforceCallingOrSelfPermission(
1775 android.Manifest.permission.ACCESS_NETWORK_STATE,
1776 "ConnectivityService");
1777 }
1778
Robert Greenwalt93dc1042010-06-15 12:19:37 -07001779 private void enforceConnectivityInternalPermission() {
1780 mContext.enforceCallingOrSelfPermission(
1781 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1782 "ConnectivityService");
1783 }
1784
Chad Brubaker11f22252013-07-11 13:29:30 -07001785 private void enforceMarkNetworkSocketPermission() {
1786 //Media server special case
1787 if (Binder.getCallingUid() == Process.MEDIA_UID) {
1788 return;
1789 }
1790 mContext.enforceCallingOrSelfPermission(
1791 android.Manifest.permission.MARK_NETWORK_SOCKET,
1792 "ConnectivityService");
1793 }
1794
The Android Open Source Project28527d22009-03-03 19:31:44 -08001795 /**
Robert Greenwalt0659da32009-07-16 17:21:39 -07001796 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
1797 * network, we ignore it. If it is for the active network, we send out a
1798 * broadcast. But first, we check whether it might be possible to connect
1799 * to a different network.
The Android Open Source Project28527d22009-03-03 19:31:44 -08001800 * @param info the {@code NetworkInfo} for the network
1801 */
1802 private void handleDisconnect(NetworkInfo info) {
1803
Robert Greenwalt2034b912009-08-12 16:08:25 -07001804 int prevNetType = info.getType();
The Android Open Source Project28527d22009-03-03 19:31:44 -08001805
Robert Greenwalt2034b912009-08-12 16:08:25 -07001806 mNetTrackers[prevNetType].setTeardownRequested(false);
Haoyu Baie2462442012-06-28 15:26:19 -07001807
1808 // Remove idletimer previously setup in {@code handleConnect}
1809 removeDataActivityTracking(prevNetType);
1810
The Android Open Source Project28527d22009-03-03 19:31:44 -08001811 /*
1812 * If the disconnected network is not the active one, then don't report
1813 * this as a loss of connectivity. What probably happened is that we're
1814 * getting the disconnect for a network that we explicitly disabled
1815 * in accordance with network preference policies.
1816 */
Robert Greenwalt34848c02011-03-25 13:09:25 -07001817 if (!mNetConfigs[prevNetType].isDefault()) {
Mattias Falkd697aa22011-08-23 14:15:13 +02001818 List<Integer> pids = mNetRequestersPids[prevNetType];
1819 for (Integer pid : pids) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001820 // will remove them because the net's no longer connected
1821 // need to do this now as only now do we know the pids and
1822 // can properly null things that are no longer referenced.
1823 reassessPidDns(pid.intValue(), false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001824 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001825 }
1826
The Android Open Source Project28527d22009-03-03 19:31:44 -08001827 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
Irfan Sheriff32bed2c2012-09-20 09:32:41 -07001828 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
Jeff Sharkey47905d12012-08-06 11:41:50 -07001829 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001830 if (info.isFailover()) {
1831 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1832 info.setFailover(false);
1833 }
1834 if (info.getReason() != null) {
1835 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1836 }
1837 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001838 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1839 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001840 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07001841
Robert Greenwalt34848c02011-03-25 13:09:25 -07001842 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001843 tryFailover(prevNetType);
1844 if (mActiveDefaultNetwork != -1) {
1845 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001846 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
1847 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001848 mDefaultInetConditionPublished = 0; // we're not connected anymore
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08001849 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
1850 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001851 }
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07001852 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001853
1854 // Reset interface if no other connections are using the same interface
1855 boolean doReset = true;
1856 LinkProperties linkProperties = mNetTrackers[prevNetType].getLinkProperties();
1857 if (linkProperties != null) {
1858 String oldIface = linkProperties.getInterfaceName();
1859 if (TextUtils.isEmpty(oldIface) == false) {
1860 for (NetworkStateTracker networkStateTracker : mNetTrackers) {
1861 if (networkStateTracker == null) continue;
1862 NetworkInfo networkInfo = networkStateTracker.getNetworkInfo();
1863 if (networkInfo.isConnected() && networkInfo.getType() != prevNetType) {
1864 LinkProperties l = networkStateTracker.getLinkProperties();
1865 if (l == null) continue;
1866 if (oldIface.equals(l.getInterfaceName())) {
1867 doReset = false;
1868 break;
1869 }
1870 }
1871 }
1872 }
1873 }
1874
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001875 // do this before we broadcast the change
Robert Greenwalt36ea8692011-06-15 12:22:07 -07001876 handleConnectivityChange(prevNetType, doReset);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001877
Jeff Sharkey971cd162011-08-29 16:02:57 -07001878 final Intent immediateIntent = new Intent(intent);
1879 immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
1880 sendStickyBroadcast(immediateIntent);
Wink Saville4f0de1e2011-08-04 15:01:58 -07001881 sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001882 /*
1883 * If the failover network is already connected, then immediately send
1884 * out a followup broadcast indicating successful failover
1885 */
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001886 if (mActiveDefaultNetwork != -1) {
Wink Saville4f0de1e2011-08-04 15:01:58 -07001887 sendConnectedBroadcastDelayed(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(),
1888 getConnectivityChangeDelay());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001889 }
1890 }
1891
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001892 private void tryFailover(int prevNetType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001893 /*
Robert Greenwalt92564852011-01-06 15:41:07 -08001894 * If this is a default network, check if other defaults are available.
1895 * Try to reconnect on all available and let them hash it out when
1896 * more than one connects.
Robert Greenwalt2034b912009-08-12 16:08:25 -07001897 */
Robert Greenwalt34848c02011-03-25 13:09:25 -07001898 if (mNetConfigs[prevNetType].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07001899 if (mActiveDefaultNetwork == prevNetType) {
1900 mActiveDefaultNetwork = -1;
1901 }
1902
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001903 // don't signal a reconnect for anything lower or equal priority than our
1904 // current connected default
1905 // TODO - don't filter by priority now - nice optimization but risky
1906// int currentPriority = -1;
1907// if (mActiveDefaultNetwork != -1) {
Robert Greenwalt34848c02011-03-25 13:09:25 -07001908// currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority;
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001909// }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08001910 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
Robert Greenwaltec05b3c2009-10-30 14:17:42 -07001911 if (checkType == prevNetType) continue;
Robert Greenwalt34848c02011-03-25 13:09:25 -07001912 if (mNetConfigs[checkType] == null) continue;
1913 if (!mNetConfigs[checkType].isDefault()) continue;
Robert Greenwaltbc026d02011-11-11 09:56:03 -08001914 if (mNetTrackers[checkType] == null) continue;
Wink Saville72a95b92011-01-26 15:43:49 -08001915
1916// Enabling the isAvailable() optimization caused mobile to not get
1917// selected if it was in the middle of error handling. Specifically
1918// a moble connection that took 30 seconds to complete the DEACTIVATE_DATA_CALL
1919// would not be available and we wouldn't get connected to anything.
1920// So removing the isAvailable() optimization below for now. TODO: This
1921// optimization should work and we need to investigate why it doesn't work.
1922// This could be related to how DEACTIVATE_DATA_CALL is reporting its
1923// complete before it is really complete.
1924// if (!mNetTrackers[checkType].isAvailable()) continue;
1925
Robert Greenwalt34848c02011-03-25 13:09:25 -07001926// if (currentPriority >= mNetConfigs[checkType].mPriority) continue;
Robert Greenwalt2034b912009-08-12 16:08:25 -07001927
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001928 NetworkStateTracker checkTracker = mNetTrackers[checkType];
1929 NetworkInfo checkInfo = checkTracker.getNetworkInfo();
1930 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
1931 checkInfo.setFailover(true);
1932 checkTracker.reconnect();
Robert Greenwalt2034b912009-08-12 16:08:25 -07001933 }
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08001934 if (DBG) log("Attempting to switch to " + checkInfo.getTypeName());
Robert Greenwalt2034b912009-08-12 16:08:25 -07001935 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001936 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08001937 }
1938
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07001939 public void sendConnectedBroadcast(NetworkInfo info) {
Robert Greenwaltfaa4b402013-02-15 10:56:35 -08001940 enforceConnectivityInternalPermission();
Jeff Sharkey971cd162011-08-29 16:02:57 -07001941 sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
1942 sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001943 }
1944
Wink Saville4f0de1e2011-08-04 15:01:58 -07001945 private void sendConnectedBroadcastDelayed(NetworkInfo info, int delayMs) {
Jeff Sharkey971cd162011-08-29 16:02:57 -07001946 sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE);
1947 sendGeneralBroadcastDelayed(info, CONNECTIVITY_ACTION, delayMs);
Wink Saville4f0de1e2011-08-04 15:01:58 -07001948 }
1949
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001950 private void sendInetConditionBroadcast(NetworkInfo info) {
1951 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
1952 }
1953
Wink Saville4f0de1e2011-08-04 15:01:58 -07001954 private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07001955 if (mLockdownTracker != null) {
1956 info = mLockdownTracker.augmentNetworkInfo(info);
1957 }
1958
Robert Greenwaltd3401f92010-09-15 17:36:33 -07001959 Intent intent = new Intent(bcastType);
Irfan Sheriff32bed2c2012-09-20 09:32:41 -07001960 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
Jeff Sharkey47905d12012-08-06 11:41:50 -07001961 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001962 if (info.isFailover()) {
1963 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
1964 info.setFailover(false);
1965 }
1966 if (info.getReason() != null) {
1967 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
1968 }
1969 if (info.getExtraInfo() != null) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07001970 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
1971 info.getExtraInfo());
The Android Open Source Project28527d22009-03-03 19:31:44 -08001972 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07001973 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Wink Saville4f0de1e2011-08-04 15:01:58 -07001974 return intent;
1975 }
1976
1977 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
1978 sendStickyBroadcast(makeGeneralIntent(info, bcastType));
1979 }
1980
1981 private void sendGeneralBroadcastDelayed(NetworkInfo info, String bcastType, int delayMs) {
1982 sendStickyBroadcastDelayed(makeGeneralIntent(info, bcastType), delayMs);
The Android Open Source Project28527d22009-03-03 19:31:44 -08001983 }
1984
Haoyu Baib5da5752012-06-20 14:29:57 -07001985 private void sendDataActivityBroadcast(int deviceType, boolean active) {
1986 Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE);
1987 intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType);
1988 intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active);
Dianne Hackborne588ca12012-09-04 18:48:37 -07001989 final long ident = Binder.clearCallingIdentity();
1990 try {
1991 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL,
1992 RECEIVE_DATA_ACTIVITY_CHANGE, null, null, 0, null, null);
1993 } finally {
1994 Binder.restoreCallingIdentity(ident);
1995 }
Haoyu Baib5da5752012-06-20 14:29:57 -07001996 }
1997
The Android Open Source Project28527d22009-03-03 19:31:44 -08001998 /**
1999 * Called when an attempt to fail over to another network has failed.
2000 * @param info the {@link NetworkInfo} for the failed network
2001 */
2002 private void handleConnectionFailure(NetworkInfo info) {
2003 mNetTrackers[info.getType()].setTeardownRequested(false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08002004
Robert Greenwalt2034b912009-08-12 16:08:25 -07002005 String reason = info.getReason();
2006 String extraInfo = info.getExtraInfo();
Robert Greenwalt0659da32009-07-16 17:21:39 -07002007
Robert Greenwalte981bc52010-10-08 16:35:52 -07002008 String reasonText;
2009 if (reason == null) {
2010 reasonText = ".";
2011 } else {
2012 reasonText = " (" + reason + ").";
The Android Open Source Project28527d22009-03-03 19:31:44 -08002013 }
Wink Savillee70c6f52010-12-03 12:01:38 -08002014 loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText);
Robert Greenwalt2034b912009-08-12 16:08:25 -07002015
2016 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
Irfan Sheriff32bed2c2012-09-20 09:32:41 -07002017 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, new NetworkInfo(info));
Jeff Sharkey47905d12012-08-06 11:41:50 -07002018 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
Robert Greenwalt2034b912009-08-12 16:08:25 -07002019 if (getActiveNetworkInfo() == null) {
2020 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
2021 }
2022 if (reason != null) {
2023 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
2024 }
2025 if (extraInfo != null) {
2026 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
2027 }
2028 if (info.isFailover()) {
2029 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
2030 info.setFailover(false);
2031 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08002032
Robert Greenwalt34848c02011-03-25 13:09:25 -07002033 if (mNetConfigs[info.getType()].isDefault()) {
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08002034 tryFailover(info.getType());
2035 if (mActiveDefaultNetwork != -1) {
2036 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08002037 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
2038 } else {
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07002039 mDefaultInetConditionPublished = 0;
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08002040 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
2041 }
Robert Greenwaltf55ced92010-01-20 19:29:41 -08002042 }
Robert Greenwalt3cc68d32010-01-25 17:54:29 -08002043
Robert Greenwaltb2a9e492010-09-20 18:01:43 -07002044 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
Jeff Sharkey971cd162011-08-29 16:02:57 -07002045
2046 final Intent immediateIntent = new Intent(intent);
2047 immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
2048 sendStickyBroadcast(immediateIntent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04002049 sendStickyBroadcast(intent);
Robert Greenwaltf55ced92010-01-20 19:29:41 -08002050 /*
2051 * If the failover network is already connected, then immediately send
2052 * out a followup broadcast indicating successful failover
2053 */
Robert Greenwalt4b7c55e2011-01-11 13:56:33 -08002054 if (mActiveDefaultNetwork != -1) {
2055 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
Robert Greenwaltf55ced92010-01-20 19:29:41 -08002056 }
Mike Lockwoodfde2b762009-08-14 14:18:49 -04002057 }
2058
2059 private void sendStickyBroadcast(Intent intent) {
2060 synchronized(this) {
Dianne Hackborna417ff82009-12-08 19:45:14 -08002061 if (!mSystemReady) {
2062 mInitialBroadcast = new Intent(intent);
Mike Lockwoodfde2b762009-08-14 14:18:49 -04002063 }
Dianne Hackborna417ff82009-12-08 19:45:14 -08002064 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Wink Savillea7d56572011-09-21 11:05:43 -07002065 if (VDBG) {
Jeff Sharkey971cd162011-08-29 16:02:57 -07002066 log("sendStickyBroadcast: action=" + intent.getAction());
Wink Saville4f0de1e2011-08-04 15:01:58 -07002067 }
2068
Dianne Hackborne588ca12012-09-04 18:48:37 -07002069 final long ident = Binder.clearCallingIdentity();
2070 try {
2071 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
2072 } finally {
2073 Binder.restoreCallingIdentity(ident);
2074 }
Mike Lockwoodfde2b762009-08-14 14:18:49 -04002075 }
2076 }
2077
Wink Saville4f0de1e2011-08-04 15:01:58 -07002078 private void sendStickyBroadcastDelayed(Intent intent, int delayMs) {
2079 if (delayMs <= 0) {
2080 sendStickyBroadcast(intent);
2081 } else {
Wink Savillea7d56572011-09-21 11:05:43 -07002082 if (VDBG) {
Jeff Sharkey971cd162011-08-29 16:02:57 -07002083 log("sendStickyBroadcastDelayed: delayMs=" + delayMs + ", action="
2084 + intent.getAction());
2085 }
Wink Saville4f0de1e2011-08-04 15:01:58 -07002086 mHandler.sendMessageDelayed(mHandler.obtainMessage(
2087 EVENT_SEND_STICKY_BROADCAST_INTENT, intent), delayMs);
2088 }
2089 }
2090
Mike Lockwoodfde2b762009-08-14 14:18:49 -04002091 void systemReady() {
2092 synchronized(this) {
2093 mSystemReady = true;
Dianne Hackborna417ff82009-12-08 19:45:14 -08002094 if (mInitialBroadcast != null) {
Dianne Hackborn22986892012-08-29 18:32:08 -07002095 mContext.sendStickyBroadcastAsUser(mInitialBroadcast, UserHandle.ALL);
Dianne Hackborna417ff82009-12-08 19:45:14 -08002096 mInitialBroadcast = null;
Mike Lockwoodfde2b762009-08-14 14:18:49 -04002097 }
2098 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002099 // load the global proxy at startup
2100 mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07002101
2102 // Try bringing up tracker, but if KeyStore isn't ready yet, wait
2103 // for user to unlock device.
2104 if (!updateLockdownVpn()) {
2105 final IntentFilter filter = new IntentFilter(Intent.ACTION_USER_PRESENT);
2106 mContext.registerReceiver(mUserPresentReceiver, filter);
2107 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002108 }
2109
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07002110 private BroadcastReceiver mUserPresentReceiver = new BroadcastReceiver() {
2111 @Override
2112 public void onReceive(Context context, Intent intent) {
2113 // Try creating lockdown tracker, since user present usually means
2114 // unlocked keystore.
2115 if (updateLockdownVpn()) {
2116 mContext.unregisterReceiver(this);
2117 }
2118 }
2119 };
2120
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002121 private boolean isNewNetTypePreferredOverCurrentNetType(int type) {
2122 if ((type != mNetworkPreference &&
2123 mNetConfigs[mActiveDefaultNetwork].priority >
2124 mNetConfigs[type].priority) ||
2125 mNetworkPreference == mActiveDefaultNetwork) return false;
2126 return true;
2127 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002128
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002129 private void handleConnect(NetworkInfo info) {
2130 final int newNetType = info.getType();
2131
2132 setupDataActivityTracking(newNetType);
Haoyu Baie2462442012-06-28 15:26:19 -07002133
The Android Open Source Project28527d22009-03-03 19:31:44 -08002134 // snapshot isFailover, because sendConnectedBroadcast() resets it
2135 boolean isFailover = info.isFailover();
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002136 final NetworkStateTracker thisNet = mNetTrackers[newNetType];
Jeff Sharkey6b9021d2012-07-26 18:32:30 -07002137 final String thisIface = thisNet.getLinkProperties().getInterfaceName();
The Android Open Source Project28527d22009-03-03 19:31:44 -08002138
Robert Greenwalt2034b912009-08-12 16:08:25 -07002139 // if this is a default net and other default is running
2140 // kill the one not preferred
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002141 if (mNetConfigs[newNetType].isDefault()) {
2142 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != newNetType) {
2143 if (isNewNetTypePreferredOverCurrentNetType(newNetType)) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07002144 // tear down the other
2145 NetworkStateTracker otherNet =
2146 mNetTrackers[mActiveDefaultNetwork];
Wink Savillee70c6f52010-12-03 12:01:38 -08002147 if (DBG) {
2148 log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
Robert Greenwalt2034b912009-08-12 16:08:25 -07002149 " teardown");
Wink Savillee70c6f52010-12-03 12:01:38 -08002150 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07002151 if (!teardown(otherNet)) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002152 loge("Network declined teardown request");
Robert Greenwalt99910172011-03-29 11:36:28 -07002153 teardown(thisNet);
Robert Greenwalt2034b912009-08-12 16:08:25 -07002154 return;
2155 }
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002156 } else {
2157 // don't accept this one
2158 if (VDBG) {
2159 log("Not broadcasting CONNECT_ACTION " +
2160 "to torn down network " + info.getTypeName());
2161 }
2162 teardown(thisNet);
2163 return;
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002164 }
2165 }
2166 synchronized (ConnectivityService.this) {
2167 // have a new default network, release the transition wakelock in a second
2168 // if it's held. The second pause is to allow apps to reconnect over the
2169 // new network
2170 if (mNetTransitionWakeLock.isHeld()) {
2171 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltccb36f92010-09-24 14:32:21 -07002172 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002173 mNetTransitionWakeLockSerialNumber, 0),
2174 1000);
Robert Greenwalt2034b912009-08-12 16:08:25 -07002175 }
2176 }
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002177 mActiveDefaultNetwork = newNetType;
Robert Greenwalt986c7412010-09-08 15:24:47 -07002178 // this will cause us to come up initially as unconnected and switching
2179 // to connected after our normal pause unless somebody reports us as reall
2180 // disconnected
2181 mDefaultInetConditionPublished = 0;
2182 mDefaultConnectionSequence++;
2183 mInetConditionChangeInFlight = false;
2184 // Don't do this - if we never sign in stay, grey
2185 //reportNetworkCondition(mActiveDefaultNetwork, 100);
Robert Greenwalt2034b912009-08-12 16:08:25 -07002186 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002187 thisNet.setTeardownRequested(false);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002188 updateNetworkSettings(thisNet);
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002189 handleConnectivityChange(newNetType, false);
Wink Saville4f0de1e2011-08-04 15:01:58 -07002190 sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
Jeff Sharkeyaac2c502011-10-04 16:54:49 -07002191
2192 // notify battery stats service about this network
Jeff Sharkey6b9021d2012-07-26 18:32:30 -07002193 if (thisIface != null) {
Jeff Sharkeyaac2c502011-10-04 16:54:49 -07002194 try {
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002195 BatteryStatsService.getService().noteNetworkInterfaceType(thisIface, newNetType);
Jeff Sharkeyaac2c502011-10-04 16:54:49 -07002196 } catch (RemoteException e) {
2197 // ignored; service lives in system_server
2198 }
2199 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002200 }
2201
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002202 private void handleCaptivePortalTrackerCheck(NetworkInfo info) {
2203 if (DBG) log("Captive portal check " + info);
2204 int type = info.getType();
2205 final NetworkStateTracker thisNet = mNetTrackers[type];
2206 if (mNetConfigs[type].isDefault()) {
2207 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
2208 if (isNewNetTypePreferredOverCurrentNetType(type)) {
2209 if (DBG) log("Captive check on " + info.getTypeName());
Irfan Sheriff32bed2c2012-09-20 09:32:41 -07002210 mCaptivePortalTracker.detectCaptivePortal(new NetworkInfo(info));
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002211 return;
2212 } else {
2213 if (DBG) log("Tear down low priority net " + info.getTypeName());
2214 teardown(thisNet);
2215 return;
2216 }
2217 }
2218 }
2219
2220 thisNet.captivePortalCheckComplete();
2221 }
2222
2223 /** @hide */
2224 public void captivePortalCheckComplete(NetworkInfo info) {
Robert Greenwaltfaa4b402013-02-15 10:56:35 -08002225 enforceConnectivityInternalPermission();
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002226 mNetTrackers[info.getType()].captivePortalCheckComplete();
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002227 }
2228
The Android Open Source Project28527d22009-03-03 19:31:44 -08002229 /**
Haoyu Baie2462442012-06-28 15:26:19 -07002230 * Setup data activity tracking for the given network interface.
2231 *
2232 * Every {@code setupDataActivityTracking} should be paired with a
2233 * {@link removeDataActivityTracking} for cleanup.
2234 */
2235 private void setupDataActivityTracking(int type) {
2236 final NetworkStateTracker thisNet = mNetTrackers[type];
2237 final String iface = thisNet.getLinkProperties().getInterfaceName();
2238
2239 final int timeout;
2240
2241 if (ConnectivityManager.isNetworkTypeMobile(type)) {
Jeff Brownc67cf562012-09-25 15:03:20 -07002242 timeout = Settings.Global.getInt(mContext.getContentResolver(),
2243 Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE,
Haoyu Baie2462442012-06-28 15:26:19 -07002244 0);
2245 // Canonicalize mobile network type
2246 type = ConnectivityManager.TYPE_MOBILE;
2247 } else if (ConnectivityManager.TYPE_WIFI == type) {
Jeff Brownc67cf562012-09-25 15:03:20 -07002248 timeout = Settings.Global.getInt(mContext.getContentResolver(),
2249 Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
Haoyu Baie2462442012-06-28 15:26:19 -07002250 0);
2251 } else {
2252 // do not track any other networks
2253 timeout = 0;
2254 }
2255
2256 if (timeout > 0 && iface != null) {
2257 try {
2258 mNetd.addIdleTimer(iface, timeout, Integer.toString(type));
2259 } catch (RemoteException e) {
2260 }
2261 }
2262 }
2263
2264 /**
2265 * Remove data activity tracking when network disconnects.
2266 */
2267 private void removeDataActivityTracking(int type) {
2268 final NetworkStateTracker net = mNetTrackers[type];
2269 final String iface = net.getLinkProperties().getInterfaceName();
2270
2271 if (iface != null && (ConnectivityManager.isNetworkTypeMobile(type) ||
2272 ConnectivityManager.TYPE_WIFI == type)) {
2273 try {
2274 // the call fails silently if no idletimer setup for this interface
2275 mNetd.removeIdleTimer(iface);
2276 } catch (RemoteException e) {
2277 }
2278 }
2279 }
2280
2281 /**
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002282 * After a change in the connectivity state of a network. We're mainly
2283 * concerned with making sure that the list of DNS servers is set up
2284 * according to which networks are connected, and ensuring that the
2285 * right routing table entries exist.
The Android Open Source Project28527d22009-03-03 19:31:44 -08002286 */
Robert Greenwalt36ea8692011-06-15 12:22:07 -07002287 private void handleConnectivityChange(int netType, boolean doReset) {
Wink Saville051a6642011-07-13 13:44:13 -07002288 int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0;
Chad Brubaker49db4222013-07-15 16:34:04 -07002289 boolean exempt = ConnectivityManager.isNetworkTypeExempt(netType);
Wink Saville051a6642011-07-13 13:44:13 -07002290
The Android Open Source Project28527d22009-03-03 19:31:44 -08002291 /*
Robert Greenwalt2034b912009-08-12 16:08:25 -07002292 * If a non-default network is enabled, add the host routes that
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002293 * will allow it's DNS servers to be accessed.
The Android Open Source Project28527d22009-03-03 19:31:44 -08002294 */
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002295 handleDnsConfigurationChange(netType);
Robert Greenwalt2034b912009-08-12 16:08:25 -07002296
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002297 LinkProperties curLp = mCurrentLinkProperties[netType];
2298 LinkProperties newLp = null;
2299
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002300 if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002301 newLp = mNetTrackers[netType].getLinkProperties();
Wink Saville051a6642011-07-13 13:44:13 -07002302 if (VDBG) {
2303 log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
2304 " doReset=" + doReset + " resetMask=" + resetMask +
2305 "\n curLp=" + curLp +
2306 "\n newLp=" + newLp);
2307 }
2308
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002309 if (curLp != null) {
2310 if (curLp.isIdenticalInterfaceName(newLp)) {
2311 CompareResult<LinkAddress> car = curLp.compareAddresses(newLp);
2312 if ((car.removed.size() != 0) || (car.added.size() != 0)) {
2313 for (LinkAddress linkAddr : car.removed) {
2314 if (linkAddr.getAddress() instanceof Inet4Address) {
2315 resetMask |= NetworkUtils.RESET_IPV4_ADDRESSES;
2316 }
2317 if (linkAddr.getAddress() instanceof Inet6Address) {
2318 resetMask |= NetworkUtils.RESET_IPV6_ADDRESSES;
2319 }
Wink Saville051a6642011-07-13 13:44:13 -07002320 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002321 if (DBG) {
2322 log("handleConnectivityChange: addresses changed" +
2323 " linkProperty[" + netType + "]:" + " resetMask=" + resetMask +
2324 "\n car=" + car);
Wink Saville051a6642011-07-13 13:44:13 -07002325 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002326 } else {
2327 if (DBG) {
2328 log("handleConnectivityChange: address are the same reset per doReset" +
2329 " linkProperty[" + netType + "]:" +
2330 " resetMask=" + resetMask);
2331 }
Wink Saville051a6642011-07-13 13:44:13 -07002332 }
2333 } else {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002334 resetMask = NetworkUtils.RESET_ALL_ADDRESSES;
Robert Greenwalt78f28112011-08-02 17:18:41 -07002335 if (DBG) {
2336 log("handleConnectivityChange: interface not not equivalent reset both" +
2337 " linkProperty[" + netType + "]:" +
2338 " resetMask=" + resetMask);
2339 }
Wink Saville051a6642011-07-13 13:44:13 -07002340 }
Wink Saville051a6642011-07-13 13:44:13 -07002341 }
Robert Greenwalt34848c02011-03-25 13:09:25 -07002342 if (mNetConfigs[netType].isDefault()) {
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07002343 handleApplyDefaultProxy(newLp.getHttpProxy());
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002344 }
2345 } else {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002346 if (VDBG) {
2347 log("handleConnectivityChange: changed linkProperty[" + netType + "]:" +
2348 " doReset=" + doReset + " resetMask=" + resetMask +
2349 "\n curLp=" + curLp +
2350 "\n newLp= null");
Robert Greenwalt2034b912009-08-12 16:08:25 -07002351 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002352 }
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002353 mCurrentLinkProperties[netType] = newLp;
Chad Brubaker49db4222013-07-15 16:34:04 -07002354 boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault(), exempt);
Robert Greenwalt36ea8692011-06-15 12:22:07 -07002355
Chia-chi Yeh4a243f52011-08-15 15:19:40 -07002356 if (resetMask != 0 || resetDns) {
Robert Greenwalt4398f342013-05-23 18:33:06 -07002357 if (curLp != null) {
2358 for (String iface : curLp.getAllInterfaceNames()) {
Lorenzo Colitti63839822013-03-20 19:22:58 +09002359 if (TextUtils.isEmpty(iface) == false) {
2360 if (resetMask != 0) {
2361 if (DBG) log("resetConnections(" + iface + ", " + resetMask + ")");
2362 NetworkUtils.resetConnections(iface, resetMask);
Chia-chi Yeh4a243f52011-08-15 15:19:40 -07002363
Lorenzo Colitti63839822013-03-20 19:22:58 +09002364 // Tell VPN the interface is down. It is a temporary
2365 // but effective fix to make VPN aware of the change.
2366 if ((resetMask & NetworkUtils.RESET_IPV4_ADDRESSES) != 0) {
Chad Brubakerb7652cd2013-06-14 11:16:51 -07002367 synchronized(mVpns) {
2368 for (int i = 0; i < mVpns.size(); i++) {
2369 mVpns.valueAt(i).interfaceStatusChanged(iface, false);
2370 }
2371 }
Lorenzo Colitti63839822013-03-20 19:22:58 +09002372 }
Chia-chi Yeh4a243f52011-08-15 15:19:40 -07002373 }
Lorenzo Colitti63839822013-03-20 19:22:58 +09002374 if (resetDns) {
2375 flushVmDnsCache();
2376 if (VDBG) log("resetting DNS cache for " + iface);
2377 try {
2378 mNetd.flushInterfaceDnsCache(iface);
2379 } catch (Exception e) {
2380 // never crash - catch them all
2381 if (DBG) loge("Exception resetting dns cache: " + e);
2382 }
Robert Greenwalt8d777252011-08-15 12:31:55 -07002383 }
Robert Greenwalt4398f342013-05-23 18:33:06 -07002384 } else {
2385 loge("Can't reset connection for type "+netType);
Robert Greenwalt8d777252011-08-15 12:31:55 -07002386 }
Robert Greenwalt36ea8692011-06-15 12:22:07 -07002387 }
2388 }
2389 }
Kazuhiro Ondo07680062011-06-22 21:10:34 -05002390
Lorenzo Colitti7a9d7972013-03-15 04:22:37 +09002391 // Update 464xlat state.
Lorenzo Colitti7a9d7972013-03-15 04:22:37 +09002392 NetworkStateTracker tracker = mNetTrackers[netType];
2393 if (mClat.requiresClat(netType, tracker)) {
Lorenzo Colitti4118d082013-03-28 14:13:43 +09002394 // If the connection was previously using clat, but is not using it now, stop the clat
2395 // daemon. Normally, this happens automatically when the connection disconnects, but if
2396 // the disconnect is not reported, or if the connection's LinkProperties changed for
2397 // some other reason (e.g., handoff changes the IP addresses on the link), it would
2398 // still be running. If it's not running, then stopping it is a no-op.
2399 if (Nat464Xlat.isRunningClat(curLp) && !Nat464Xlat.isRunningClat(newLp)) {
2400 mClat.stopClat();
2401 }
2402 // If the link requires clat to be running, then start the daemon now.
Lorenzo Colitti7a9d7972013-03-15 04:22:37 +09002403 if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
2404 mClat.startClat(tracker);
2405 } else {
2406 mClat.stopClat();
2407 }
2408 }
2409
Kazuhiro Ondo07680062011-06-22 21:10:34 -05002410 // TODO: Temporary notifying upstread change to Tethering.
2411 // @see bug/4455071
2412 /** Notify TetheringService if interface name has been changed. */
2413 if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
Wink Saville64e3f782012-07-10 12:37:54 -07002414 PhoneConstants.REASON_LINK_PROPERTIES_CHANGED)) {
Kazuhiro Ondo07680062011-06-22 21:10:34 -05002415 if (isTetheringSupported()) {
2416 mTethering.handleTetherIfaceChange();
2417 }
2418 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002419 }
2420
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002421 /**
2422 * Add and remove routes using the old properties (null if not previously connected),
2423 * new properties (null if becoming disconnected). May even be double null, which
2424 * is a noop.
2425 * Uses isLinkDefault to determine if default routes should be set or conversely if
2426 * host routes should be set to the dns servers
Robert Greenwalt8d777252011-08-15 12:31:55 -07002427 * returns a boolean indicating the routes changed
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002428 */
Robert Greenwalt8d777252011-08-15 12:31:55 -07002429 private boolean updateRoutes(LinkProperties newLp, LinkProperties curLp,
Chad Brubaker49db4222013-07-15 16:34:04 -07002430 boolean isLinkDefault, boolean exempt) {
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002431 Collection<RouteInfo> routesToAdd = null;
Robert Greenwalt98107422011-07-22 11:55:33 -07002432 CompareResult<InetAddress> dnsDiff = new CompareResult<InetAddress>();
2433 CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>();
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002434 if (curLp != null) {
2435 // check for the delta between the current set and the new
Lorenzo Colittie1b47422013-07-31 23:23:21 +09002436 routeDiff = curLp.compareAllRoutes(newLp);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002437 dnsDiff = curLp.compareDnses(newLp);
Robert Greenwalt98107422011-07-22 11:55:33 -07002438 } else if (newLp != null) {
Lorenzo Colittie43b6c42013-03-15 13:58:38 +09002439 routeDiff.added = newLp.getAllRoutes();
Robert Greenwalt98107422011-07-22 11:55:33 -07002440 dnsDiff.added = newLp.getDnses();
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002441 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002442
Robert Greenwalt8d777252011-08-15 12:31:55 -07002443 boolean routesChanged = (routeDiff.removed.size() != 0 || routeDiff.added.size() != 0);
2444
Robert Greenwalt98107422011-07-22 11:55:33 -07002445 for (RouteInfo r : routeDiff.removed) {
2446 if (isLinkDefault || ! r.isDefaultRoute()) {
Robert Greenwalt49c75d32011-11-02 14:37:19 -07002447 removeRoute(curLp, r, TO_DEFAULT_TABLE);
2448 }
2449 if (isLinkDefault == false) {
2450 // remove from a secondary route table
2451 removeRoute(curLp, r, TO_SECONDARY_TABLE);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002452 }
Robert Greenwalt98107422011-07-22 11:55:33 -07002453 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002454
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -07002455 if (!isLinkDefault) {
2456 // handle DNS routes
Robert Greenwalt8d777252011-08-15 12:31:55 -07002457 if (routesChanged) {
Robert Greenwalt98107422011-07-22 11:55:33 -07002458 // routes changed - remove all old dns entries and add new
2459 if (curLp != null) {
2460 for (InetAddress oldDns : curLp.getDnses()) {
2461 removeRouteToAddress(curLp, oldDns);
2462 }
2463 }
2464 if (newLp != null) {
2465 for (InetAddress newDns : newLp.getDnses()) {
Chad Brubaker49db4222013-07-15 16:34:04 -07002466 addRouteToAddress(newLp, newDns, exempt);
Robert Greenwalt98107422011-07-22 11:55:33 -07002467 }
Robert Greenwalt03d53da2011-03-22 18:47:42 -07002468 }
Robert Greenwalt8d777252011-08-15 12:31:55 -07002469 } else {
2470 // no change in routes, check for change in dns themselves
2471 for (InetAddress oldDns : dnsDiff.removed) {
2472 removeRouteToAddress(curLp, oldDns);
2473 }
2474 for (InetAddress newDns : dnsDiff.added) {
Chad Brubaker49db4222013-07-15 16:34:04 -07002475 addRouteToAddress(newLp, newDns, exempt);
Robert Greenwalt8d777252011-08-15 12:31:55 -07002476 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002477 }
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002478 }
Robert Greenwalt6bd85ba2013-04-05 16:49:32 -07002479
2480 for (RouteInfo r : routeDiff.added) {
2481 if (isLinkDefault || ! r.isDefaultRoute()) {
Chad Brubaker49db4222013-07-15 16:34:04 -07002482 addRoute(newLp, r, TO_DEFAULT_TABLE, exempt);
Robert Greenwalt6bd85ba2013-04-05 16:49:32 -07002483 } else {
2484 // add to a secondary route table
Chad Brubaker49db4222013-07-15 16:34:04 -07002485 addRoute(newLp, r, TO_SECONDARY_TABLE, UNEXEMPT);
Robert Greenwalt6bd85ba2013-04-05 16:49:32 -07002486
2487 // many radios add a default route even when we don't want one.
2488 // remove the default route unless somebody else has asked for it
2489 String ifaceName = newLp.getInterfaceName();
Chad Brubaker49db4222013-07-15 16:34:04 -07002490 synchronized (mRoutesLock) {
2491 if (!TextUtils.isEmpty(ifaceName) && !mAddedRoutes.contains(r)) {
2492 if (VDBG) log("Removing " + r + " for interface " + ifaceName);
2493 try {
2494 mNetd.removeRoute(ifaceName, r);
2495 } catch (Exception e) {
2496 // never crash - catch them all
2497 if (DBG) loge("Exception trying to remove a route: " + e);
2498 }
Robert Greenwalt6bd85ba2013-04-05 16:49:32 -07002499 }
2500 }
2501 }
2502 }
2503
Robert Greenwalt8d777252011-08-15 12:31:55 -07002504 return routesChanged;
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002505 }
2506
2507
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002508 /**
2509 * Reads the network specific TCP buffer sizes from SystemProperties
2510 * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
2511 * wide use
2512 */
Robert Greenwaltfaa4b402013-02-15 10:56:35 -08002513 private void updateNetworkSettings(NetworkStateTracker nt) {
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002514 String key = nt.getTcpBufferSizesPropName();
Jeff Sharkey366e0b72012-08-04 15:24:58 -07002515 String bufferSizes = key == null ? null : SystemProperties.get(key);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002516
Jeff Sharkey366e0b72012-08-04 15:24:58 -07002517 if (TextUtils.isEmpty(bufferSizes)) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002518 if (VDBG) log(key + " not found in system properties. Using defaults");
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002519
2520 // Setting to default values so we won't be stuck to previous values
2521 key = "net.tcp.buffersize.default";
2522 bufferSizes = SystemProperties.get(key);
2523 }
2524
2525 // Set values in kernel
2526 if (bufferSizes.length() != 0) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07002527 if (VDBG) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002528 log("Setting TCP values: [" + bufferSizes
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002529 + "] which comes from [" + key + "]");
2530 }
2531 setBufferSize(bufferSizes);
2532 }
2533 }
2534
2535 /**
2536 * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max]
2537 * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem
2538 *
2539 * @param bufferSizes in the format of "readMin, readInitial, readMax,
2540 * writeMin, writeInitial, writeMax"
2541 */
2542 private void setBufferSize(String bufferSizes) {
2543 try {
2544 String[] values = bufferSizes.split(",");
2545
2546 if (values.length == 6) {
2547 final String prefix = "/sys/kernel/ipv4/tcp_";
Mike Lockwood0d5916c2011-05-28 13:24:04 -04002548 FileUtils.stringToFile(prefix + "rmem_min", values[0]);
2549 FileUtils.stringToFile(prefix + "rmem_def", values[1]);
2550 FileUtils.stringToFile(prefix + "rmem_max", values[2]);
2551 FileUtils.stringToFile(prefix + "wmem_min", values[3]);
2552 FileUtils.stringToFile(prefix + "wmem_def", values[4]);
2553 FileUtils.stringToFile(prefix + "wmem_max", values[5]);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002554 } else {
Wink Savillee70c6f52010-12-03 12:01:38 -08002555 loge("Invalid buffersize string: " + bufferSizes);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002556 }
2557 } catch (IOException e) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002558 loge("Can't set tcp buffer sizes:" + e);
Irfan Sheriff7f132d92010-06-09 15:39:36 -07002559 }
2560 }
2561
Robert Greenwalt2034b912009-08-12 16:08:25 -07002562 /**
2563 * Adjust the per-process dns entries (net.dns<x>.<pid>) based
2564 * on the highest priority active net which this process requested.
2565 * If there aren't any, clear it out
2566 */
Mattias Falkd697aa22011-08-23 14:15:13 +02002567 private void reassessPidDns(int pid, boolean doBump)
Robert Greenwalt2034b912009-08-12 16:08:25 -07002568 {
Mattias Falkd697aa22011-08-23 14:15:13 +02002569 if (VDBG) log("reassessPidDns for pid " + pid);
2570 Integer myPid = new Integer(pid);
Robert Greenwalt2034b912009-08-12 16:08:25 -07002571 for(int i : mPriorityList) {
Robert Greenwalt34848c02011-03-25 13:09:25 -07002572 if (mNetConfigs[i].isDefault()) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07002573 continue;
2574 }
2575 NetworkStateTracker nt = mNetTrackers[i];
Robert Greenwalt0659da32009-07-16 17:21:39 -07002576 if (nt.getNetworkInfo().isConnected() &&
2577 !nt.isTeardownRequested()) {
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07002578 LinkProperties p = nt.getLinkProperties();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07002579 if (p == null) continue;
Mattias Falkd697aa22011-08-23 14:15:13 +02002580 if (mNetRequestersPids[i].contains(myPid)) {
2581 try {
2582 mNetd.setDnsInterfaceForPid(p.getInterfaceName(), pid);
2583 } catch (Exception e) {
2584 Slog.e(TAG, "exception reasseses pid dns: " + e);
Robert Greenwalt2034b912009-08-12 16:08:25 -07002585 }
Mattias Falkd697aa22011-08-23 14:15:13 +02002586 return;
Robert Greenwalt2034b912009-08-12 16:08:25 -07002587 }
2588 }
2589 }
2590 // nothing found - delete
Mattias Falkd697aa22011-08-23 14:15:13 +02002591 try {
2592 mNetd.clearDnsInterfaceForPid(pid);
2593 } catch (Exception e) {
2594 Slog.e(TAG, "exception clear interface from pid: " + e);
Robert Greenwalt2034b912009-08-12 16:08:25 -07002595 }
2596 }
2597
Mattias Falkd697aa22011-08-23 14:15:13 +02002598 private void flushVmDnsCache() {
Robert Greenwalt051642b2010-11-02 14:08:23 -07002599 /*
2600 * Tell the VMs to toss their DNS caches
2601 */
2602 Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
2603 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Stan Chesnuttf444f502011-01-05 17:14:03 -08002604 /*
2605 * Connectivity events can happen before boot has completed ...
2606 */
2607 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackborne588ca12012-09-04 18:48:37 -07002608 final long ident = Binder.clearCallingIdentity();
2609 try {
2610 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2611 } finally {
2612 Binder.restoreCallingIdentity(ident);
2613 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07002614 }
2615
Chia-chi Yehcc844502011-07-14 18:01:57 -07002616 // Caller must grab mDnsLock.
Mattias Falkd697aa22011-08-23 14:15:13 +02002617 private void updateDnsLocked(String network, String iface,
Chad Brubaker73652d02013-07-23 17:13:36 -07002618 Collection<InetAddress> dnses, String domains, boolean defaultDns) {
Chia-chi Yehcc844502011-07-14 18:01:57 -07002619 int last = 0;
2620 if (dnses.size() == 0 && mDefaultDns != null) {
Mattias Falkd697aa22011-08-23 14:15:13 +02002621 dnses = new ArrayList();
2622 dnses.add(mDefaultDns);
2623 if (DBG) {
2624 loge("no dns provided for " + network + " - using " + mDefaultDns.getHostAddress());
Robert Greenwaltd3aec302013-01-19 00:34:07 +00002625 }
Robert Greenwaltd3aec302013-01-19 00:34:07 +00002626 }
2627
Mattias Falkd697aa22011-08-23 14:15:13 +02002628 try {
2629 mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses), domains);
Chad Brubaker73652d02013-07-23 17:13:36 -07002630 if (defaultDns) {
2631 mNetd.setDefaultInterfaceForDns(iface);
2632 }
2633
Robert Greenwalte41e3b32013-02-11 15:25:10 -08002634 for (InetAddress dns : dnses) {
2635 ++last;
2636 String key = "net.dns" + last;
2637 String value = dns.getHostAddress();
2638 SystemProperties.set(key, value);
2639 }
2640 for (int i = last + 1; i <= mNumDnsEntries; ++i) {
2641 String key = "net.dns" + i;
2642 SystemProperties.set(key, "");
2643 }
2644 mNumDnsEntries = last;
Mattias Falkd697aa22011-08-23 14:15:13 +02002645 } catch (Exception e) {
2646 if (DBG) loge("exception setting default dns interface: " + e);
Robert Greenwaltd3aec302013-01-19 00:34:07 +00002647 }
Chia-chi Yehcc844502011-07-14 18:01:57 -07002648 }
2649
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002650 private void handleDnsConfigurationChange(int netType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07002651 // add default net's dns entries
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002652 NetworkStateTracker nt = mNetTrackers[netType];
2653 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07002654 LinkProperties p = nt.getLinkProperties();
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002655 if (p == null) return;
2656 Collection<InetAddress> dnses = p.getDnses();
Robert Greenwalt34848c02011-03-25 13:09:25 -07002657 if (mNetConfigs[netType].isDefault()) {
Chia-chi Yehcc844502011-07-14 18:01:57 -07002658 String network = nt.getNetworkInfo().getTypeName();
2659 synchronized (mDnsLock) {
Chad Brubaker5fdc1462013-07-23 17:44:41 -07002660 updateDnsLocked(network, p.getInterfaceName(), dnses, p.getDomains(), true);
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002661 }
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002662 } else {
Robert Greenwaltfce71862011-07-25 16:06:25 -07002663 try {
Robert Greenwalt49f762e2011-07-27 10:00:36 -07002664 mNetd.setDnsServersForInterface(p.getInterfaceName(),
Robert Greenwaltcd277852012-11-09 10:52:27 -08002665 NetworkUtils.makeStrings(dnses), p.getDomains());
Robert Greenwaltfce71862011-07-25 16:06:25 -07002666 } catch (Exception e) {
Robert Greenwalt7fa3bdb2011-12-13 15:26:02 -08002667 if (DBG) loge("exception setting dns servers: " + e);
Robert Greenwaltfce71862011-07-25 16:06:25 -07002668 }
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002669 // set per-pid dns for attached secondary nets
Mattias Falkd697aa22011-08-23 14:15:13 +02002670 List<Integer> pids = mNetRequestersPids[netType];
2671 for (Integer pid : pids) {
2672 try {
2673 mNetd.setDnsInterfaceForPid(p.getInterfaceName(), pid);
2674 } catch (Exception e) {
2675 Slog.e(TAG, "exception setting interface for pid: " + e);
2676 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002677 }
2678 }
Mattias Falkd697aa22011-08-23 14:15:13 +02002679 flushVmDnsCache();
The Android Open Source Project28527d22009-03-03 19:31:44 -08002680 }
Robert Greenwalt2034b912009-08-12 16:08:25 -07002681 }
2682
Robert Greenwalt20f819c2011-05-03 19:02:44 -07002683 private int getRestoreDefaultNetworkDelay(int networkType) {
Robert Greenwalt2034b912009-08-12 16:08:25 -07002684 String restoreDefaultNetworkDelayStr = SystemProperties.get(
2685 NETWORK_RESTORE_DELAY_PROP_NAME);
2686 if(restoreDefaultNetworkDelayStr != null &&
2687 restoreDefaultNetworkDelayStr.length() != 0) {
2688 try {
2689 return Integer.valueOf(restoreDefaultNetworkDelayStr);
2690 } catch (NumberFormatException e) {
2691 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002692 }
Robert Greenwalt20f819c2011-05-03 19:02:44 -07002693 // if the system property isn't set, use the value for the apn type
2694 int ret = RESTORE_DEFAULT_NETWORK_DELAY;
2695
2696 if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
2697 (mNetConfigs[networkType] != null)) {
2698 ret = mNetConfigs[networkType].restoreTime;
2699 }
2700 return ret;
The Android Open Source Project28527d22009-03-03 19:31:44 -08002701 }
2702
2703 @Override
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002704 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
2705 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
Robert Greenwalt0659da32009-07-16 17:21:39 -07002706 if (mContext.checkCallingOrSelfPermission(
2707 android.Manifest.permission.DUMP)
The Android Open Source Project28527d22009-03-03 19:31:44 -08002708 != PackageManager.PERMISSION_GRANTED) {
Robert Greenwalt0659da32009-07-16 17:21:39 -07002709 pw.println("Permission Denial: can't dump ConnectivityService " +
2710 "from from pid=" + Binder.getCallingPid() + ", uid=" +
2711 Binder.getCallingUid());
The Android Open Source Project28527d22009-03-03 19:31:44 -08002712 return;
2713 }
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002714
2715 // TODO: add locking to get atomic snapshot
The Android Open Source Project28527d22009-03-03 19:31:44 -08002716 pw.println();
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002717 for (int i = 0; i < mNetTrackers.length; i++) {
2718 final NetworkStateTracker nst = mNetTrackers[i];
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002719 if (nst != null) {
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002720 pw.println("NetworkStateTracker for " + getNetworkTypeName(i) + ":");
2721 pw.increaseIndent();
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002722 if (nst.getNetworkInfo().isConnected()) {
2723 pw.println("Active network: " + nst.getNetworkInfo().
2724 getTypeName());
2725 }
2726 pw.println(nst.getNetworkInfo());
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002727 pw.println(nst.getLinkProperties());
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002728 pw.println(nst);
2729 pw.println();
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002730 pw.decreaseIndent();
Robert Greenwalt2034b912009-08-12 16:08:25 -07002731 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002732 }
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002733
2734 pw.println("Network Requester Pids:");
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002735 pw.increaseIndent();
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002736 for (int net : mPriorityList) {
2737 String pidString = net + ": ";
Mattias Falkd697aa22011-08-23 14:15:13 +02002738 for (Integer pid : mNetRequestersPids[net]) {
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002739 pidString = pidString + pid.toString() + ", ";
2740 }
2741 pw.println(pidString);
2742 }
2743 pw.println();
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002744 pw.decreaseIndent();
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002745
2746 pw.println("FeatureUsers:");
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002747 pw.increaseIndent();
Robert Greenwalt3eeb6032009-12-21 18:24:07 -08002748 for (Object requester : mFeatureUsers) {
2749 pw.println(requester.toString());
2750 }
2751 pw.println();
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002752 pw.decreaseIndent();
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002753
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002754 synchronized (this) {
2755 pw.println("NetworkTranstionWakeLock is currently " +
2756 (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held.");
2757 pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy);
2758 }
2759 pw.println();
2760
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002761 mTethering.dump(fd, pw, args);
Robert Greenwalt0e80be12010-09-20 14:35:25 -07002762
2763 if (mInetLog != null) {
2764 pw.println();
2765 pw.println("Inet condition reports:");
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002766 pw.increaseIndent();
Robert Greenwalt0e80be12010-09-20 14:35:25 -07002767 for(int i = 0; i < mInetLog.size(); i++) {
2768 pw.println(mInetLog.get(i));
2769 }
Jeff Sharkeycf6ffaf2012-09-14 13:47:51 -07002770 pw.decreaseIndent();
Robert Greenwalt0e80be12010-09-20 14:35:25 -07002771 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002772 }
2773
Robert Greenwalt2034b912009-08-12 16:08:25 -07002774 // must be stateless - things change under us.
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -07002775 private class NetworkStateTrackerHandler extends Handler {
2776 public NetworkStateTrackerHandler(Looper looper) {
Wink Saville775aad62010-09-02 19:23:52 -07002777 super(looper);
2778 }
2779
The Android Open Source Project28527d22009-03-03 19:31:44 -08002780 @Override
2781 public void handleMessage(Message msg) {
2782 NetworkInfo info;
2783 switch (msg.what) {
2784 case NetworkStateTracker.EVENT_STATE_CHANGED:
2785 info = (NetworkInfo) msg.obj;
Robert Greenwalt12c44552009-12-07 11:33:18 -08002786 int type = info.getType();
2787 NetworkInfo.State state = info.getState();
Robert Greenwalt12c44552009-12-07 11:33:18 -08002788
Wink Savillea7d56572011-09-21 11:05:43 -07002789 if (VDBG || (state == NetworkInfo.State.CONNECTED) ||
2790 (state == NetworkInfo.State.DISCONNECTED)) {
2791 log("ConnectivityChange for " +
Robert Greenwalt0659da32009-07-16 17:21:39 -07002792 info.getTypeName() + ": " +
Robert Greenwalt12c44552009-12-07 11:33:18 -08002793 state + "/" + info.getDetailedState());
Wink Savillea7d56572011-09-21 11:05:43 -07002794 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002795
Wink Savillef0e9c7f2013-07-16 17:16:37 -07002796 // After booting we'll check once for mobile provisioning
2797 // if we've provisioned by and connected.
2798 if (!mFirstProvisioningCheckStarted
2799 && (0 != Settings.Global.getInt(mContext.getContentResolver(),
2800 Settings.Global.DEVICE_PROVISIONED, 0))
2801 && (state == NetworkInfo.State.CONNECTED)) {
2802 log("check provisioning after booting");
2803 mFirstProvisioningCheckStarted = true;
2804 checkMobileProvisioning(true, CheckMp.MAX_TIMEOUT_MS, null);
2805 }
2806
Jeff Sharkey876ddc92012-11-09 15:57:02 -08002807 EventLogTags.writeConnectivityStateChanged(
2808 info.getType(), info.getSubtype(), info.getDetailedState().ordinal());
Robert Greenwalt0659da32009-07-16 17:21:39 -07002809
2810 if (info.getDetailedState() ==
2811 NetworkInfo.DetailedState.FAILED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002812 handleConnectionFailure(info);
Irfan Sheriff0ad0d132012-08-16 12:49:23 -07002813 } else if (info.getDetailedState() ==
2814 DetailedState.CAPTIVE_PORTAL_CHECK) {
2815 handleCaptivePortalTrackerCheck(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08002816 } else if (state == NetworkInfo.State.DISCONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002817 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08002818 } else if (state == NetworkInfo.State.SUSPENDED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002819 // TODO: need to think this over.
Robert Greenwalt0659da32009-07-16 17:21:39 -07002820 // the logic here is, handle SUSPENDED the same as
2821 // DISCONNECTED. The only difference being we are
2822 // broadcasting an intent with NetworkInfo that's
2823 // suspended. This allows the applications an
2824 // opportunity to handle DISCONNECTED and SUSPENDED
2825 // differently, or not.
The Android Open Source Project28527d22009-03-03 19:31:44 -08002826 handleDisconnect(info);
Robert Greenwalt12c44552009-12-07 11:33:18 -08002827 } else if (state == NetworkInfo.State.CONNECTED) {
The Android Open Source Project28527d22009-03-03 19:31:44 -08002828 handleConnect(info);
2829 }
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07002830 if (mLockdownTracker != null) {
2831 mLockdownTracker.onNetworkInfoChanged(info);
2832 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002833 break;
The Android Open Source Project28527d22009-03-03 19:31:44 -08002834 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
Robert Greenwalt3afbead2010-07-23 15:46:26 -07002835 info = (NetworkInfo) msg.obj;
Kazuhiro Ondo07680062011-06-22 21:10:34 -05002836 // TODO: Temporary allowing network configuration
2837 // change not resetting sockets.
2838 // @see bug/4455071
2839 handleConnectivityChange(info.getType(), false);
The Android Open Source Project28527d22009-03-03 19:31:44 -08002840 break;
Robert Greenwaltadb8bf92012-08-20 11:15:39 -07002841 case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED:
2842 info = (NetworkInfo) msg.obj;
2843 type = info.getType();
2844 updateNetworkSettings(mNetTrackers[type]);
2845 break;
Jeff Sharkeya1ef1be2012-07-23 13:19:46 -07002846 }
2847 }
2848 }
2849
2850 private class InternalHandler extends Handler {
2851 public InternalHandler(Looper looper) {
2852 super(looper);
2853 }
2854
2855 @Override
2856 public void handleMessage(Message msg) {
2857 NetworkInfo info;
2858 switch (msg.what) {
Robert Greenwaltccb36f92010-09-24 14:32:21 -07002859 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002860 String causedBy = null;
2861 synchronized (ConnectivityService.this) {
2862 if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
2863 mNetTransitionWakeLock.isHeld()) {
2864 mNetTransitionWakeLock.release();
2865 causedBy = mNetTransitionWakeLockCausedBy;
2866 }
2867 }
2868 if (causedBy != null) {
Wink Savillee70c6f52010-12-03 12:01:38 -08002869 log("NetTransition Wakelock for " + causedBy + " released by timeout");
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002870 }
Robert Greenwaltcf1a56c2010-09-09 14:05:10 -07002871 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002872 case EVENT_RESTORE_DEFAULT_NETWORK:
Robert Greenwaltaffc3a12009-09-27 17:27:04 -07002873 FeatureUser u = (FeatureUser)msg.obj;
2874 u.expire();
Robert Greenwalt986c7412010-09-08 15:24:47 -07002875 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002876 case EVENT_INET_CONDITION_CHANGE:
2877 {
2878 int netType = msg.arg1;
2879 int condition = msg.arg2;
2880 handleInetConditionChange(netType, condition);
Robert Greenwalt93dc1042010-06-15 12:19:37 -07002881 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002882 }
2883 case EVENT_INET_CONDITION_HOLD_END:
2884 {
2885 int netType = msg.arg1;
2886 int sequence = msg.arg2;
Wink Saville151eaa62013-01-31 00:30:13 +00002887 handleInetConditionHoldEnd(netType, sequence);
Robert Greenwalt986c7412010-09-08 15:24:47 -07002888 break;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002889 }
2890 case EVENT_SET_NETWORK_PREFERENCE:
2891 {
2892 int preference = msg.arg1;
2893 handleSetNetworkPreference(preference);
2894 break;
2895 }
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07002896 case EVENT_SET_MOBILE_DATA:
2897 {
2898 boolean enabled = (msg.arg1 == ENABLED);
2899 handleSetMobileData(enabled);
2900 break;
2901 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002902 case EVENT_APPLY_GLOBAL_HTTP_PROXY:
2903 {
2904 handleDeprecatedGlobalHttpProxy();
Robert Greenwalt34848c02011-03-25 13:09:25 -07002905 break;
2906 }
2907 case EVENT_SET_DEPENDENCY_MET:
2908 {
2909 boolean met = (msg.arg1 == ENABLED);
2910 handleSetDependencyMet(msg.arg2, met);
2911 break;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07002912 }
Wink Saville4f0de1e2011-08-04 15:01:58 -07002913 case EVENT_SEND_STICKY_BROADCAST_INTENT:
2914 {
2915 Intent intent = (Intent)msg.obj;
Wink Saville4f0de1e2011-08-04 15:01:58 -07002916 sendStickyBroadcast(intent);
2917 break;
2918 }
Jeff Sharkey805662d2011-08-19 02:24:24 -07002919 case EVENT_SET_POLICY_DATA_ENABLE: {
2920 final int networkType = msg.arg1;
2921 final boolean enabled = msg.arg2 == ENABLED;
2922 handleSetPolicyDataEnable(networkType, enabled);
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07002923 break;
2924 }
2925 case EVENT_VPN_STATE_CHANGED: {
2926 if (mLockdownTracker != null) {
2927 mLockdownTracker.onVpnStateChanged((NetworkInfo) msg.obj);
2928 }
2929 break;
Jeff Sharkey805662d2011-08-19 02:24:24 -07002930 }
Wink Saville32506bc2013-06-29 21:10:57 -07002931 case EVENT_ENABLE_FAIL_FAST_MOBILE_DATA: {
2932 int tag = mEnableFailFastMobileDataTag.get();
2933 if (msg.arg1 == tag) {
2934 MobileDataStateTracker mobileDst =
2935 (MobileDataStateTracker) mNetTrackers[ConnectivityManager.TYPE_MOBILE];
2936 if (mobileDst != null) {
2937 mobileDst.setEnableFailFastMobileData(msg.arg2);
2938 }
2939 } else {
2940 log("EVENT_ENABLE_FAIL_FAST_MOBILE_DATA: stale arg1:" + msg.arg1
2941 + " != tag:" + tag);
2942 }
2943 }
The Android Open Source Project28527d22009-03-03 19:31:44 -08002944 }
2945 }
2946 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002947
2948 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002949 public int tether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002950 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002951
2952 if (isTetheringSupported()) {
2953 return mTethering.tether(iface);
2954 } else {
2955 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2956 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002957 }
2958
2959 // javadoc from interface
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002960 public int untether(String iface) {
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002961 enforceTetherChangePermission();
Robert Greenwalt4283ded2010-03-02 17:25:02 -08002962
2963 if (isTetheringSupported()) {
2964 return mTethering.untether(iface);
2965 } else {
2966 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2967 }
2968 }
2969
2970 // javadoc from interface
2971 public int getLastTetherError(String iface) {
2972 enforceTetherAccessPermission();
2973
2974 if (isTetheringSupported()) {
2975 return mTethering.getLastTetherError(iface);
2976 } else {
2977 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
2978 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08002979 }
2980
2981 // TODO - proper iface API for selection by property, inspection, etc
2982 public String[] getTetherableUsbRegexs() {
2983 enforceTetherAccessPermission();
2984 if (isTetheringSupported()) {
2985 return mTethering.getTetherableUsbRegexs();
2986 } else {
2987 return new String[0];
2988 }
2989 }
2990
2991 public String[] getTetherableWifiRegexs() {
2992 enforceTetherAccessPermission();
2993 if (isTetheringSupported()) {
2994 return mTethering.getTetherableWifiRegexs();
2995 } else {
2996 return new String[0];
2997 }
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08002998 }
2999
Danica Chang96567052010-08-11 14:54:43 -07003000 public String[] getTetherableBluetoothRegexs() {
3001 enforceTetherAccessPermission();
3002 if (isTetheringSupported()) {
3003 return mTethering.getTetherableBluetoothRegexs();
3004 } else {
3005 return new String[0];
3006 }
3007 }
3008
Mike Lockwooded4a1742011-07-19 13:04:47 -07003009 public int setUsbTethering(boolean enable) {
Robert Greenwaltfaa4b402013-02-15 10:56:35 -08003010 enforceTetherChangePermission();
Mike Lockwooded4a1742011-07-19 13:04:47 -07003011 if (isTetheringSupported()) {
3012 return mTethering.setUsbTethering(enable);
3013 } else {
3014 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
3015 }
3016 }
3017
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08003018 // TODO - move iface listing, queries, etc to new module
3019 // javadoc from interface
3020 public String[] getTetherableIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08003021 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08003022 return mTethering.getTetherableIfaces();
3023 }
3024
3025 public String[] getTetheredIfaces() {
Robert Greenwalt8e87f122010-02-11 18:18:40 -08003026 enforceTetherAccessPermission();
Robert Greenwalt0c4828c2010-01-26 11:40:34 -08003027 return mTethering.getTetheredIfaces();
3028 }
Robert Greenwalt8e87f122010-02-11 18:18:40 -08003029
Jeff Sharkey300f08f2011-09-16 01:52:49 -07003030 @Override
3031 public String[] getTetheredIfacePairs() {
3032 enforceTetherAccessPermission();
3033 return mTethering.getTetheredIfacePairs();
3034 }
3035
Robert Greenwalt4283ded2010-03-02 17:25:02 -08003036 public String[] getTetheringErroredIfaces() {
3037 enforceTetherAccessPermission();
3038 return mTethering.getErroredIfaces();
3039 }
3040
Robert Greenwalt8e87f122010-02-11 18:18:40 -08003041 // if ro.tether.denied = true we default to no tethering
3042 // gservices could set the secure setting to 1 though to enable it on a build where it
3043 // had previously been turned off.
3044 public boolean isTetheringSupported() {
3045 enforceTetherAccessPermission();
3046 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
Jeff Brownc67cf562012-09-25 15:03:20 -07003047 boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(),
3048 Settings.Global.TETHER_SUPPORTED, defaultVal) != 0);
Robert Greenwalt368095f2013-07-18 14:24:42 -07003049 return tetherEnabledInSettings && ((mTethering.getTetherableUsbRegexs().length != 0 ||
3050 mTethering.getTetherableWifiRegexs().length != 0 ||
3051 mTethering.getTetherableBluetoothRegexs().length != 0) &&
3052 mTethering.getUpstreamIfaceTypes().length != 0);
Robert Greenwalt8e87f122010-02-11 18:18:40 -08003053 }
Robert Greenwalt93dc1042010-06-15 12:19:37 -07003054
3055 // An API NetworkStateTrackers can call when they lose their network.
3056 // This will automatically be cleared after X seconds or a network becomes CONNECTED,
3057 // whichever happens first. The timer is started by the first caller and not
3058 // restarted by subsequent callers.
3059 public void requestNetworkTransitionWakelock(String forWhom) {
3060 enforceConnectivityInternalPermission();
3061 synchronized (this) {
3062 if (mNetTransitionWakeLock.isHeld()) return;
3063 mNetTransitionWakeLockSerialNumber++;
3064 mNetTransitionWakeLock.acquire();
3065 mNetTransitionWakeLockCausedBy = forWhom;
3066 }
3067 mHandler.sendMessageDelayed(mHandler.obtainMessage(
Robert Greenwaltccb36f92010-09-24 14:32:21 -07003068 EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
Robert Greenwalt93dc1042010-06-15 12:19:37 -07003069 mNetTransitionWakeLockSerialNumber, 0),
3070 mNetTransitionWakeLockTimeout);
3071 return;
3072 }
Robert Greenwalt24118e82010-09-09 13:15:32 -07003073
Robert Greenwalt986c7412010-09-08 15:24:47 -07003074 // 100 percent is full good, 0 is full bad.
3075 public void reportInetCondition(int networkType, int percentage) {
Robert Greenwalt78f28112011-08-02 17:18:41 -07003076 if (VDBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")");
Robert Greenwalt986c7412010-09-08 15:24:47 -07003077 mContext.enforceCallingOrSelfPermission(
3078 android.Manifest.permission.STATUS_BAR,
3079 "ConnectivityService");
3080
Robert Greenwalt0e80be12010-09-20 14:35:25 -07003081 if (DBG) {
3082 int pid = getCallingPid();
3083 int uid = getCallingUid();
3084 String s = pid + "(" + uid + ") reports inet is " +
3085 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
3086 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
3087 mInetLog.add(s);
3088 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
3089 mInetLog.remove(0);
3090 }
3091 }
Robert Greenwalt986c7412010-09-08 15:24:47 -07003092 mHandler.sendMessage(mHandler.obtainMessage(
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003093 EVENT_INET_CONDITION_CHANGE, networkType, percentage));
3094 }
3095
3096 private void handleInetConditionChange(int netType, int condition) {
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003097 if (mActiveDefaultNetwork == -1) {
Wink Savillea7d56572011-09-21 11:05:43 -07003098 if (DBG) log("handleInetConditionChange: no active default network - ignore");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003099 return;
3100 }
3101 if (mActiveDefaultNetwork != netType) {
Wink Savillea7d56572011-09-21 11:05:43 -07003102 if (DBG) log("handleInetConditionChange: net=" + netType +
3103 " != default=" + mActiveDefaultNetwork + " - ignore");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003104 return;
3105 }
Wink Savillea7d56572011-09-21 11:05:43 -07003106 if (VDBG) {
3107 log("handleInetConditionChange: net=" +
3108 netType + ", condition=" + condition +
Wink Saville151eaa62013-01-31 00:30:13 +00003109 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
Wink Savillea7d56572011-09-21 11:05:43 -07003110 }
Wink Saville151eaa62013-01-31 00:30:13 +00003111 mDefaultInetCondition = condition;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003112 int delay;
3113 if (mInetConditionChangeInFlight == false) {
Wink Savillea7d56572011-09-21 11:05:43 -07003114 if (VDBG) log("handleInetConditionChange: starting a change hold");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003115 // setup a new hold to debounce this
Wink Saville151eaa62013-01-31 00:30:13 +00003116 if (mDefaultInetCondition > 50) {
Jeff Sharkey8c870452012-09-26 22:03:49 -07003117 delay = Settings.Global.getInt(mContext.getContentResolver(),
3118 Settings.Global.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003119 } else {
Jeff Sharkey8c870452012-09-26 22:03:49 -07003120 delay = Settings.Global.getInt(mContext.getContentResolver(),
3121 Settings.Global.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003122 }
3123 mInetConditionChangeInFlight = true;
3124 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
Wink Saville151eaa62013-01-31 00:30:13 +00003125 mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003126 } else {
Wink Savillea7d56572011-09-21 11:05:43 -07003127 // we've set the new condition, when this hold ends that will get picked up
3128 if (VDBG) log("handleInetConditionChange: currently in hold - not setting new end evt");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003129 }
3130 }
3131
Wink Saville151eaa62013-01-31 00:30:13 +00003132 private void handleInetConditionHoldEnd(int netType, int sequence) {
Wink Savillea7d56572011-09-21 11:05:43 -07003133 if (DBG) {
Wink Saville151eaa62013-01-31 00:30:13 +00003134 log("handleInetConditionHoldEnd: net=" + netType +
3135 ", condition=" + mDefaultInetCondition +
3136 ", published condition=" + mDefaultInetConditionPublished);
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003137 }
3138 mInetConditionChangeInFlight = false;
3139
3140 if (mActiveDefaultNetwork == -1) {
Wink Savillea7d56572011-09-21 11:05:43 -07003141 if (DBG) log("handleInetConditionHoldEnd: no active default network - ignoring");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003142 return;
3143 }
3144 if (mDefaultConnectionSequence != sequence) {
Wink Savillea7d56572011-09-21 11:05:43 -07003145 if (DBG) log("handleInetConditionHoldEnd: event hold for obsolete network - ignoring");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003146 return;
3147 }
Wink Saville151eaa62013-01-31 00:30:13 +00003148 // TODO: Figure out why this optimization sometimes causes a
3149 // change in mDefaultInetCondition to be missed and the
3150 // UI to not be updated.
3151 //if (mDefaultInetConditionPublished == mDefaultInetCondition) {
3152 // if (DBG) log("no change in condition - aborting");
3153 // return;
3154 //}
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003155 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
3156 if (networkInfo.isConnected() == false) {
Wink Savillea7d56572011-09-21 11:05:43 -07003157 if (DBG) log("handleInetConditionHoldEnd: default network not connected - ignoring");
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003158 return;
3159 }
Wink Saville151eaa62013-01-31 00:30:13 +00003160 mDefaultInetConditionPublished = mDefaultInetCondition;
Robert Greenwalt6a2db8a2010-09-23 10:05:56 -07003161 sendInetConditionBroadcast(networkInfo);
3162 return;
Robert Greenwalt986c7412010-09-08 15:24:47 -07003163 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003164
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003165 public ProxyProperties getProxy() {
Robert Greenwalt0e0ae8a2013-02-22 14:57:00 -08003166 // this information is already available as a world read/writable jvm property
3167 // so this API change wouldn't have a benifit. It also breaks the passing
3168 // of proxy info to all the JVMs.
3169 // enforceAccessPermission();
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003170 synchronized (mProxyLock) {
3171 if (mGlobalProxy != null) return mGlobalProxy;
3172 return (mDefaultProxyDisabled ? null : mDefaultProxy);
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003173 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003174 }
3175
3176 public void setGlobalProxy(ProxyProperties proxyProperties) {
Robert Greenwalt6477bd02013-04-10 15:32:18 -07003177 enforceConnectivityInternalPermission();
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003178 synchronized (mProxyLock) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003179 if (proxyProperties == mGlobalProxy) return;
3180 if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
3181 if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
3182
3183 String host = "";
3184 int port = 0;
3185 String exclList = "";
3186 if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) {
3187 mGlobalProxy = new ProxyProperties(proxyProperties);
3188 host = mGlobalProxy.getHost();
3189 port = mGlobalProxy.getPort();
3190 exclList = mGlobalProxy.getExclusionList();
3191 } else {
3192 mGlobalProxy = null;
3193 }
3194 ContentResolver res = mContext.getContentResolver();
Robert Greenwalt6477bd02013-04-10 15:32:18 -07003195 final long token = Binder.clearCallingIdentity();
3196 try {
3197 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, host);
3198 Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
3199 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
3200 exclList);
3201 } finally {
3202 Binder.restoreCallingIdentity(token);
3203 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003204 }
3205
3206 if (mGlobalProxy == null) {
3207 proxyProperties = mDefaultProxy;
3208 }
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003209 sendProxyBroadcast(proxyProperties);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003210 }
3211
Robert Greenwalt6f7c6092010-12-02 11:31:00 -08003212 private void loadGlobalProxy() {
3213 ContentResolver res = mContext.getContentResolver();
Jeff Sharkey8c870452012-09-26 22:03:49 -07003214 String host = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST);
3215 int port = Settings.Global.getInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, 0);
3216 String exclList = Settings.Global.getString(res,
3217 Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
Robert Greenwalt6f7c6092010-12-02 11:31:00 -08003218 if (!TextUtils.isEmpty(host)) {
3219 ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList);
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003220 synchronized (mProxyLock) {
Robert Greenwalt6f7c6092010-12-02 11:31:00 -08003221 mGlobalProxy = proxyProperties;
3222 }
3223 }
3224 }
3225
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003226 public ProxyProperties getGlobalProxy() {
Robert Greenwalt0e0ae8a2013-02-22 14:57:00 -08003227 // this information is already available as a world read/writable jvm property
3228 // so this API change wouldn't have a benifit. It also breaks the passing
3229 // of proxy info to all the JVMs.
3230 // enforceAccessPermission();
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003231 synchronized (mProxyLock) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003232 return mGlobalProxy;
3233 }
3234 }
3235
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003236 private void handleApplyDefaultProxy(ProxyProperties proxy) {
3237 if (proxy != null && TextUtils.isEmpty(proxy.getHost())) {
3238 proxy = null;
3239 }
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003240 synchronized (mProxyLock) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003241 if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003242 if (mDefaultProxy == proxy) return; // catches repeated nulls
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003243 mDefaultProxy = proxy;
3244
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003245 if (mGlobalProxy != null) return;
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003246 if (!mDefaultProxyDisabled) {
3247 sendProxyBroadcast(proxy);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003248 }
3249 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003250 }
3251
3252 private void handleDeprecatedGlobalHttpProxy() {
Jeff Sharkey8c870452012-09-26 22:03:49 -07003253 String proxy = Settings.Global.getString(mContext.getContentResolver(),
3254 Settings.Global.HTTP_PROXY);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003255 if (!TextUtils.isEmpty(proxy)) {
3256 String data[] = proxy.split(":");
Andreas Huber23bff232013-05-28 15:17:37 -07003257 if (data.length == 0) {
3258 return;
3259 }
3260
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003261 String proxyHost = data[0];
3262 int proxyPort = 8080;
3263 if (data.length > 1) {
3264 try {
3265 proxyPort = Integer.parseInt(data[1]);
3266 } catch (NumberFormatException e) {
3267 return;
3268 }
3269 }
3270 ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
3271 setGlobalProxy(p);
Andreas Huber23bff232013-05-28 15:17:37 -07003272 } else {
3273 setGlobalProxy(null);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003274 }
3275 }
3276
3277 private void sendProxyBroadcast(ProxyProperties proxy) {
Robert Greenwalt611291c2010-12-23 15:51:10 -08003278 if (proxy == null) proxy = new ProxyProperties("", 0, "");
Robert Greenwalt78f28112011-08-02 17:18:41 -07003279 if (DBG) log("sending Proxy Broadcast for " + proxy);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003280 Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
Stan Chesnutt1f2a2ac2011-01-06 11:00:19 -08003281 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
3282 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003283 intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
Dianne Hackborne588ca12012-09-04 18:48:37 -07003284 final long ident = Binder.clearCallingIdentity();
3285 try {
3286 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
3287 } finally {
3288 Binder.restoreCallingIdentity(ident);
3289 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003290 }
3291
3292 private static class SettingsObserver extends ContentObserver {
3293 private int mWhat;
3294 private Handler mHandler;
3295 SettingsObserver(Handler handler, int what) {
3296 super(handler);
3297 mHandler = handler;
3298 mWhat = what;
3299 }
3300
3301 void observe(Context context) {
3302 ContentResolver resolver = context.getContentResolver();
Jeff Sharkey8c870452012-09-26 22:03:49 -07003303 resolver.registerContentObserver(Settings.Global.getUriFor(
3304 Settings.Global.HTTP_PROXY), false, this);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -07003305 }
3306
3307 @Override
3308 public void onChange(boolean selfChange) {
3309 mHandler.obtainMessage(mWhat).sendToTarget();
3310 }
3311 }
Wink Savillee70c6f52010-12-03 12:01:38 -08003312
Jeff Sharkey6b9021d2012-07-26 18:32:30 -07003313 private static void log(String s) {
Wink Savillee70c6f52010-12-03 12:01:38 -08003314 Slog.d(TAG, s);
3315 }
3316
Jeff Sharkey6b9021d2012-07-26 18:32:30 -07003317 private static void loge(String s) {
Wink Savillee70c6f52010-12-03 12:01:38 -08003318 Slog.e(TAG, s);
3319 }
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003320
repo syncf5de5572011-07-29 23:55:49 -07003321 int convertFeatureToNetworkType(int networkType, String feature) {
3322 int usedNetworkType = networkType;
3323
3324 if(networkType == ConnectivityManager.TYPE_MOBILE) {
3325 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
3326 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
3327 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
3328 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
3329 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
3330 TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
3331 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
3332 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
3333 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
3334 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
3335 usedNetworkType = ConnectivityManager.TYPE_MOBILE_FOTA;
3336 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
3337 usedNetworkType = ConnectivityManager.TYPE_MOBILE_IMS;
3338 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
3339 usedNetworkType = ConnectivityManager.TYPE_MOBILE_CBS;
3340 } else {
3341 Slog.e(TAG, "Can't match any mobile netTracker!");
3342 }
3343 } else if (networkType == ConnectivityManager.TYPE_WIFI) {
3344 if (TextUtils.equals(feature, "p2p")) {
3345 usedNetworkType = ConnectivityManager.TYPE_WIFI_P2P;
3346 } else {
3347 Slog.e(TAG, "Can't match any wifi netTracker!");
3348 }
3349 } else {
3350 Slog.e(TAG, "Unexpected network type");
Wink Savillef6b76692011-02-24 17:58:51 -08003351 }
repo syncf5de5572011-07-29 23:55:49 -07003352 return usedNetworkType;
Wink Savillef6b76692011-02-24 17:58:51 -08003353 }
Jeff Sharkey921ebf22011-05-19 17:12:49 -07003354
3355 private static <T> T checkNotNull(T value, String message) {
3356 if (value == null) {
3357 throw new NullPointerException(message);
3358 }
3359 return value;
3360 }
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003361
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07003362 /**
3363 * Protect a socket from VPN routing rules. This method is used by
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07003364 * VpnBuilder and not available in ConnectivityManager. Permissions
3365 * are checked in Vpn class.
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07003366 * @hide
3367 */
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003368 @Override
Chia-chi Yeh9e4ff6e2011-07-14 16:19:19 -07003369 public boolean protectVpn(ParcelFileDescriptor socket) {
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07003370 throwIfLockdownEnabled();
Chia-chi Yeh9e4ff6e2011-07-14 16:19:19 -07003371 try {
3372 int type = mActiveDefaultNetwork;
Chad Brubakerb7652cd2013-06-14 11:16:51 -07003373 int user = UserHandle.getUserId(Binder.getCallingUid());
Robert Greenwalt15a41532012-08-21 19:27:00 -07003374 if (ConnectivityManager.isNetworkTypeValid(type) && mNetTrackers[type] != null) {
Chad Brubakerb7652cd2013-06-14 11:16:51 -07003375 synchronized(mVpns) {
3376 mVpns.get(user).protect(socket,
3377 mNetTrackers[type].getLinkProperties().getInterfaceName());
3378 }
Chia-chi Yeh9e4ff6e2011-07-14 16:19:19 -07003379 return true;
3380 }
3381 } catch (Exception e) {
3382 // ignore
3383 } finally {
3384 try {
3385 socket.close();
3386 } catch (Exception e) {
3387 // ignore
3388 }
3389 }
3390 return false;
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003391 }
3392
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07003393 /**
3394 * Prepare for a VPN application. This method is used by VpnDialogs
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07003395 * and not available in ConnectivityManager. Permissions are checked
3396 * in Vpn class.
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07003397 * @hide
3398 */
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003399 @Override
Chia-chi Yeh3e2e1da2011-07-03 16:52:38 -07003400 public boolean prepareVpn(String oldPackage, String newPackage) {
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07003401 throwIfLockdownEnabled();
Chad Brubakerb7652cd2013-06-14 11:16:51 -07003402 int user = UserHandle.getUserId(Binder.getCallingUid());
3403 synchronized(mVpns) {
3404 return mVpns.get(user).prepare(oldPackage, newPackage);
3405 }
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003406 }
3407
Chad Brubaker11f22252013-07-11 13:29:30 -07003408 @Override
3409 public void markSocketAsUser(ParcelFileDescriptor socket, int uid) {
3410 enforceMarkNetworkSocketPermission();
3411 final long token = Binder.clearCallingIdentity();
3412 try {
3413 int mark = mNetd.getMarkForUid(uid);
3414 // Clear the mark on the socket if no mark is needed to prevent socket reuse issues
3415 if (mark == -1) {
3416 mark = 0;
3417 }
3418 NetworkUtils.markSocket(socket.getFd(), mark);
3419 } catch (RemoteException e) {
3420 } finally {
3421 Binder.restoreCallingIdentity(token);
3422 }
3423 }
3424
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07003425 /**
3426 * Configure a TUN interface and return its file descriptor. Parameters
3427 * are encoded and opaque to this class. This method is used by VpnBuilder
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07003428 * and not available in ConnectivityManager. Permissions are checked in
3429 * Vpn class.
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07003430 * @hide
3431 */
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003432 @Override
Chia-chi Yeh75cacd52011-06-15 17:07:27 -07003433 public ParcelFileDescriptor establishVpn(VpnConfig config) {
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07003434 throwIfLockdownEnabled();
Chad Brubakerb7652cd2013-06-14 11:16:51 -07003435 int user = UserHandle.getUserId(Binder.getCallingUid());
3436 synchronized(mVpns) {
3437 return mVpns.get(user).establish(config);
3438 }
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003439 }
3440
Chia-chi Yeh7e026b32011-07-02 17:15:00 -07003441 /**
Jeff Sharkey64d8b3b2012-08-24 11:17:25 -07003442 * Start legacy VPN, controlling native daemons as needed. Creates a
3443 * secondary thread to perform connection work, returning quickly.
Chia-chi Yeh7e026b32011-07-02 17:15:00 -07003444 */
3445 @Override
Jeff Sharkey64d8b3b2012-08-24 11:17:25 -07003446 public void startLegacyVpn(VpnProfile profile) {
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07003447 throwIfLockdownEnabled();
Jeff Sharkey64d8b3b2012-08-24 11:17:25 -07003448 final LinkProperties egress = getActiveLinkProperties();
3449 if (egress == null) {
3450 throw new IllegalStateException("Missing active network connection");
3451 }
Chad Brubakerb7652cd2013-06-14 11:16:51 -07003452 int user = UserHandle.getUserId(Binder.getCallingUid());
3453 synchronized(mVpns) {
3454 mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress);
3455 }
Chia-chi Yehbded3eb2011-07-04 03:23:12 -07003456 }
3457
3458 /**
3459 * Return the information of the ongoing legacy VPN. This method is used
3460 * by VpnSettings and not available in ConnectivityManager. Permissions
3461 * are checked in Vpn class.
3462 * @hide
3463 */
3464 @Override
3465 public LegacyVpnInfo getLegacyVpnInfo() {
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07003466 throwIfLockdownEnabled();
Chad Brubakerb7652cd2013-06-14 11:16:51 -07003467 int user = UserHandle.getUserId(Binder.getCallingUid());
3468 synchronized(mVpns) {
3469 return mVpns.get(user).getLegacyVpnInfo();
3470 }
Chia-chi Yeh7e026b32011-07-02 17:15:00 -07003471 }
3472
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003473 /**
Chad Brubaker94f3c8c2013-07-16 18:59:12 -07003474 * Returns the information of the ongoing VPN. This method is used by VpnDialogs and
3475 * not available in ConnectivityManager.
3476 * Permissions are checked in Vpn class.
3477 * @hide
3478 */
3479 @Override
3480 public VpnConfig getVpnConfig() {
3481 int user = UserHandle.getUserId(Binder.getCallingUid());
3482 synchronized(mVpns) {
3483 return mVpns.get(user).getVpnConfig();
3484 }
3485 }
3486
3487 /**
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003488 * Callback for VPN subsystem. Currently VPN is not adapted to the service
3489 * through NetworkStateTracker since it works differently. For example, it
3490 * needs to override DNS servers but never takes the default routes. It
3491 * relies on another data network, and it could keep existing connections
3492 * alive after reconnecting, switching between networks, or even resuming
3493 * from deep sleep. Calls from applications should be done synchronously
3494 * to avoid race conditions. As these are all hidden APIs, refactoring can
3495 * be done whenever a better abstraction is developed.
3496 */
3497 public class VpnCallback {
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003498 private VpnCallback() {
3499 }
3500
Jeff Sharkey366e0b72012-08-04 15:24:58 -07003501 public void onStateChanged(NetworkInfo info) {
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07003502 mHandler.obtainMessage(EVENT_VPN_STATE_CHANGED, info).sendToTarget();
Jeff Sharkey366e0b72012-08-04 15:24:58 -07003503 }
3504
Chad Brubakerb7652cd2013-06-14 11:16:51 -07003505 public void override(String iface, List<String> dnsServers, List<String> searchDomains) {
Chia-chi Yehcc844502011-07-14 18:01:57 -07003506 if (dnsServers == null) {
3507 restore();
3508 return;
3509 }
3510
3511 // Convert DNS servers into addresses.
3512 List<InetAddress> addresses = new ArrayList<InetAddress>();
3513 for (String address : dnsServers) {
3514 // Double check the addresses and remove invalid ones.
3515 try {
3516 addresses.add(InetAddress.parseNumericAddress(address));
3517 } catch (Exception e) {
3518 // ignore
3519 }
3520 }
3521 if (addresses.isEmpty()) {
3522 restore();
3523 return;
3524 }
3525
3526 // Concatenate search domains into a string.
3527 StringBuilder buffer = new StringBuilder();
3528 if (searchDomains != null) {
3529 for (String domain : searchDomains) {
3530 buffer.append(domain).append(' ');
3531 }
3532 }
3533 String domains = buffer.toString().trim();
3534
3535 // Apply DNS changes.
Chia-chi Yehcc844502011-07-14 18:01:57 -07003536 synchronized (mDnsLock) {
Chad Brubaker73652d02013-07-23 17:13:36 -07003537 updateDnsLocked("VPN", iface, addresses, domains, false);
Chia-chi Yehcc844502011-07-14 18:01:57 -07003538 }
Chia-chi Yehcc844502011-07-14 18:01:57 -07003539
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003540 // Temporarily disable the default proxy (not global).
3541 synchronized (mProxyLock) {
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003542 mDefaultProxyDisabled = true;
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003543 if (mGlobalProxy == null && mDefaultProxy != null) {
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003544 sendProxyBroadcast(null);
3545 }
3546 }
3547
3548 // TODO: support proxy per network.
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003549 }
3550
Chia-chi Yehcc844502011-07-14 18:01:57 -07003551 public void restore() {
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003552 synchronized (mProxyLock) {
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003553 mDefaultProxyDisabled = false;
Robert Greenwaltf9661d32013-04-05 17:14:19 -07003554 if (mGlobalProxy == null && mDefaultProxy != null) {
Chia-chi Yeh763a11c2011-10-03 15:34:04 -07003555 sendProxyBroadcast(mDefaultProxy);
3556 }
3557 }
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003558 }
Chad Brubakerb7652cd2013-06-14 11:16:51 -07003559
3560 public void protect(ParcelFileDescriptor socket) {
3561 try {
3562 final int mark = mNetd.getMarkForProtect();
3563 NetworkUtils.markSocket(socket.getFd(), mark);
3564 } catch (RemoteException e) {
3565 }
3566 }
3567
3568 public void setRoutes(String interfaze, List<RouteInfo> routes) {
3569 for (RouteInfo route : routes) {
3570 try {
3571 mNetd.setMarkedForwardingRoute(interfaze, route);
3572 } catch (RemoteException e) {
3573 }
3574 }
3575 }
3576
3577 public void setMarkedForwarding(String interfaze) {
3578 try {
3579 mNetd.setMarkedForwarding(interfaze);
3580 } catch (RemoteException e) {
3581 }
3582 }
3583
3584 public void clearMarkedForwarding(String interfaze) {
3585 try {
3586 mNetd.clearMarkedForwarding(interfaze);
3587 } catch (RemoteException e) {
3588 }
3589 }
3590
3591 public void addUserForwarding(String interfaze, int uid) {
3592 int uidStart = uid * UserHandle.PER_USER_RANGE;
3593 int uidEnd = uidStart + UserHandle.PER_USER_RANGE - 1;
3594 addUidForwarding(interfaze, uidStart, uidEnd);
3595 }
3596
3597 public void clearUserForwarding(String interfaze, int uid) {
3598 int uidStart = uid * UserHandle.PER_USER_RANGE;
3599 int uidEnd = uidStart + UserHandle.PER_USER_RANGE - 1;
3600 clearUidForwarding(interfaze, uidStart, uidEnd);
3601 }
3602
3603 public void addUidForwarding(String interfaze, int uidStart, int uidEnd) {
3604 try {
3605 mNetd.setUidRangeRoute(interfaze,uidStart, uidEnd);
3606 mNetd.setDnsInterfaceForUidRange(interfaze, uidStart, uidEnd);
3607 } catch (RemoteException e) {
3608 }
3609
3610 }
3611
3612 public void clearUidForwarding(String interfaze, int uidStart, int uidEnd) {
3613 try {
3614 mNetd.clearUidRangeRoute(interfaze, uidStart, uidEnd);
3615 mNetd.clearDnsInterfaceForUidRange(uidStart, uidEnd);
3616 } catch (RemoteException e) {
3617 }
3618
3619 }
Chia-chi Yeh9a4ad7d2011-05-23 17:26:46 -07003620 }
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07003621
3622 @Override
3623 public boolean updateLockdownVpn() {
Jeff Sharkey760c6202013-01-31 17:22:26 -08003624 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
3625 Slog.w(TAG, "Lockdown VPN only available to AID_SYSTEM");
3626 return false;
3627 }
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07003628
3629 // Tear down existing lockdown if profile was removed
3630 mLockdownEnabled = LockdownVpnTracker.isEnabled();
3631 if (mLockdownEnabled) {
Kenny Root0ded63c2013-02-14 10:18:38 -08003632 if (!mKeyStore.isUnlocked()) {
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07003633 Slog.w(TAG, "KeyStore locked; unable to create LockdownTracker");
3634 return false;
3635 }
3636
3637 final String profileName = new String(mKeyStore.get(Credentials.LOCKDOWN_VPN));
3638 final VpnProfile profile = VpnProfile.decode(
3639 profileName, mKeyStore.get(Credentials.VPN + profileName));
Chad Brubakerb7652cd2013-06-14 11:16:51 -07003640 int user = UserHandle.getUserId(Binder.getCallingUid());
3641 synchronized(mVpns) {
3642 setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, mVpns.get(user),
3643 profile));
3644 }
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07003645 } else {
3646 setLockdownTracker(null);
3647 }
3648
3649 return true;
3650 }
3651
3652 /**
3653 * Internally set new {@link LockdownVpnTracker}, shutting down any existing
3654 * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown.
3655 */
3656 private void setLockdownTracker(LockdownVpnTracker tracker) {
3657 // Shutdown any existing tracker
3658 final LockdownVpnTracker existing = mLockdownTracker;
3659 mLockdownTracker = null;
3660 if (existing != null) {
3661 existing.shutdown();
3662 }
3663
3664 try {
3665 if (tracker != null) {
3666 mNetd.setFirewallEnabled(true);
Jeff Sharkeydb44d2c2013-02-28 16:57:58 -08003667 mNetd.setFirewallInterfaceRule("lo", true);
Jeff Sharkeyebcc7972012-08-25 00:05:46 -07003668 mLockdownTracker = tracker;
3669 mLockdownTracker.init();
3670 } else {
3671 mNetd.setFirewallEnabled(false);
3672 }
3673 } catch (RemoteException e) {
3674 // ignored; NMS lives inside system_server
3675 }
3676 }
3677
3678 private void throwIfLockdownEnabled() {
3679 if (mLockdownEnabled) {
3680 throw new IllegalStateException("Unavailable in lockdown mode");
3681 }
3682 }
Robert Greenwalt15a41532012-08-21 19:27:00 -07003683
3684 public void supplyMessenger(int networkType, Messenger messenger) {
3685 enforceConnectivityInternalPermission();
3686
3687 if (isNetworkTypeValid(networkType) && mNetTrackers[networkType] != null) {
3688 mNetTrackers[networkType].supplyMessenger(messenger);
3689 }
3690 }
Robert Greenwalt9a37e5d2013-04-22 11:13:02 -07003691
3692 public int findConnectionTypeForIface(String iface) {
3693 enforceConnectivityInternalPermission();
3694
3695 if (TextUtils.isEmpty(iface)) return ConnectivityManager.TYPE_NONE;
3696 for (NetworkStateTracker tracker : mNetTrackers) {
3697 if (tracker != null) {
3698 LinkProperties lp = tracker.getLinkProperties();
3699 if (lp != null && iface.equals(lp.getInterfaceName())) {
3700 return tracker.getNetworkInfo().getType();
3701 }
3702 }
3703 }
3704 return ConnectivityManager.TYPE_NONE;
3705 }
Wink Saville32506bc2013-06-29 21:10:57 -07003706
3707 /**
3708 * Have mobile data fail fast if enabled.
3709 *
3710 * @param enabled DctConstants.ENABLED/DISABLED
3711 */
3712 private void setEnableFailFastMobileData(int enabled) {
3713 int tag;
3714
3715 if (enabled == DctConstants.ENABLED) {
3716 tag = mEnableFailFastMobileDataTag.incrementAndGet();
3717 } else {
3718 tag = mEnableFailFastMobileDataTag.get();
3719 }
3720 mHandler.sendMessage(mHandler.obtainMessage(EVENT_ENABLE_FAIL_FAST_MOBILE_DATA, tag,
3721 enabled));
3722 }
3723
3724 @Override
Wink Saville99fedeb2013-07-19 09:27:56 -07003725 public int checkMobileProvisioning(final boolean sendNotification, int suggestedTimeOutMs,
Wink Saville32506bc2013-06-29 21:10:57 -07003726 final ResultReceiver resultReceiver) {
3727 log("checkMobileProvisioning: E sendNotification=" + sendNotification
3728 + " suggestedTimeOutMs=" + suggestedTimeOutMs
3729 + " resultReceiver=" + resultReceiver);
3730 enforceChangePermission();
3731
Wink Savillef0e9c7f2013-07-16 17:16:37 -07003732 mFirstProvisioningCheckStarted = true;
3733
Wink Saville32506bc2013-06-29 21:10:57 -07003734 int timeOutMs = suggestedTimeOutMs;
3735 if (suggestedTimeOutMs > CheckMp.MAX_TIMEOUT_MS) {
3736 timeOutMs = CheckMp.MAX_TIMEOUT_MS;
3737 }
3738
Wink Savilled469c472013-07-02 10:55:14 -07003739 // Check that mobile networks are supported
3740 if (!isNetworkSupported(ConnectivityManager.TYPE_MOBILE)
3741 || !isNetworkSupported(ConnectivityManager.TYPE_MOBILE_HIPRI)) {
3742 log("checkMobileProvisioning: X no mobile network");
3743 if (resultReceiver != null) {
3744 resultReceiver.send(ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION, null);
3745 }
3746 return timeOutMs;
3747 }
3748
Wink Saville32506bc2013-06-29 21:10:57 -07003749 final long token = Binder.clearCallingIdentity();
3750 try {
3751 CheckMp checkMp = new CheckMp(mContext, this);
3752 CheckMp.CallBack cb = new CheckMp.CallBack() {
3753 @Override
3754 void onComplete(Integer result) {
3755 log("CheckMp.onComplete: result=" + result);
3756 if (resultReceiver != null) {
3757 log("CheckMp.onComplete: send result");
3758 resultReceiver.send(result, null);
3759 }
Wink Saville99fedeb2013-07-19 09:27:56 -07003760 if (!sendNotification) {
3761 log("CheckMp.onComplete: done, not sending notification");
3762 return;
3763 }
Wink Saville32506bc2013-06-29 21:10:57 -07003764 NetworkInfo ni =
3765 mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI].getNetworkInfo();
3766 switch(result) {
3767 case ConnectivityManager.CMP_RESULT_CODE_CONNECTABLE:
3768 case ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION: {
3769 log("CheckMp.onComplete: ignore, connected or no connection");
3770 break;
3771 }
3772 case ConnectivityManager.CMP_RESULT_CODE_REDIRECTED: {
3773 log("CheckMp.onComplete: warm sim");
Robert Greenwalt39d56012013-07-16 12:06:09 -07003774 String url = getMobileProvisioningUrl();
Wink Saville32506bc2013-06-29 21:10:57 -07003775 if (TextUtils.isEmpty(url)) {
Robert Greenwalt39d56012013-07-16 12:06:09 -07003776 url = getMobileRedirectedProvisioningUrl();
Wink Saville32506bc2013-06-29 21:10:57 -07003777 }
3778 if (TextUtils.isEmpty(url) == false) {
3779 log("CheckMp.onComplete: warm sim (redirected), url=" + url);
3780 setNotificationVisible(true, ni, url);
3781 } else {
3782 log("CheckMp.onComplete: warm sim (redirected), no url");
3783 }
3784 break;
3785 }
3786 case ConnectivityManager.CMP_RESULT_CODE_NO_DNS:
3787 case ConnectivityManager.CMP_RESULT_CODE_NO_TCP_CONNECTION: {
Robert Greenwalt39d56012013-07-16 12:06:09 -07003788 String url = getMobileProvisioningUrl();
Wink Saville32506bc2013-06-29 21:10:57 -07003789 if (TextUtils.isEmpty(url) == false) {
3790 log("CheckMp.onComplete: warm sim (no dns/tcp), url=" + url);
3791 setNotificationVisible(true, ni, url);
3792 } else {
3793 log("CheckMp.onComplete: warm sim (no dns/tcp), no url");
3794 }
3795 break;
3796 }
3797 default: {
3798 loge("CheckMp.onComplete: ignore unexpected result=" + result);
3799 break;
3800 }
3801 }
3802 }
3803 };
3804 CheckMp.Params params =
3805 new CheckMp.Params(checkMp.getDefaultUrl(), timeOutMs, cb);
3806 log("checkMobileProvisioning: params=" + params);
3807 setNotificationVisible(false, null, null);
3808 checkMp.execute(params);
3809 } finally {
3810 Binder.restoreCallingIdentity(token);
3811 log("checkMobileProvisioning: X");
3812 }
3813 return timeOutMs;
3814 }
3815
3816 static class CheckMp extends
3817 AsyncTask<CheckMp.Params, Void, Integer> {
3818 private static final String CHECKMP_TAG = "CheckMp";
3819 public static final int MAX_TIMEOUT_MS = 60000;
3820 private static final int SOCKET_TIMEOUT_MS = 5000;
3821 private Context mContext;
3822 private ConnectivityService mCs;
3823 private TelephonyManager mTm;
3824 private Params mParams;
3825
3826 /**
3827 * Parameters for AsyncTask.execute
3828 */
3829 static class Params {
3830 private String mUrl;
3831 private long mTimeOutMs;
3832 private CallBack mCb;
3833
3834 Params(String url, long timeOutMs, CallBack cb) {
3835 mUrl = url;
3836 mTimeOutMs = timeOutMs;
3837 mCb = cb;
3838 }
3839
3840 @Override
3841 public String toString() {
3842 return "{" + " url=" + mUrl + " mTimeOutMs=" + mTimeOutMs + " mCb=" + mCb + "}";
3843 }
3844 }
3845
3846 /**
3847 * The call back object passed in Params. onComplete will be called
3848 * on the main thread.
3849 */
3850 abstract static class CallBack {
3851 // Called on the main thread.
3852 abstract void onComplete(Integer result);
3853 }
3854
3855 public CheckMp(Context context, ConnectivityService cs) {
3856 mContext = context;
3857 mCs = cs;
3858
3859 // Setup access to TelephonyService we'll be using.
3860 mTm = (TelephonyManager) mContext.getSystemService(
3861 Context.TELEPHONY_SERVICE);
3862 }
3863
3864 /**
3865 * Get the default url to use for the test.
3866 */
3867 public String getDefaultUrl() {
3868 // See http://go/clientsdns for usage approval
3869 String server = Settings.Global.getString(mContext.getContentResolver(),
3870 Settings.Global.CAPTIVE_PORTAL_SERVER);
3871 if (server == null) {
3872 server = "clients3.google.com";
3873 }
3874 return "http://" + server + "/generate_204";
3875 }
3876
3877 /**
3878 * Detect if its possible to connect to the http url. DNS based detection techniques
3879 * do not work at all hotspots. The best way to check is to perform a request to
3880 * a known address that fetches the data we expect.
3881 */
3882 private synchronized Integer isMobileOk(Params params) {
3883 Integer result = ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION;
3884 Uri orgUri = Uri.parse(params.mUrl);
3885 Random rand = new Random();
3886 mParams = params;
3887
3888 try {
3889 if (mCs.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false) {
3890 log("isMobileOk: not mobile capable");
3891 result = ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION;
3892 return result;
3893 }
3894
3895 // Enable fail fast as we'll do retries here and use a
3896 // hipri connection so the default connection stays active.
3897 log("isMobileOk: start hipri url=" + params.mUrl);
3898 mCs.setEnableFailFastMobileData(DctConstants.ENABLED);
3899 mCs.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
3900 Phone.FEATURE_ENABLE_HIPRI, new Binder());
3901
3902 // Continue trying to connect until time has run out
3903 long endTime = SystemClock.elapsedRealtime() + params.mTimeOutMs;
3904 while(SystemClock.elapsedRealtime() < endTime) {
3905 try {
3906 // Wait for hipri to connect.
3907 // TODO: Don't poll and handle situation where hipri fails
3908 // because default is retrying. See b/9569540
3909 NetworkInfo.State state = mCs
3910 .getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
3911 if (state != NetworkInfo.State.CONNECTED) {
3912 log("isMobileOk: not connected ni=" +
3913 mCs.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI));
3914 sleep(1);
3915 result = ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION;
3916 continue;
3917 }
3918
3919 // Get of the addresses associated with the url host. We need to use the
3920 // address otherwise HttpURLConnection object will use the name to get
3921 // the addresses and is will try every address but that will bypass the
3922 // route to host we setup and the connection could succeed as the default
3923 // interface might be connected to the internet via wifi or other interface.
3924 InetAddress[] addresses;
3925 try {
3926 addresses = InetAddress.getAllByName(orgUri.getHost());
3927 } catch (UnknownHostException e) {
3928 log("isMobileOk: UnknownHostException");
3929 result = ConnectivityManager.CMP_RESULT_CODE_NO_DNS;
3930 return result;
3931 }
3932 log("isMobileOk: addresses=" + inetAddressesToString(addresses));
3933
3934 // Get the type of addresses supported by this link
3935 LinkProperties lp = mCs.getLinkProperties(
3936 ConnectivityManager.TYPE_MOBILE_HIPRI);
3937 boolean linkHasIpv4 = hasIPv4Address(lp);
3938 boolean linkHasIpv6 = hasIPv6Address(lp);
3939 log("isMobileOk: linkHasIpv4=" + linkHasIpv4
3940 + " linkHasIpv6=" + linkHasIpv6);
3941
3942 // Loop through at most 3 valid addresses or all of the address or until
3943 // we run out of time
3944 int loops = Math.min(3, addresses.length);
3945 for(int validAddr=0, addrTried=0;
3946 (validAddr < loops) && (addrTried < addresses.length)
3947 && (SystemClock.elapsedRealtime() < endTime);
3948 addrTried ++) {
3949
3950 // Choose the address at random but make sure its type is supported
3951 InetAddress hostAddr = addresses[rand.nextInt(addresses.length)];
3952 if (((hostAddr instanceof Inet4Address) && linkHasIpv4)
3953 || ((hostAddr instanceof Inet6Address) && linkHasIpv6)) {
3954 // Valid address, so use it
3955 validAddr += 1;
3956 } else {
3957 // Invalid address so try next address
3958 continue;
3959 }
3960
3961 // Make a route to host so we check the specific interface.
3962 if (mCs.requestRouteToHostAddress(ConnectivityManager.TYPE_MOBILE_HIPRI,
3963 hostAddr.getAddress())) {
3964 // Wait a short time to be sure the route is established ??
3965 log("isMobileOk:"
3966 + " wait to establish route to hostAddr=" + hostAddr);
3967 sleep(3);
3968 } else {
3969 log("isMobileOk:"
3970 + " could not establish route to hostAddr=" + hostAddr);
3971 continue;
3972 }
3973
3974 // Rewrite the url to have numeric address to use the specific route.
3975 // I also set the "Connection" to "Close" as by default "Keep-Alive"
3976 // is used which is useless in this case.
3977 URL newUrl = new URL(orgUri.getScheme() + "://"
3978 + hostAddr.getHostAddress() + orgUri.getPath());
3979 log("isMobileOk: newUrl=" + newUrl);
3980
3981 HttpURLConnection urlConn = null;
3982 try {
3983 // Open the connection set the request header and get the response
3984 urlConn = (HttpURLConnection) newUrl.openConnection(
3985 java.net.Proxy.NO_PROXY);
3986 urlConn.setInstanceFollowRedirects(false);
3987 urlConn.setConnectTimeout(SOCKET_TIMEOUT_MS);
3988 urlConn.setReadTimeout(SOCKET_TIMEOUT_MS);
3989 urlConn.setUseCaches(false);
3990 urlConn.setAllowUserInteraction(false);
3991 urlConn.setRequestProperty("Connection", "close");
3992 int responseCode = urlConn.getResponseCode();
3993 if (responseCode == 204) {
3994 result = ConnectivityManager.CMP_RESULT_CODE_CONNECTABLE;
3995 } else {
3996 result = ConnectivityManager.CMP_RESULT_CODE_REDIRECTED;
3997 }
3998 log("isMobileOk: connected responseCode=" + responseCode);
3999 urlConn.disconnect();
4000 urlConn = null;
4001 return result;
4002 } catch (Exception e) {
4003 log("isMobileOk: HttpURLConnection Exception e=" + e);
4004 if (urlConn != null) {
4005 urlConn.disconnect();
4006 urlConn = null;
4007 }
4008 }
4009 }
4010 result = ConnectivityManager.CMP_RESULT_CODE_NO_TCP_CONNECTION;
4011 log("isMobileOk: loops|timed out");
4012 return result;
4013 } catch (Exception e) {
4014 log("isMobileOk: Exception e=" + e);
4015 continue;
4016 }
4017 }
4018 log("isMobileOk: timed out");
4019 } finally {
4020 log("isMobileOk: F stop hipri");
4021 mCs.setEnableFailFastMobileData(DctConstants.DISABLED);
4022 mCs.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
4023 Phone.FEATURE_ENABLE_HIPRI);
4024 log("isMobileOk: X result=" + result);
4025 }
4026 return result;
4027 }
4028
4029 @Override
4030 protected Integer doInBackground(Params... params) {
4031 return isMobileOk(params[0]);
4032 }
4033
4034 @Override
4035 protected void onPostExecute(Integer result) {
4036 log("onPostExecute: result=" + result);
4037 if ((mParams != null) && (mParams.mCb != null)) {
4038 mParams.mCb.onComplete(result);
4039 }
4040 }
4041
4042 private String inetAddressesToString(InetAddress[] addresses) {
4043 StringBuffer sb = new StringBuffer();
4044 boolean firstTime = true;
4045 for(InetAddress addr : addresses) {
4046 if (firstTime) {
4047 firstTime = false;
4048 } else {
4049 sb.append(",");
4050 }
4051 sb.append(addr);
4052 }
4053 return sb.toString();
4054 }
4055
4056 private void printNetworkInfo() {
4057 boolean hasIccCard = mTm.hasIccCard();
4058 int simState = mTm.getSimState();
4059 log("hasIccCard=" + hasIccCard
4060 + " simState=" + simState);
4061 NetworkInfo[] ni = mCs.getAllNetworkInfo();
4062 if (ni != null) {
4063 log("ni.length=" + ni.length);
4064 for (NetworkInfo netInfo: ni) {
4065 log("netInfo=" + netInfo.toString());
4066 }
4067 } else {
4068 log("no network info ni=null");
4069 }
4070 }
4071
4072 /**
4073 * Sleep for a few seconds then return.
4074 * @param seconds
4075 */
4076 private static void sleep(int seconds) {
4077 try {
4078 Thread.sleep(seconds * 1000);
4079 } catch (InterruptedException e) {
4080 e.printStackTrace();
4081 }
4082 }
4083
4084 public boolean hasIPv4Address(LinkProperties lp) {
4085 return lp.hasIPv4Address();
4086 }
4087
4088 // Not implemented in LinkProperties, do it here.
4089 public boolean hasIPv6Address(LinkProperties lp) {
4090 for (LinkAddress address : lp.getLinkAddresses()) {
4091 if (address.getAddress() instanceof Inet6Address) {
4092 return true;
4093 }
4094 }
4095 return false;
4096 }
4097
4098 private void log(String s) {
4099 Slog.d(ConnectivityService.TAG, "[" + CHECKMP_TAG + "] " + s);
4100 }
4101 }
4102
4103 private static final String NOTIFICATION_ID = "CaptivePortal.Notification";
4104
4105 private void setNotificationVisible(boolean visible, NetworkInfo networkInfo, String url) {
4106 log("setNotificationVisible: E visible=" + visible + " ni=" + networkInfo + " url=" + url);
4107
4108 Resources r = Resources.getSystem();
4109 NotificationManager notificationManager = (NotificationManager) mContext
4110 .getSystemService(Context.NOTIFICATION_SERVICE);
4111
4112 if (visible) {
4113 CharSequence title;
4114 CharSequence details;
4115 int icon;
4116 switch (networkInfo.getType()) {
4117 case ConnectivityManager.TYPE_WIFI:
4118 log("setNotificationVisible: TYPE_WIFI");
4119 title = r.getString(R.string.wifi_available_sign_in, 0);
4120 details = r.getString(R.string.network_available_sign_in_detailed,
4121 networkInfo.getExtraInfo());
4122 icon = R.drawable.stat_notify_wifi_in_range;
4123 break;
4124 case ConnectivityManager.TYPE_MOBILE:
4125 case ConnectivityManager.TYPE_MOBILE_HIPRI:
4126 log("setNotificationVisible: TYPE_MOBILE|HIPRI");
4127 title = r.getString(R.string.network_available_sign_in, 0);
4128 // TODO: Change this to pull from NetworkInfo once a printable
4129 // name has been added to it
4130 details = mTelephonyManager.getNetworkOperatorName();
4131 icon = R.drawable.stat_notify_rssi_in_range;
4132 break;
4133 default:
4134 log("setNotificationVisible: other type=" + networkInfo.getType());
4135 title = r.getString(R.string.network_available_sign_in, 0);
4136 details = r.getString(R.string.network_available_sign_in_detailed,
4137 networkInfo.getExtraInfo());
4138 icon = R.drawable.stat_notify_rssi_in_range;
4139 break;
4140 }
4141
4142 Notification notification = new Notification();
4143 notification.when = 0;
4144 notification.icon = icon;
4145 notification.flags = Notification.FLAG_AUTO_CANCEL;
4146 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
4147 intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
4148 Intent.FLAG_ACTIVITY_NEW_TASK);
4149 notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
4150 notification.tickerText = title;
4151 notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
4152
4153 log("setNotificaitionVisible: notify notificaiton=" + notification);
4154 notificationManager.notify(NOTIFICATION_ID, 1, notification);
4155 } else {
4156 log("setNotificaitionVisible: cancel");
4157 notificationManager.cancel(NOTIFICATION_ID, 1);
4158 }
4159 log("setNotificationVisible: X visible=" + visible + " ni=" + networkInfo + " url=" + url);
4160 }
4161
Robert Greenwalt39d56012013-07-16 12:06:09 -07004162 /** Location to an updatable file listing carrier provisioning urls.
4163 * An example:
4164 *
4165 * <?xml version="1.0" encoding="utf-8"?>
4166 * <provisioningUrls>
4167 * <provisioningUrl mcc="310" mnc="4">http://myserver.com/foo?mdn=%3$s&amp;iccid=%1$s&amp;imei=%2$s</provisioningUrl>
4168 * <redirectedUrl mcc="310" mnc="4">http://www.google.com</redirectedUrl>
4169 * </provisioningUrls>
4170 */
4171 private static final String PROVISIONING_URL_PATH =
4172 "/data/misc/radio/provisioning_urls.xml";
4173 private final File mProvisioningUrlFile = new File(PROVISIONING_URL_PATH);
Wink Saville32506bc2013-06-29 21:10:57 -07004174
Robert Greenwalt39d56012013-07-16 12:06:09 -07004175 /** XML tag for root element. */
4176 private static final String TAG_PROVISIONING_URLS = "provisioningUrls";
4177 /** XML tag for individual url */
4178 private static final String TAG_PROVISIONING_URL = "provisioningUrl";
4179 /** XML tag for redirected url */
4180 private static final String TAG_REDIRECTED_URL = "redirectedUrl";
4181 /** XML attribute for mcc */
4182 private static final String ATTR_MCC = "mcc";
4183 /** XML attribute for mnc */
4184 private static final String ATTR_MNC = "mnc";
4185
4186 private static final int REDIRECTED_PROVISIONING = 1;
4187 private static final int PROVISIONING = 2;
4188
4189 private String getProvisioningUrlBaseFromFile(int type) {
4190 FileReader fileReader = null;
4191 XmlPullParser parser = null;
4192 Configuration config = mContext.getResources().getConfiguration();
4193 String tagType;
4194
4195 switch (type) {
4196 case PROVISIONING:
4197 tagType = TAG_PROVISIONING_URL;
4198 break;
4199 case REDIRECTED_PROVISIONING:
4200 tagType = TAG_REDIRECTED_URL;
4201 break;
4202 default:
4203 throw new RuntimeException("getProvisioningUrlBaseFromFile: Unexpected parameter " +
4204 type);
4205 }
4206
4207 try {
4208 fileReader = new FileReader(mProvisioningUrlFile);
4209 parser = Xml.newPullParser();
4210 parser.setInput(fileReader);
4211 XmlUtils.beginDocument(parser, TAG_PROVISIONING_URLS);
4212
4213 while (true) {
4214 XmlUtils.nextElement(parser);
4215
4216 String element = parser.getName();
4217 if (element == null) break;
4218
4219 if (element.equals(tagType)) {
4220 String mcc = parser.getAttributeValue(null, ATTR_MCC);
4221 try {
4222 if (mcc != null && Integer.parseInt(mcc) == config.mcc) {
4223 String mnc = parser.getAttributeValue(null, ATTR_MNC);
4224 if (mnc != null && Integer.parseInt(mnc) == config.mnc) {
4225 parser.next();
4226 if (parser.getEventType() == XmlPullParser.TEXT) {
4227 return parser.getText();
4228 }
4229 }
4230 }
4231 } catch (NumberFormatException e) {
4232 loge("NumberFormatException in getProvisioningUrlBaseFromFile: " + e);
4233 }
4234 }
4235 }
4236 return null;
4237 } catch (FileNotFoundException e) {
4238 loge("Carrier Provisioning Urls file not found");
4239 } catch (XmlPullParserException e) {
4240 loge("Xml parser exception reading Carrier Provisioning Urls file: " + e);
4241 } catch (IOException e) {
4242 loge("I/O exception reading Carrier Provisioning Urls file: " + e);
4243 } finally {
4244 if (fileReader != null) {
4245 try {
4246 fileReader.close();
4247 } catch (IOException e) {}
4248 }
4249 }
4250 return null;
4251 }
4252
4253 private String getMobileRedirectedProvisioningUrl() {
4254 String url = getProvisioningUrlBaseFromFile(REDIRECTED_PROVISIONING);
4255 if (TextUtils.isEmpty(url)) {
4256 url = mContext.getResources().getString(R.string.mobile_redirected_provisioning_url);
4257 }
4258 return url;
4259 }
4260
4261 public String getMobileProvisioningUrl() {
4262 enforceConnectivityInternalPermission();
4263 String url = getProvisioningUrlBaseFromFile(PROVISIONING);
4264 if (TextUtils.isEmpty(url)) {
4265 url = mContext.getResources().getString(R.string.mobile_provisioning_url);
4266 log("getProvisioningUrl: mobile_provisioining_url from resource =" + url);
4267 } else {
4268 log("getProvisioningUrl: mobile_provisioning_url from File =" + url);
4269 }
Wink Savillec118d7e2013-07-10 23:00:07 -07004270 // populate the iccid, imei and phone number in the provisioning url.
Wink Saville32506bc2013-06-29 21:10:57 -07004271 if (!TextUtils.isEmpty(url)) {
Wink Savillec118d7e2013-07-10 23:00:07 -07004272 String phoneNumber = mTelephonyManager.getLine1Number();
4273 if (TextUtils.isEmpty(phoneNumber)) {
4274 phoneNumber = "0000000000";
4275 }
Wink Saville32506bc2013-06-29 21:10:57 -07004276 url = String.format(url,
4277 mTelephonyManager.getSimSerialNumber() /* ICCID */,
4278 mTelephonyManager.getDeviceId() /* IMEI */,
Wink Savillec118d7e2013-07-10 23:00:07 -07004279 phoneNumber /* Phone numer */);
Wink Saville32506bc2013-06-29 21:10:57 -07004280 }
4281
Wink Saville32506bc2013-06-29 21:10:57 -07004282 return url;
4283 }
Chad Brubakerb7652cd2013-06-14 11:16:51 -07004284
4285 private void onUserStart(int userId) {
4286 synchronized(mVpns) {
4287 Vpn userVpn = mVpns.get(userId);
4288 if (userVpn != null) {
4289 loge("Starting user already has a VPN");
4290 return;
4291 }
4292 userVpn = new Vpn(mContext, mVpnCallback, mNetd, this, userId);
4293 mVpns.put(userId, userVpn);
4294 userVpn.startMonitoring(mContext, mTrackerHandler);
4295 }
4296 }
4297
4298 private void onUserStop(int userId) {
4299 synchronized(mVpns) {
4300 Vpn userVpn = mVpns.get(userId);
4301 if (userVpn == null) {
4302 loge("Stopping user has no VPN");
4303 return;
4304 }
4305 mVpns.delete(userId);
4306 }
4307 }
4308
4309 private BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
4310 @Override
4311 public void onReceive(Context context, Intent intent) {
4312 final String action = intent.getAction();
4313 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
4314 if (userId == UserHandle.USER_NULL) return;
4315
4316 if (Intent.ACTION_USER_STARTING.equals(action)) {
4317 onUserStart(userId);
4318 } else if (Intent.ACTION_USER_STOPPING.equals(action)) {
4319 onUserStop(userId);
4320 }
4321 }
4322 };
The Android Open Source Project28527d22009-03-03 19:31:44 -08004323}