blob: e2956ddfd432c9d09835f0a44940b3232547f18b [file] [log] [blame]
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001/*
2 * Copyright (C) 2010 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.connectivity;
18
Erik Kline2e88b5e2017-01-18 11:57:45 +090019import static android.hardware.usb.UsbManager.USB_CONNECTED;
20import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
Erik Kline93c4afa2017-06-04 11:36:01 +090021import static android.net.ConnectivityManager.getNetworkTypeName;
Erik Kline2efb8272017-05-31 15:53:53 +090022import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
23import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
Erik Kline2e88b5e2017-01-18 11:57:45 +090024import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
Erik Kline2efb8272017-05-31 15:53:53 +090025import static android.net.wifi.WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR;
26import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
27import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
28import static android.net.wifi.WifiManager.IFACE_IP_MODE_UNSPECIFIED;
Erik Kline2e88b5e2017-01-18 11:57:45 +090029import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
Erik Kline7747fd42017-05-12 16:52:48 +090030import static com.android.server.ConnectivityService.SHORT_ARG;
Erik Kline2e88b5e2017-01-18 11:57:45 +090031
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080032import android.app.Notification;
33import android.app.NotificationManager;
34import android.app.PendingIntent;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080035import android.bluetooth.BluetoothAdapter;
36import android.bluetooth.BluetoothPan;
37import android.bluetooth.BluetoothProfile;
38import android.bluetooth.BluetoothProfile.ServiceListener;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080039import android.content.BroadcastReceiver;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -080040import android.content.ComponentName;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080041import android.content.Context;
42import android.content.Intent;
43import android.content.IntentFilter;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080044import android.content.pm.PackageManager;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080045import android.content.res.Resources;
Mike Lockwoodc4308f02011-03-01 08:04:54 -080046import android.hardware.usb.UsbManager;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080047import android.net.ConnectivityManager;
Christopher Wileydeebfec2016-09-16 11:14:36 -070048import android.net.INetworkPolicyManager;
Jeff Sharkey367d15a2011-09-22 14:59:51 -070049import android.net.INetworkStatsService;
Erik Kline3a5278f2017-06-24 19:29:10 +090050import android.net.IpPrefix;
Robert Greenwalt05d89362011-01-23 16:04:05 -080051import android.net.LinkProperties;
Lorenzo Colittib57edc52014-08-22 17:10:50 -070052import android.net.Network;
Erik Kline0c9cb2b2015-11-20 17:47:08 +090053import android.net.NetworkCapabilities;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080054import android.net.NetworkInfo;
Erik Kline0c9cb2b2015-11-20 17:47:08 +090055import android.net.NetworkRequest;
Erik Kline6ff17f72015-12-10 20:42:12 +090056import android.net.NetworkState;
Robert Greenwalte5903732011-02-22 16:00:42 -080057import android.net.NetworkUtils;
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090058import android.net.RouteInfo;
Erik Kline7747fd42017-05-12 16:52:48 +090059import android.net.util.SharedLog;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080060import android.net.wifi.WifiManager;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080061import android.os.Binder;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080062import android.os.Bundle;
Erik Klinef4b6e342017-04-25 19:19:59 +090063import android.os.Handler;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080064import android.os.INetworkManagementService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -080065import android.os.Looper;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080066import android.os.Message;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080067import android.os.Parcel;
Christopher Wileydeebfec2016-09-16 11:14:36 -070068import android.os.RemoteException;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080069import android.os.ResultReceiver;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070070import android.os.UserHandle;
Jeremy Klein15f3d212016-01-24 17:01:09 -080071import android.provider.Settings;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080072import android.telephony.CarrierConfigManager;
Junda Liu38531582014-10-28 13:52:51 -070073import android.telephony.TelephonyManager;
Lorenzo Colitticd63d242016-04-10 15:39:53 +090074import android.text.TextUtils;
Christopher Wileye9490392016-05-26 15:57:29 -070075import android.util.ArrayMap;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080076import android.util.Log;
Lorenzo Colitticd63d242016-04-10 15:39:53 +090077import android.util.SparseArray;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080078
Christopher Wiley497c1472016-10-11 13:26:03 -070079import com.android.internal.annotations.VisibleForTesting;
Chris Wren282cfef2017-03-27 15:01:44 -040080import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
Geoffrey Pitschaf759c52017-02-15 09:35:38 -050081import com.android.internal.notification.SystemNotificationChannels;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -080082import com.android.internal.telephony.IccCardConstants;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -080083import com.android.internal.telephony.TelephonyIntents;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060084import com.android.internal.util.DumpUtils;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080085import com.android.internal.util.IndentingPrintWriter;
Lorenzo Colitticd63d242016-04-10 15:39:53 +090086import com.android.internal.util.MessageUtils;
87import com.android.internal.util.Protocol;
Wink Saville64c42ca2011-04-18 14:55:10 -070088import com.android.internal.util.State;
89import com.android.internal.util.StateMachine;
Christopher Wileye03fb442016-05-18 13:45:20 -070090import com.android.server.connectivity.tethering.IControlsTethering;
Erik Kline1eb8c692016-07-08 17:21:26 +090091import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Klinee0cce212017-03-06 14:05:23 +090092import com.android.server.connectivity.tethering.OffloadController;
Erik Kline227648f2017-01-20 20:26:10 +090093import com.android.server.connectivity.tethering.SimChangeListener;
Mitchell Wills7040b4e2016-05-23 16:40:10 -070094import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
Hugo Benichib55fb222017-03-10 14:20:57 +090095import com.android.server.connectivity.tethering.TetheringConfiguration;
Erik Kline47222fc2017-04-30 19:36:15 +090096import com.android.server.connectivity.tethering.TetheringDependencies;
Erik Kline9bba3402017-01-13 16:46:52 +090097import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Lorenzo Colittif4e90ea2013-10-31 23:30:47 +090098import com.android.server.net.BaseNetworkObserver;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080099
100import java.io.FileDescriptor;
101import java.io.PrintWriter;
Robert Greenwalt4f74d552011-12-19 16:59:31 -0800102import java.net.Inet4Address;
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800103import java.net.InetAddress;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800104import java.util.ArrayList;
Lorenzo Colittib57edc52014-08-22 17:10:50 -0700105import java.util.Arrays;
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700106import java.util.Collection;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800107import java.util.HashMap;
Erik Klineea9cc482017-03-10 19:35:34 +0900108import java.util.HashSet;
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700109import java.util.Iterator;
Erik Klineea9cc482017-03-10 19:35:34 +0900110import java.util.Map;
Erik Kline3a5278f2017-06-24 19:29:10 +0900111import java.util.Set;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800112import java.util.concurrent.atomic.AtomicInteger;
113
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700114
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800115/**
116 * @hide
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800117 *
Christopher Wiley3b1d9222016-05-20 16:44:04 -0700118 * This class holds much of the business logic to allow Android devices
119 * to act as IP gateways via USB, BT, and WiFi interfaces.
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800120 */
Erik Kline6e9a1012017-06-06 19:24:21 +0900121public class Tethering extends BaseNetworkObserver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800122
Hugo Benichib55fb222017-03-10 14:20:57 +0900123 private final static String TAG = Tethering.class.getSimpleName();
Joe Onorato12acbd72016-02-01 17:49:31 -0800124 private final static boolean DBG = false;
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800125 private final static boolean VDBG = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800126
Christopher Wiley497c1472016-10-11 13:26:03 -0700127 protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning";
128
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900129 private static final Class[] messageClasses = {
Mitchell Wills7040b4e2016-05-23 16:40:10 -0700130 Tethering.class, TetherMasterSM.class, TetherInterfaceStateMachine.class
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900131 };
132 private static final SparseArray<String> sMagicDecoderRing =
133 MessageUtils.findMessageNames(messageClasses);
134
Hugo Benichib55fb222017-03-10 14:20:57 +0900135 // {@link ComponentName} of the Service used to run tether provisioning.
136 private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources
137 .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
138
139 private static class TetherState {
140 public final TetherInterfaceStateMachine stateMachine;
141 public int lastState;
142 public int lastError;
Erik Klineea9cc482017-03-10 19:35:34 +0900143
Hugo Benichib55fb222017-03-10 14:20:57 +0900144 public TetherState(TetherInterfaceStateMachine sm) {
145 stateMachine = sm;
146 // Assume all state machines start out available and with no errors.
147 lastState = IControlsTethering.STATE_AVAILABLE;
148 lastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
149 }
Erik Klineea9cc482017-03-10 19:35:34 +0900150
151 public boolean isCurrentlyServing() {
152 switch (lastState) {
153 case IControlsTethering.STATE_TETHERED:
Erik Klineca41be72017-04-20 22:59:16 +0900154 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Klineea9cc482017-03-10 19:35:34 +0900155 return true;
156 default:
157 return false;
158 }
159 }
Hugo Benichib55fb222017-03-10 14:20:57 +0900160 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700161
Erik Kline7747fd42017-05-12 16:52:48 +0900162 private final SharedLog mLog = new SharedLog(TAG);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900163
Robert Greenwaltb4453622011-11-03 16:01:40 -0700164 // used to synchronize public access to members
Erik Kline6ff17f72015-12-10 20:42:12 +0900165 private final Object mPublicSync;
Hugo Benichib55fb222017-03-10 14:20:57 +0900166 private final Context mContext;
167 private final ArrayMap<String, TetherState> mTetherStates;
168 private final BroadcastReceiver mStateReceiver;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700169 private final INetworkManagementService mNMService;
170 private final INetworkStatsService mStatsService;
Christopher Wileydeebfec2016-09-16 11:14:36 -0700171 private final INetworkPolicyManager mPolicyManager;
Erik Kline6ff17f72015-12-10 20:42:12 +0900172 private final Looper mLooper;
Christopher Wiley497c1472016-10-11 13:26:03 -0700173 private final MockableSystemProperties mSystemProperties;
Erik Kline6ff17f72015-12-10 20:42:12 +0900174 private final StateMachine mTetherMasterSM;
Erik Klinee0cce212017-03-06 14:05:23 +0900175 private final OffloadController mOffloadController;
Erik Kline6ff17f72015-12-10 20:42:12 +0900176 private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
Erik Kline6e9a1012017-06-06 19:24:21 +0900177 // TODO: Figure out how to merge this and other downstream-tracking objects
178 // into a single coherent structure.
Erik Klineea9cc482017-03-10 19:35:34 +0900179 private final HashSet<TetherInterfaceStateMachine> mForwardedDownstreams;
Erik Kline227648f2017-01-20 20:26:10 +0900180 private final SimChangeListener mSimChange;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800181
Hugo Benichib55fb222017-03-10 14:20:57 +0900182 private volatile TetheringConfiguration mConfig;
183 private String mCurrentUpstreamIface;
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400184 private Notification.Builder mTetheredNotificationBuilder;
185 private int mLastNotificationId;
Erik Klineea9cc482017-03-10 19:35:34 +0900186
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700187 private boolean mRndisEnabled; // track the RNDIS function enabled state
188 private boolean mUsbTetherRequested; // true if USB tethering should be started
189 // when RNDIS is enabled
Erik Kline6e9a1012017-06-06 19:24:21 +0900190 // True iff. WiFi tethering should be started when soft AP is ready.
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700191 private boolean mWifiTetherRequested;
192
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700193 public Tethering(Context context, INetworkManagementService nmService,
Christopher Wiley497c1472016-10-11 13:26:03 -0700194 INetworkStatsService statsService, INetworkPolicyManager policyManager,
Erik Kline47222fc2017-04-30 19:36:15 +0900195 Looper looper, MockableSystemProperties systemProperties,
196 TetheringDependencies deps) {
Erik Kline7747fd42017-05-12 16:52:48 +0900197 mLog.mark("constructed");
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800198 mContext = context;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700199 mNMService = nmService;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700200 mStatsService = statsService;
Christopher Wileydeebfec2016-09-16 11:14:36 -0700201 mPolicyManager = policyManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700202 mLooper = looper;
203 mSystemProperties = systemProperties;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800204
Robert Greenwaltb4453622011-11-03 16:01:40 -0700205 mPublicSync = new Object();
206
Christopher Wileyd985dde2016-05-31 10:44:35 -0700207 mTetherStates = new ArrayMap<>();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800208
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800209 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800210 mTetherMasterSM.start();
211
Erik Klinef4b6e342017-04-25 19:19:59 +0900212 final Handler smHandler = mTetherMasterSM.getHandler();
213 mOffloadController = new OffloadController(smHandler,
214 deps.getOffloadHardwareInterface(smHandler, mLog),
Erik Kline92c4db02017-05-31 10:21:32 +0900215 mContext.getContentResolver(),
Erik Klinef4b6e342017-04-25 19:19:59 +0900216 mLog);
Erik Klineebdb8c82017-01-10 17:37:54 +0900217 mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
Erik Kline3a5278f2017-06-24 19:29:10 +0900218 mContext, mTetherMasterSM, mLog, TetherMasterSM.EVENT_UPSTREAM_CALLBACK );
Erik Klineea9cc482017-03-10 19:35:34 +0900219 mForwardedDownstreams = new HashSet<>();
Erik Kline227648f2017-01-20 20:26:10 +0900220 mSimChange = new SimChangeListener(
221 mContext, mTetherMasterSM.getHandler(), () -> reevaluateSimCardProvisioning());
Erik Kline6ff17f72015-12-10 20:42:12 +0900222
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800223 mStateReceiver = new StateReceiver();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800224 IntentFilter filter = new IntentFilter();
Mike Lockwood770126a2010-12-09 22:30:37 -0800225 filter.addAction(UsbManager.ACTION_USB_STATE);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800226 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700227 filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700228 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
Erik Kline2e88b5e2017-01-18 11:57:45 +0900229 mContext.registerReceiver(mStateReceiver, filter, null, mTetherMasterSM.getHandler());
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800230
231 filter = new IntentFilter();
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800232 filter.addAction(Intent.ACTION_MEDIA_SHARED);
233 filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800234 filter.addDataScheme("file");
Erik Kline2e88b5e2017-01-18 11:57:45 +0900235 mContext.registerReceiver(mStateReceiver, filter, null, mTetherMasterSM.getHandler());
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800236
Robert Greenwalt49348e72011-10-21 16:54:26 -0700237 // load device config info
238 updateConfiguration();
Robert Greenwalt49348e72011-10-21 16:54:26 -0700239 }
240
Sreeram Ramachandran62a61312014-07-24 16:05:17 -0700241 // We can't do this once in the Tethering() constructor and cache the value, because the
242 // CONNECTIVITY_SERVICE is registered only after the Tethering() constructor has completed.
243 private ConnectivityManager getConnectivityManager() {
244 return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
245 }
246
Erik Kline216af6d2017-04-27 20:57:23 +0900247 private WifiManager getWifiManager() {
248 return (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
249 }
250
Erik Kline93c4afa2017-06-04 11:36:01 +0900251 // NOTE: This is always invoked on the mLooper thread.
Erik Klined781fba2017-01-23 13:01:58 +0900252 private void updateConfiguration() {
Erik Kline6bd74532017-05-19 10:10:41 +0900253 mConfig = new TetheringConfiguration(mContext, mLog);
Erik Kline93c4afa2017-06-04 11:36:01 +0900254 mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800255 }
256
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900257 @Override
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700258 public void interfaceStatusChanged(String iface, boolean up) {
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900259 // Never called directly: only called from interfaceLinkStateChanged.
260 // See NetlinkHandler.cpp:71.
Wink Savillec9acde92011-09-21 11:05:43 -0700261 if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700262 synchronized (mPublicSync) {
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700263 if (up) {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900264 maybeTrackNewInterfaceLocked(iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800265 } else {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900266 if (ifaceNameToType(iface) == ConnectivityManager.TETHERING_BLUETOOTH) {
267 stopTrackingInterfaceLocked(iface);
Christopher Wileyd30aaeb2016-07-08 09:33:50 -0700268 } else {
269 // Ignore usb0 down after enabling RNDIS.
270 // We will handle disconnect in interfaceRemoved.
271 // Similarly, ignore interface down for WiFi. We monitor WiFi AP status
272 // through the WifiManager.WIFI_AP_STATE_CHANGED_ACTION intent.
273 if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800274 }
275 }
276 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800277 }
278
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900279 @Override
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700280 public void interfaceLinkStateChanged(String iface, boolean up) {
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700281 interfaceStatusChanged(iface, up);
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700282 }
283
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700284 private int ifaceNameToType(String iface) {
Erik Kline3e756652017-01-17 13:42:19 +0900285 final TetheringConfiguration cfg = mConfig;
286
287 if (cfg.isWifi(iface)) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700288 return ConnectivityManager.TETHERING_WIFI;
Erik Kline3e756652017-01-17 13:42:19 +0900289 } else if (cfg.isUsb(iface)) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700290 return ConnectivityManager.TETHERING_USB;
Erik Kline3e756652017-01-17 13:42:19 +0900291 } else if (cfg.isBluetooth(iface)) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700292 return ConnectivityManager.TETHERING_BLUETOOTH;
293 }
294 return ConnectivityManager.TETHERING_INVALID;
295 }
296
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900297 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800298 public void interfaceAdded(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700299 if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700300 synchronized (mPublicSync) {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900301 maybeTrackNewInterfaceLocked(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800302 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800303 }
304
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900305 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800306 public void interfaceRemoved(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700307 if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700308 synchronized (mPublicSync) {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900309 stopTrackingInterfaceLocked(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800310 }
311 }
312
Hugo Benichib55fb222017-03-10 14:20:57 +0900313 public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800314 if (!isTetherProvisioningRequired()) {
315 enableTetheringInternal(type, true, receiver);
316 return;
317 }
318
319 if (showProvisioningUi) {
320 runUiTetherProvisioningAndEnable(type, receiver);
321 } else {
322 runSilentTetherProvisioningAndEnable(type, receiver);
323 }
324 }
325
326 public void stopTethering(int type) {
327 enableTetheringInternal(type, false, null);
328 if (isTetherProvisioningRequired()) {
329 cancelTetherProvisioningRechecks(type);
330 }
331 }
332
333 /**
334 * Check if the device requires a provisioning check in order to enable tethering.
335 *
336 * @return a boolean - {@code true} indicating tether provisioning is required by the carrier.
337 */
Christopher Wiley497c1472016-10-11 13:26:03 -0700338 @VisibleForTesting
339 protected boolean isTetherProvisioningRequired() {
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800340 String[] provisionApp = mContext.getResources().getStringArray(
341 com.android.internal.R.array.config_mobile_hotspot_provision_app);
Christopher Wiley497c1472016-10-11 13:26:03 -0700342 if (mSystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false)
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800343 || provisionApp == null) {
344 return false;
345 }
346
347 // Check carrier config for entitlement checks
348 final CarrierConfigManager configManager = (CarrierConfigManager) mContext
349 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
Rebecca Silbersteinb07f1402016-10-04 13:53:33 -0700350 if (configManager != null && configManager.getConfig() != null) {
351 // we do have a CarrierConfigManager and it has a config.
352 boolean isEntitlementCheckRequired = configManager.getConfig().getBoolean(
353 CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
354 if (!isEntitlementCheckRequired) {
355 return false;
356 }
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800357 }
358 return (provisionApp.length == 2);
359 }
360
Erik Kline227648f2017-01-20 20:26:10 +0900361 // Used by the SIM card change observation code.
362 // TODO: De-duplicate above code.
363 private boolean hasMobileHotspotProvisionApp() {
364 try {
365 if (!mContext.getResources().getString(com.android.internal.R.string.
366 config_mobile_hotspot_provision_app_no_ui).isEmpty()) {
367 Log.d(TAG, "re-evaluate provisioning");
368 return true;
369 }
370 } catch (Resources.NotFoundException e) {}
371 Log.d(TAG, "no prov-check needed for new SIM");
372 return false;
373 }
374
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800375 /**
376 * Enables or disables tethering for the given type. This should only be called once
377 * provisioning has succeeded or is not necessary. It will also schedule provisioning rechecks
378 * for the specified interface.
379 */
380 private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700381 boolean isProvisioningRequired = enable && isTetherProvisioningRequired();
382 int result;
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800383 switch (type) {
384 case ConnectivityManager.TETHERING_WIFI:
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700385 result = setWifiTethering(enable);
386 if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
387 scheduleProvisioningRechecks(type);
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800388 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700389 sendTetherResult(receiver, result);
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800390 break;
391 case ConnectivityManager.TETHERING_USB:
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700392 result = setUsbTethering(enable);
393 if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800394 scheduleProvisioningRechecks(type);
395 }
396 sendTetherResult(receiver, result);
397 break;
398 case ConnectivityManager.TETHERING_BLUETOOTH:
399 setBluetoothTethering(enable, receiver);
400 break;
401 default:
402 Log.w(TAG, "Invalid tether type.");
403 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE);
404 }
405 }
406
407 private void sendTetherResult(ResultReceiver receiver, int result) {
408 if (receiver != null) {
409 receiver.send(result, null);
410 }
411 }
412
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700413 private int setWifiTethering(final boolean enable) {
Erik Kline256be782017-04-29 13:20:04 +0900414 int rval = ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
415 final long ident = Binder.clearCallingIdentity();
416 try {
417 synchronized (mPublicSync) {
418 mWifiTetherRequested = enable;
419 final WifiManager mgr = getWifiManager();
420 if ((enable && mgr.startSoftAp(null /* use existing wifi config */)) ||
421 (!enable && mgr.stopSoftAp())) {
422 rval = ConnectivityManager.TETHER_ERROR_NO_ERROR;
423 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700424 }
Erik Kline256be782017-04-29 13:20:04 +0900425 } finally {
426 Binder.restoreCallingIdentity(ident);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700427 }
Erik Kline256be782017-04-29 13:20:04 +0900428 return rval;
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700429 }
430
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800431 private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) {
432 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
433 if (adapter == null || !adapter.isEnabled()) {
434 Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: " +
435 (adapter == null));
436 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL);
437 return;
438 }
439
440 adapter.getProfileProxy(mContext, new ServiceListener() {
441 @Override
442 public void onServiceDisconnected(int profile) { }
443
444 @Override
445 public void onServiceConnected(int profile, BluetoothProfile proxy) {
446 ((BluetoothPan) proxy).setBluetoothTethering(enable);
447 // TODO: Enabling bluetooth tethering can fail asynchronously here.
448 // We should figure out a way to bubble up that failure instead of sending success.
Jeremy Klein45ae04a2016-02-05 10:37:32 -0800449 int result = ((BluetoothPan) proxy).isTetheringOn() == enable ?
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800450 ConnectivityManager.TETHER_ERROR_NO_ERROR :
451 ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
452 sendTetherResult(receiver, result);
453 if (enable && isTetherProvisioningRequired()) {
454 scheduleProvisioningRechecks(ConnectivityManager.TETHERING_BLUETOOTH);
455 }
456 adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
457 }
458 }, BluetoothProfile.PAN);
459 }
460
461 private void runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
Jeremy Klein15f3d212016-01-24 17:01:09 -0800462 ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
463 sendUiTetherProvisionIntent(type, proxyReceiver);
464 }
465
466 private void sendUiTetherProvisionIntent(int type, ResultReceiver receiver) {
467 Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
468 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
469 intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver);
470 final long ident = Binder.clearCallingIdentity();
471 try {
472 mContext.startActivityAsUser(intent, UserHandle.CURRENT);
473 } finally {
474 Binder.restoreCallingIdentity(ident);
475 }
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800476 }
477
478 /**
Erik Klinefdd41112017-01-12 17:02:51 +0900479 * Creates a proxy {@link ResultReceiver} which enables tethering if the provisioning result
480 * is successful before firing back up to the wrapped receiver.
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800481 *
482 * @param type The type of tethering being enabled.
483 * @param receiver A ResultReceiver which will be called back with an int resultCode.
484 * @return The proxy receiver.
485 */
486 private ResultReceiver getProxyReceiver(final int type, final ResultReceiver receiver) {
487 ResultReceiver rr = new ResultReceiver(null) {
488 @Override
489 protected void onReceiveResult(int resultCode, Bundle resultData) {
490 // If provisioning is successful, enable tethering, otherwise just send the error.
491 if (resultCode == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
492 enableTetheringInternal(type, true, receiver);
493 } else {
494 sendTetherResult(receiver, resultCode);
495 }
496 }
497 };
498
499 // The following is necessary to avoid unmarshalling issues when sending the receiver
Erik Kline6ff17f72015-12-10 20:42:12 +0900500 // across processes.
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800501 Parcel parcel = Parcel.obtain();
502 rr.writeToParcel(parcel,0);
503 parcel.setDataPosition(0);
504 ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel);
505 parcel.recycle();
506 return receiverForSending;
507 }
508
509 private void scheduleProvisioningRechecks(int type) {
510 Intent intent = new Intent();
511 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
512 intent.putExtra(ConnectivityManager.EXTRA_SET_ALARM, true);
513 intent.setComponent(TETHER_SERVICE);
514 final long ident = Binder.clearCallingIdentity();
515 try {
516 mContext.startServiceAsUser(intent, UserHandle.CURRENT);
517 } finally {
518 Binder.restoreCallingIdentity(ident);
519 }
520 }
521
522 private void runSilentTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
523 ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
524 sendSilentTetherProvisionIntent(type, proxyReceiver);
525 }
526
527 private void sendSilentTetherProvisionIntent(int type, ResultReceiver receiver) {
528 Intent intent = new Intent();
529 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
530 intent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
531 intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver);
532 intent.setComponent(TETHER_SERVICE);
533 final long ident = Binder.clearCallingIdentity();
534 try {
535 mContext.startServiceAsUser(intent, UserHandle.CURRENT);
536 } finally {
537 Binder.restoreCallingIdentity(ident);
538 }
539 }
540
541 private void cancelTetherProvisioningRechecks(int type) {
542 if (getConnectivityManager().isTetheringSupported()) {
543 Intent intent = new Intent();
544 intent.putExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE, type);
545 intent.setComponent(TETHER_SERVICE);
546 final long ident = Binder.clearCallingIdentity();
547 try {
548 mContext.startServiceAsUser(intent, UserHandle.CURRENT);
549 } finally {
550 Binder.restoreCallingIdentity(ident);
551 }
552 }
553 }
Erik Kline6ff17f72015-12-10 20:42:12 +0900554
Erik Kline227648f2017-01-20 20:26:10 +0900555 // Used by the SIM card change observation code.
556 // TODO: De-duplicate with above code, where possible.
557 private void startProvisionIntent(int tetherType) {
558 final Intent startProvIntent = new Intent();
559 startProvIntent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType);
560 startProvIntent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
561 startProvIntent.setComponent(TETHER_SERVICE);
562 mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT);
563 }
564
Robert Greenwalt5a735062010-03-02 17:25:02 -0800565 public int tether(String iface) {
Erik Klineea9cc482017-03-10 19:35:34 +0900566 return tether(iface, IControlsTethering.STATE_TETHERED);
567 }
568
569 private int tether(String iface, int requestedState) {
Wink Savillec9acde92011-09-21 11:05:43 -0700570 if (DBG) Log.d(TAG, "Tethering " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700571 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700572 TetherState tetherState = mTetherStates.get(iface);
573 if (tetherState == null) {
Erik Kline00019f42016-06-30 19:31:46 +0900574 Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring");
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700575 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
576 }
577 // Ignore the error status of the interface. If the interface is available,
578 // the errors are referring to past tethering attempts anyway.
Hugo Benichib55fb222017-03-10 14:20:57 +0900579 if (tetherState.lastState != IControlsTethering.STATE_AVAILABLE) {
Erik Kline00019f42016-06-30 19:31:46 +0900580 Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700581 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700582 }
Erik Klineea9cc482017-03-10 19:35:34 +0900583 // NOTE: If a CMD_TETHER_REQUESTED message is already in the TISM's
584 // queue but not yet processed, this will be a no-op and it will not
585 // return an error.
586 //
587 // TODO: reexamine the threading and messaging model.
588 tetherState.stateMachine.sendMessage(
589 TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, requestedState);
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700590 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800591 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800592 }
593
Robert Greenwalt5a735062010-03-02 17:25:02 -0800594 public int untether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700595 if (DBG) Log.d(TAG, "Untethering " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700596 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700597 TetherState tetherState = mTetherStates.get(iface);
598 if (tetherState == null) {
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700599 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
600 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
601 }
Erik Klineea9cc482017-03-10 19:35:34 +0900602 if (!tetherState.isCurrentlyServing()) {
603 Log.e(TAG, "Tried to untether an inactive iface :" + iface + ", ignoring");
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700604 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
605 }
Hugo Benichib55fb222017-03-10 14:20:57 +0900606 tetherState.stateMachine.sendMessage(
Christopher Wileyd985dde2016-05-31 10:44:35 -0700607 TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700608 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800609 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800610 }
611
Felipe Leme70c8b9b2016-04-25 14:41:31 -0700612 public void untetherAll() {
Christopher Wileyfa6a4862016-09-19 08:58:06 -0700613 stopTethering(ConnectivityManager.TETHERING_WIFI);
614 stopTethering(ConnectivityManager.TETHERING_USB);
615 stopTethering(ConnectivityManager.TETHERING_BLUETOOTH);
Felipe Leme70c8b9b2016-04-25 14:41:31 -0700616 }
617
Robert Greenwalt5a735062010-03-02 17:25:02 -0800618 public int getLastTetherError(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700619 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700620 TetherState tetherState = mTetherStates.get(iface);
621 if (tetherState == null) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700622 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
623 ", ignoring");
624 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
625 }
Hugo Benichib55fb222017-03-10 14:20:57 +0900626 return tetherState.lastError;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800627 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800628 }
629
Erik Klineea9cc482017-03-10 19:35:34 +0900630 // TODO: Figure out how to update for local hotspot mode interfaces.
Christopher Wileyd985dde2016-05-31 10:44:35 -0700631 private void sendTetherStateChangedBroadcast() {
Sreeram Ramachandran62a61312014-07-24 16:05:17 -0700632 if (!getConnectivityManager().isTetheringSupported()) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800633
Erik Kline8351faa2017-04-17 16:47:23 +0900634 final ArrayList<String> availableList = new ArrayList<>();
635 final ArrayList<String> tetherList = new ArrayList<>();
636 final ArrayList<String> localOnlyList = new ArrayList<>();
637 final ArrayList<String> erroredList = new ArrayList<>();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800638
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800639 boolean wifiTethered = false;
640 boolean usbTethered = false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700641 boolean bluetoothTethered = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800642
Erik Kline3e756652017-01-17 13:42:19 +0900643 final TetheringConfiguration cfg = mConfig;
644
Robert Greenwaltb4453622011-11-03 16:01:40 -0700645 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700646 for (int i = 0; i < mTetherStates.size(); i++) {
647 TetherState tetherState = mTetherStates.valueAt(i);
648 String iface = mTetherStates.keyAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +0900649 if (tetherState.lastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700650 erroredList.add(iface);
Hugo Benichib55fb222017-03-10 14:20:57 +0900651 } else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700652 availableList.add(iface);
Erik Klineca41be72017-04-20 22:59:16 +0900653 } else if (tetherState.lastState == IControlsTethering.STATE_LOCAL_ONLY) {
Erik Kline8351faa2017-04-17 16:47:23 +0900654 localOnlyList.add(iface);
Hugo Benichib55fb222017-03-10 14:20:57 +0900655 } else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
Erik Kline3e756652017-01-17 13:42:19 +0900656 if (cfg.isUsb(iface)) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700657 usbTethered = true;
Erik Kline3e756652017-01-17 13:42:19 +0900658 } else if (cfg.isWifi(iface)) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700659 wifiTethered = true;
Erik Kline3e756652017-01-17 13:42:19 +0900660 } else if (cfg.isBluetooth(iface)) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700661 bluetoothTethered = true;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800662 }
Erik Kline8351faa2017-04-17 16:47:23 +0900663 tetherList.add(iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800664 }
665 }
666 }
Erik Kline8351faa2017-04-17 16:47:23 +0900667 final Intent bcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
668 bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
Robert Greenwalt98c79e52011-07-28 11:51:11 -0700669 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Erik Kline8351faa2017-04-17 16:47:23 +0900670 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, availableList);
671 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList);
672 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, tetherList);
673 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, erroredList);
674 mContext.sendStickyBroadcastAsUser(bcast, UserHandle.ALL);
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800675 if (DBG) {
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900676 Log.d(TAG, String.format(
Erik Kline8351faa2017-04-17 16:47:23 +0900677 "sendTetherStateChangedBroadcast %s=[%s] %s=[%s] %s=[%s] %s=[%s]",
678 "avail", TextUtils.join(",", availableList),
679 "local_only", TextUtils.join(",", localOnlyList),
680 "tether", TextUtils.join(",", tetherList),
681 "error", TextUtils.join(",", erroredList)));
Robert Greenwalt924cc942010-06-28 10:26:19 -0700682 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800683
684 if (usbTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700685 if (wifiTethered || bluetoothTethered) {
Chris Wren282cfef2017-03-27 15:01:44 -0400686 showTetheredNotification(SystemMessage.NOTE_TETHER_GENERAL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800687 } else {
Chris Wren282cfef2017-03-27 15:01:44 -0400688 showTetheredNotification(SystemMessage.NOTE_TETHER_USB);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800689 }
690 } else if (wifiTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700691 if (bluetoothTethered) {
Chris Wren282cfef2017-03-27 15:01:44 -0400692 showTetheredNotification(SystemMessage.NOTE_TETHER_GENERAL);
Danica Chang6fdd0c62010-08-11 14:54:43 -0700693 } else {
Vinit Deshpande2576a802014-11-18 13:56:15 -0800694 /* We now have a status bar icon for WifiTethering, so drop the notification */
695 clearTetheredNotification();
Danica Chang6fdd0c62010-08-11 14:54:43 -0700696 }
697 } else if (bluetoothTethered) {
Chris Wren282cfef2017-03-27 15:01:44 -0400698 showTetheredNotification(SystemMessage.NOTE_TETHER_BLUETOOTH);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800699 } else {
700 clearTetheredNotification();
701 }
702 }
703
Chris Wren282cfef2017-03-27 15:01:44 -0400704 private void showTetheredNotification(int id) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800705 NotificationManager notificationManager =
706 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
707 if (notificationManager == null) {
708 return;
709 }
Chris Wren282cfef2017-03-27 15:01:44 -0400710 int icon = 0;
711 switch(id) {
712 case SystemMessage.NOTE_TETHER_USB:
713 icon = com.android.internal.R.drawable.stat_sys_tether_usb;
714 break;
715 case SystemMessage.NOTE_TETHER_BLUETOOTH:
716 icon = com.android.internal.R.drawable.stat_sys_tether_bluetooth;
717 break;
718 case SystemMessage.NOTE_TETHER_GENERAL:
719 default:
720 icon = com.android.internal.R.drawable.stat_sys_tether_general;
721 break;
722 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800723
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400724 if (mLastNotificationId != 0) {
725 if (mLastNotificationId == icon) {
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700726 return;
727 }
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400728 notificationManager.cancelAsUser(null, mLastNotificationId,
Robert Greenwalt3cab6b02012-10-04 16:44:26 -0700729 UserHandle.ALL);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400730 mLastNotificationId = 0;
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700731 }
732
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800733 Intent intent = new Intent();
734 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
735 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
736
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700737 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
738 null, UserHandle.CURRENT);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800739
740 Resources r = Resources.getSystem();
741 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
742 CharSequence message = r.getText(com.android.internal.R.string.
743 tethered_notification_message);
744
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400745 if (mTetheredNotificationBuilder == null) {
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500746 mTetheredNotificationBuilder =
747 new Notification.Builder(mContext, SystemNotificationChannels.NETWORK_STATUS);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400748 mTetheredNotificationBuilder.setWhen(0)
749 .setOngoing(true)
750 .setColor(mContext.getColor(
751 com.android.internal.R.color.system_notification_accent_color))
752 .setVisibility(Notification.VISIBILITY_PUBLIC)
753 .setCategory(Notification.CATEGORY_STATUS);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800754 }
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400755 mTetheredNotificationBuilder.setSmallIcon(icon)
756 .setContentTitle(title)
757 .setContentText(message)
758 .setContentIntent(pi);
Chris Wren282cfef2017-03-27 15:01:44 -0400759 mLastNotificationId = id;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800760
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400761 notificationManager.notifyAsUser(null, mLastNotificationId,
zhouzhijie130d4592017-05-18 10:02:59 +0800762 mTetheredNotificationBuilder.buildInto(new Notification()), UserHandle.ALL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800763 }
764
765 private void clearTetheredNotification() {
766 NotificationManager notificationManager =
767 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400768 if (notificationManager != null && mLastNotificationId != 0) {
769 notificationManager.cancelAsUser(null, mLastNotificationId,
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700770 UserHandle.ALL);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400771 mLastNotificationId = 0;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800772 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800773 }
774
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800775 private class StateReceiver extends BroadcastReceiver {
Nick Kralevich70c117a2014-05-27 15:30:02 -0700776 @Override
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800777 public void onReceive(Context content, Intent intent) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900778 final String action = intent.getAction();
779 if (action == null) return;
780
Mike Lockwood770126a2010-12-09 22:30:37 -0800781 if (action.equals(UsbManager.ACTION_USB_STATE)) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900782 handleUsbAction(intent);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800783 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900784 handleConnectivityAction(intent);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700785 } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900786 handleWifiApAction(intent);
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700787 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
788 updateConfiguration();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800789 }
790 }
Erik Kline2e88b5e2017-01-18 11:57:45 +0900791
792 private void handleConnectivityAction(Intent intent) {
793 final NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
794 ConnectivityManager.EXTRA_NETWORK_INFO);
795 if (networkInfo == null ||
796 networkInfo.getDetailedState() == NetworkInfo.DetailedState.FAILED) {
797 return;
798 }
799
800 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION: " + networkInfo.toString());
801 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
802 }
803
804 private void handleUsbAction(Intent intent) {
805 final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false);
806 final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false);
807 synchronized (Tethering.this.mPublicSync) {
808 mRndisEnabled = rndisEnabled;
809 // start tethering if we have a request pending
810 if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
Erik Klineea9cc482017-03-10 19:35:34 +0900811 tetherMatchingInterfaces(
812 IControlsTethering.STATE_TETHERED,
813 ConnectivityManager.TETHERING_USB);
Erik Kline2e88b5e2017-01-18 11:57:45 +0900814 }
815 mUsbTetherRequested = false;
816 }
817 }
818
819 private void handleWifiApAction(Intent intent) {
Erik Kline2efb8272017-05-31 15:53:53 +0900820 final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
821 final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
822 final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED);
823
Erik Kline2e88b5e2017-01-18 11:57:45 +0900824 synchronized (Tethering.this.mPublicSync) {
825 switch (curState) {
826 case WifiManager.WIFI_AP_STATE_ENABLING:
827 // We can see this state on the way to both enabled and failure states.
828 break;
829 case WifiManager.WIFI_AP_STATE_ENABLED:
Erik Kline2efb8272017-05-31 15:53:53 +0900830 enableWifiIpServingLocked(ifname, ipmode);
Erik Kline2e88b5e2017-01-18 11:57:45 +0900831 break;
832 case WifiManager.WIFI_AP_STATE_DISABLED:
833 case WifiManager.WIFI_AP_STATE_DISABLING:
834 case WifiManager.WIFI_AP_STATE_FAILED:
835 default:
Erik Kline562e0c12017-06-09 16:36:29 +0900836 disableWifiIpServingLocked(ifname, curState);
Erik Kline2efb8272017-05-31 15:53:53 +0900837 break;
Erik Kline2e88b5e2017-01-18 11:57:45 +0900838 }
839 }
840 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800841 }
842
Erik Kline562e0c12017-06-09 16:36:29 +0900843 private void disableWifiIpServingLocked(String ifname, int apState) {
844 mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState);
Erik Kline2efb8272017-05-31 15:53:53 +0900845
Erik Kline562e0c12017-06-09 16:36:29 +0900846 // Regardless of whether we requested this transition, the AP has gone
847 // down. Don't try to tether again unless we're requested to do so.
848 // TODO: Remove this altogether, once Wi-Fi reliably gives us an
849 // interface name with every broadcast.
850 mWifiTetherRequested = false;
851
852 if (!TextUtils.isEmpty(ifname)) {
853 final TetherState ts = mTetherStates.get(ifname);
854 if (ts != null) {
855 ts.stateMachine.unwanted();
856 return;
857 }
858 }
859
Erik Kline2efb8272017-05-31 15:53:53 +0900860 for (int i = 0; i < mTetherStates.size(); i++) {
861 TetherInterfaceStateMachine tism = mTetherStates.valueAt(i).stateMachine;
862 if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
Erik Kline562e0c12017-06-09 16:36:29 +0900863 tism.unwanted();
864 return;
Erik Kline2efb8272017-05-31 15:53:53 +0900865 }
866 }
Erik Kline562e0c12017-06-09 16:36:29 +0900867
868 mLog.log("Error disabling Wi-Fi IP serving; " +
869 (TextUtils.isEmpty(ifname) ? "no interface name specified"
870 : "specified interface: " + ifname));
Erik Kline2efb8272017-05-31 15:53:53 +0900871 }
872
873 private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
874 // Map wifiIpMode values to IControlsTethering serving states, inferring
875 // from mWifiTetherRequested as a final "best guess".
876 final int ipServingMode;
877 switch (wifiIpMode) {
878 case IFACE_IP_MODE_TETHERED:
879 ipServingMode = IControlsTethering.STATE_TETHERED;
880 break;
881 case IFACE_IP_MODE_LOCAL_ONLY:
882 ipServingMode = IControlsTethering.STATE_LOCAL_ONLY;
883 break;
884 default:
Erik Kline9e225542017-06-08 17:48:48 +0900885 mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode);
886 return;
Erik Kline2efb8272017-05-31 15:53:53 +0900887 }
888
889 if (!TextUtils.isEmpty(ifname)) {
Erik Klinea9cde8b2017-06-20 21:18:31 +0900890 maybeTrackNewInterfaceLocked(ifname, ConnectivityManager.TETHERING_WIFI);
Erik Kline2efb8272017-05-31 15:53:53 +0900891 changeInterfaceState(ifname, ipServingMode);
892 } else {
Erik Kline9e225542017-06-08 17:48:48 +0900893 mLog.e(String.format(
894 "Cannot enable IP serving in mode %s on missing interface name",
895 ipServingMode));
Erik Kline2efb8272017-05-31 15:53:53 +0900896 }
897 }
898
Erik Klineea9cc482017-03-10 19:35:34 +0900899 // TODO: Consider renaming to something more accurate in its description.
900 // This method:
901 // - allows requesting either tethering or local hotspot serving states
902 // - handles both enabling and disabling serving states
903 // - only tethers the first matching interface in listInterfaces()
904 // order of a given type
905 private void tetherMatchingInterfaces(int requestedState, int interfaceType) {
906 if (VDBG) {
907 Log.d(TAG, "tetherMatchingInterfaces(" + requestedState + ", " + interfaceType + ")");
908 }
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700909
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700910 String[] ifaces = null;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800911 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700912 ifaces = mNMService.listInterfaces();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800913 } catch (Exception e) {
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700914 Log.e(TAG, "Error listing Interfaces", e);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800915 return;
916 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700917 String chosenIface = null;
918 if (ifaces != null) {
919 for (String iface : ifaces) {
920 if (ifaceNameToType(iface) == interfaceType) {
921 chosenIface = iface;
922 break;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800923 }
924 }
925 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700926 if (chosenIface == null) {
927 Log.e(TAG, "could not find iface of type " + interfaceType);
928 return;
929 }
930
Erik Kline2efb8272017-05-31 15:53:53 +0900931 changeInterfaceState(chosenIface, requestedState);
932 }
933
934 private void changeInterfaceState(String ifname, int requestedState) {
Erik Klineea9cc482017-03-10 19:35:34 +0900935 final int result;
936 switch (requestedState) {
937 case IControlsTethering.STATE_UNAVAILABLE:
938 case IControlsTethering.STATE_AVAILABLE:
Erik Kline2efb8272017-05-31 15:53:53 +0900939 result = untether(ifname);
Erik Klineea9cc482017-03-10 19:35:34 +0900940 break;
941 case IControlsTethering.STATE_TETHERED:
Erik Klineca41be72017-04-20 22:59:16 +0900942 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Kline2efb8272017-05-31 15:53:53 +0900943 result = tether(ifname, requestedState);
Erik Klineea9cc482017-03-10 19:35:34 +0900944 break;
945 default:
946 Log.wtf(TAG, "Unknown interface state: " + requestedState);
947 return;
948 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700949 if (result != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Erik Kline2efb8272017-05-31 15:53:53 +0900950 Log.e(TAG, "unable start or stop tethering on iface " + ifname);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700951 return;
952 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800953 }
954
Erik Kline3e756652017-01-17 13:42:19 +0900955 public TetheringConfiguration getTetheringConfiguration() {
956 return mConfig;
957 }
958
Erik Klined781fba2017-01-23 13:01:58 +0900959 public boolean hasTetherableConfiguration() {
960 final TetheringConfiguration cfg = mConfig;
961 final boolean hasDownstreamConfiguration =
962 (cfg.tetherableUsbRegexs.length != 0) ||
963 (cfg.tetherableWifiRegexs.length != 0) ||
964 (cfg.tetherableBluetoothRegexs.length != 0);
965 final boolean hasUpstreamConfiguration = !cfg.preferredUpstreamIfaceTypes.isEmpty();
966
967 return hasDownstreamConfiguration && hasUpstreamConfiguration;
968 }
969
Erik Kline3e756652017-01-17 13:42:19 +0900970 // TODO - update callers to use getTetheringConfiguration(),
971 // which has only final members.
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800972 public String[] getTetherableUsbRegexs() {
Erik Kline3e756652017-01-17 13:42:19 +0900973 return copy(mConfig.tetherableUsbRegexs);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800974 }
975
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800976 public String[] getTetherableWifiRegexs() {
Erik Kline3e756652017-01-17 13:42:19 +0900977 return copy(mConfig.tetherableWifiRegexs);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800978 }
979
Danica Chang6fdd0c62010-08-11 14:54:43 -0700980 public String[] getTetherableBluetoothRegexs() {
Erik Kline3e756652017-01-17 13:42:19 +0900981 return copy(mConfig.tetherableBluetoothRegexs);
Danica Chang6fdd0c62010-08-11 14:54:43 -0700982 }
983
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700984 public int setUsbTethering(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -0700985 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
Erik Klinefdd41112017-01-12 17:02:51 +0900986 UsbManager usbManager = mContext.getSystemService(UsbManager.class);
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700987
Robert Greenwaltb4453622011-11-03 16:01:40 -0700988 synchronized (mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700989 if (enable) {
990 if (mRndisEnabled) {
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800991 final long ident = Binder.clearCallingIdentity();
992 try {
Erik Klineea9cc482017-03-10 19:35:34 +0900993 tetherMatchingInterfaces(IControlsTethering.STATE_TETHERED,
994 ConnectivityManager.TETHERING_USB);
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800995 } finally {
996 Binder.restoreCallingIdentity(ident);
997 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700998 } else {
999 mUsbTetherRequested = true;
Jerry Zhang935372b2016-10-12 15:49:32 -07001000 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001001 }
1002 } else {
Jeremy Klein36c7aa02016-01-22 14:11:45 -08001003 final long ident = Binder.clearCallingIdentity();
1004 try {
Erik Klineea9cc482017-03-10 19:35:34 +09001005 tetherMatchingInterfaces(IControlsTethering.STATE_AVAILABLE,
1006 ConnectivityManager.TETHERING_USB);
Jeremy Klein36c7aa02016-01-22 14:11:45 -08001007 } finally {
1008 Binder.restoreCallingIdentity(ident);
1009 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001010 if (mRndisEnabled) {
Jerry Zhang935372b2016-10-12 15:49:32 -07001011 usbManager.setCurrentFunction(null, false);
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001012 }
1013 mUsbTetherRequested = false;
1014 }
1015 }
1016 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
1017 }
1018
Erik Kline1fdc2e22017-05-08 17:56:35 +09001019 // TODO review API - figure out how to delete these entirely.
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001020 public String[] getTetheredIfaces() {
1021 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -07001022 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001023 for (int i = 0; i < mTetherStates.size(); i++) {
1024 TetherState tetherState = mTetherStates.valueAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +09001025 if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001026 list.add(mTetherStates.keyAt(i));
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001027 }
1028 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001029 }
Christopher Wileyd985dde2016-05-31 10:44:35 -07001030 return list.toArray(new String[list.size()]);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001031 }
1032
1033 public String[] getTetherableIfaces() {
1034 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -07001035 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001036 for (int i = 0; i < mTetherStates.size(); i++) {
1037 TetherState tetherState = mTetherStates.valueAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +09001038 if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001039 list.add(mTetherStates.keyAt(i));
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001040 }
1041 }
1042 }
Christopher Wileyd985dde2016-05-31 10:44:35 -07001043 return list.toArray(new String[list.size()]);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001044 }
1045
Robert Greenwalt9c7e2c22014-06-23 14:53:42 -07001046 public String[] getTetheredDhcpRanges() {
Erik Kline3e756652017-01-17 13:42:19 +09001047 return mConfig.dhcpRanges;
Robert Greenwalt9c7e2c22014-06-23 14:53:42 -07001048 }
1049
Robert Greenwalt5a735062010-03-02 17:25:02 -08001050 public String[] getErroredIfaces() {
1051 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -07001052 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001053 for (int i = 0; i < mTetherStates.size(); i++) {
1054 TetherState tetherState = mTetherStates.valueAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +09001055 if (tetherState.lastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001056 list.add(mTetherStates.keyAt(i));
Robert Greenwalt5a735062010-03-02 17:25:02 -08001057 }
1058 }
1059 }
Christopher Wileyd985dde2016-05-31 10:44:35 -07001060 return list.toArray(new String[list.size()]);
Robert Greenwalt5a735062010-03-02 17:25:02 -08001061 }
1062
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001063 private void maybeLogMessage(State state, int what) {
1064 if (DBG) {
1065 Log.d(TAG, state.getName() + " got " +
1066 sMagicDecoderRing.get(what, Integer.toString(what)));
1067 }
1068 }
1069
Erik Klineea9cc482017-03-10 19:35:34 +09001070 private boolean upstreamWanted() {
1071 if (!mForwardedDownstreams.isEmpty()) return true;
1072
1073 synchronized (mPublicSync) {
1074 return mUsbTetherRequested || mWifiTetherRequested;
1075 }
1076 }
1077
Erik Kline00019f42016-06-30 19:31:46 +09001078 // Needed because the canonical source of upstream truth is just the
1079 // upstream interface name, |mCurrentUpstreamIface|. This is ripe for
1080 // future simplification, once the upstream Network is canonical.
Erik Kline3a5278f2017-06-24 19:29:10 +09001081 private boolean pertainsToCurrentUpstream(NetworkState ns) {
Erik Kline00019f42016-06-30 19:31:46 +09001082 if (ns != null && ns.linkProperties != null && mCurrentUpstreamIface != null) {
1083 for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
1084 if (mCurrentUpstreamIface.equals(ifname)) {
1085 return true;
Erik Kline6ff17f72015-12-10 20:42:12 +09001086 }
1087 }
Erik Kline6ff17f72015-12-10 20:42:12 +09001088 }
Erik Kline00019f42016-06-30 19:31:46 +09001089 return false;
Erik Kline6ff17f72015-12-10 20:42:12 +09001090 }
1091
Erik Kline227648f2017-01-20 20:26:10 +09001092 private void reevaluateSimCardProvisioning() {
1093 if (!hasMobileHotspotProvisionApp()) return;
1094
1095 ArrayList<Integer> tethered = new ArrayList<>();
1096 synchronized (mPublicSync) {
1097 for (int i = 0; i < mTetherStates.size(); i++) {
1098 TetherState tetherState = mTetherStates.valueAt(i);
1099 if (tetherState.lastState != IControlsTethering.STATE_TETHERED) {
1100 continue; // Skip interfaces that aren't tethered.
1101 }
1102 String iface = mTetherStates.keyAt(i);
1103 int interfaceType = ifaceNameToType(iface);
1104 if (interfaceType != ConnectivityManager.TETHERING_INVALID) {
1105 tethered.add(interfaceType);
1106 }
1107 }
1108 }
1109
1110 for (int tetherType : tethered) {
1111 startProvisionIntent(tetherType);
1112 }
1113 }
1114
Erik Kline3a5278f2017-06-24 19:29:10 +09001115 private void startOffloadController() {
1116 mOffloadController.start();
1117 mOffloadController.updateExemptPrefixes(
1118 mUpstreamNetworkMonitor.getOffloadExemptPrefixes());
1119 }
1120
Wink Saville64c42ca2011-04-18 14:55:10 -07001121 class TetherMasterSM extends StateMachine {
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001122 private static final int BASE_MASTER = Protocol.BASE_TETHERING;
Erik Klineea9cc482017-03-10 19:35:34 +09001123 // an interface SM has requested Tethering/Local Hotspot
1124 static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MASTER + 1;
1125 // an interface SM has unrequested Tethering/Local Hotspot
1126 static final int EVENT_IFACE_SERVING_STATE_INACTIVE = BASE_MASTER + 2;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001127 // upstream connection change - do the right thing
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001128 static final int CMD_UPSTREAM_CHANGED = BASE_MASTER + 3;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001129 // we don't have a valid upstream conn, check again after a delay
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001130 static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4;
Erik Kline6ff17f72015-12-10 20:42:12 +09001131 // Events from NetworkCallbacks that we process on the master state
1132 // machine thread on behalf of the UpstreamNetworkMonitor.
Erik Kline00019f42016-06-30 19:31:46 +09001133 static final int EVENT_UPSTREAM_CALLBACK = BASE_MASTER + 5;
Yohei, Oshima977aad52016-12-08 13:39:20 +09001134 // we treated the error and want now to clear it
1135 static final int CMD_CLEAR_ERROR = BASE_MASTER + 6;
Erik Kline6e9a1012017-06-06 19:24:21 +09001136 static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MASTER + 7;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001137
Wink Saville64c42ca2011-04-18 14:55:10 -07001138 private State mInitialState;
1139 private State mTetherModeAliveState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001140
Wink Saville64c42ca2011-04-18 14:55:10 -07001141 private State mSetIpForwardingEnabledErrorState;
1142 private State mSetIpForwardingDisabledErrorState;
1143 private State mStartTetheringErrorState;
1144 private State mStopTetheringErrorState;
1145 private State mSetDnsForwardersErrorState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001146
Christopher Wileyd985dde2016-05-31 10:44:35 -07001147 // This list is a little subtle. It contains all the interfaces that currently are
1148 // requesting tethering, regardless of whether these interfaces are still members of
1149 // mTetherStates. This allows us to maintain the following predicates:
1150 //
1151 // 1) mTetherStates contains the set of all currently existing, tetherable, link state up
1152 // interfaces.
1153 // 2) mNotifyList contains all state machines that may have outstanding tethering state
1154 // that needs to be torn down.
1155 //
1156 // Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList
1157 // so that the garbage collector does not clean up the state machine before it has a chance
1158 // to tear itself down.
Erik Kline1eb8c692016-07-08 17:21:26 +09001159 private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
1160 private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001161
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001162 private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001163
Robert Greenwaltdfadaea2010-03-11 15:03:08 -08001164 TetherMasterSM(String name, Looper looper) {
1165 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001166
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001167 mInitialState = new InitialState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001168 mTetherModeAliveState = new TetherModeAliveState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001169 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001170 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001171 mStartTetheringErrorState = new StartTetheringErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001172 mStopTetheringErrorState = new StopTetheringErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001173 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
Erik Kline1fdc2e22017-05-08 17:56:35 +09001174
1175 addState(mInitialState);
1176 addState(mTetherModeAliveState);
1177 addState(mSetIpForwardingEnabledErrorState);
1178 addState(mSetIpForwardingDisabledErrorState);
1179 addState(mStartTetheringErrorState);
1180 addState(mStopTetheringErrorState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001181 addState(mSetDnsForwardersErrorState);
1182
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001183 mNotifyList = new ArrayList<>();
Erik Kline7747fd42017-05-12 16:52:48 +09001184 mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList, mLog);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001185 setInitialState(mInitialState);
1186 }
1187
Erik Kline1fdc2e22017-05-08 17:56:35 +09001188 class InitialState extends State {
1189 @Override
1190 public boolean processMessage(Message message) {
1191 maybeLogMessage(this, message.what);
1192 switch (message.what) {
1193 case EVENT_IFACE_SERVING_STATE_ACTIVE:
1194 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
1195 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
1196 handleInterfaceServingStateActive(message.arg1, who);
1197 transitionTo(mTetherModeAliveState);
1198 break;
1199 case EVENT_IFACE_SERVING_STATE_INACTIVE:
1200 who = (TetherInterfaceStateMachine)message.obj;
1201 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
1202 handleInterfaceServingStateInactive(who);
1203 break;
Erik Kline6e9a1012017-06-06 19:24:21 +09001204 case EVENT_IFACE_UPDATE_LINKPROPERTIES:
1205 // Silently ignore these for now.
1206 break;
Erik Kline1fdc2e22017-05-08 17:56:35 +09001207 default:
1208 return NOT_HANDLED;
1209 }
1210 return HANDLED;
1211 }
1212 }
1213
Erik Kline3a5278f2017-06-24 19:29:10 +09001214 protected boolean turnOnMasterTetherSettings() {
1215 final TetheringConfiguration cfg = mConfig;
1216 try {
1217 mNMService.setIpForwardingEnabled(true);
1218 } catch (Exception e) {
1219 mLog.e(e);
1220 transitionTo(mSetIpForwardingEnabledErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001221 return false;
1222 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001223 // TODO: Randomize DHCPv4 ranges, especially in hotspot mode.
1224 try {
1225 // TODO: Find a more accurate method name (startDHCPv4()?).
1226 mNMService.startTethering(cfg.dhcpRanges);
1227 } catch (Exception e) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001228 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001229 mNMService.stopTethering();
Erik Kline3a5278f2017-06-24 19:29:10 +09001230 mNMService.startTethering(cfg.dhcpRanges);
1231 } catch (Exception ee) {
1232 mLog.e(ee);
1233 transitionTo(mStartTetheringErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001234 return false;
1235 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001236 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001237 mLog.log("SET master tether settings: ON");
1238 return true;
1239 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001240
Erik Kline3a5278f2017-06-24 19:29:10 +09001241 protected boolean turnOffMasterTetherSettings() {
1242 try {
1243 mNMService.stopTethering();
1244 } catch (Exception e) {
1245 mLog.e(e);
1246 transitionTo(mStopTetheringErrorState);
1247 return false;
Erik Kline14f7faf2017-02-14 19:03:09 +09001248 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001249 try {
1250 mNMService.setIpForwardingEnabled(false);
1251 } catch (Exception e) {
1252 mLog.e(e);
1253 transitionTo(mSetIpForwardingDisabledErrorState);
1254 return false;
1255 }
1256 transitionTo(mInitialState);
1257 mLog.log("SET master tether settings: OFF");
1258 return true;
1259 }
Erik Kline14f7faf2017-02-14 19:03:09 +09001260
Erik Kline3a5278f2017-06-24 19:29:10 +09001261 protected void chooseUpstreamType(boolean tryCell) {
1262 updateConfiguration(); // TODO - remove?
Erik Kline1e2897d2017-06-09 17:08:52 +09001263
Erik Kline3a5278f2017-06-24 19:29:10 +09001264 final NetworkState ns = mUpstreamNetworkMonitor.selectPreferredUpstreamType(
1265 mConfig.preferredUpstreamIfaceTypes);
1266 if (ns == null) {
1267 if (tryCell) {
1268 mUpstreamNetworkMonitor.registerMobileNetworkRequest();
1269 // We think mobile should be coming up; don't set a retry.
1270 } else {
1271 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
Erik Kline1e2897d2017-06-09 17:08:52 +09001272 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001273 }
1274 setUpstreamNetwork(ns);
1275 }
1276
1277 protected void setUpstreamNetwork(NetworkState ns) {
1278 String iface = null;
1279 if (ns != null && ns.linkProperties != null) {
1280 // Find the interface with the default IPv4 route. It may be the
1281 // interface described by linkProperties, or one of the interfaces
1282 // stacked on top of it.
1283 Log.i(TAG, "Finding IPv4 upstream interface on: " + ns.linkProperties);
1284 RouteInfo ipv4Default = RouteInfo.selectBestRoute(
1285 ns.linkProperties.getAllRoutes(), Inet4Address.ANY);
1286 if (ipv4Default != null) {
1287 iface = ipv4Default.getInterface();
1288 Log.i(TAG, "Found interface " + ipv4Default.getInterface());
1289 } else {
1290 Log.i(TAG, "No IPv4 upstream interface, giving up.");
Erik Kline00019f42016-06-30 19:31:46 +09001291 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001292 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001293
Erik Kline3a5278f2017-06-24 19:29:10 +09001294 if (iface != null) {
1295 setDnsForwarders(ns.network, ns.linkProperties);
Erik Kline6ff17f72015-12-10 20:42:12 +09001296 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001297 notifyTetheredOfNewUpstreamIface(iface);
1298 if (ns != null && pertainsToCurrentUpstream(ns)) {
1299 // If we already have NetworkState for this network examine
1300 // it immediately, because there likely will be no second
1301 // EVENT_ON_AVAILABLE (it was already received).
1302 handleNewUpstreamNetworkState(ns);
1303 } else if (mCurrentUpstreamIface == null) {
1304 // There are no available upstream networks, or none that
1305 // have an IPv4 default route (current metric for success).
1306 handleNewUpstreamNetworkState(null);
1307 }
1308 }
Erik Kline6ff17f72015-12-10 20:42:12 +09001309
Erik Kline3a5278f2017-06-24 19:29:10 +09001310 protected void setDnsForwarders(final Network network, final LinkProperties lp) {
1311 // TODO: Set v4 and/or v6 DNS per available connectivity.
1312 String[] dnsServers = mConfig.defaultIPv4DNS;
1313 final Collection<InetAddress> dnses = lp.getDnsServers();
1314 // TODO: Properly support the absence of DNS servers.
1315 if (dnses != null && !dnses.isEmpty()) {
1316 // TODO: remove this invocation of NetworkUtils.makeStrings().
1317 dnsServers = NetworkUtils.makeStrings(dnses);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001318 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001319 try {
1320 mNMService.setDnsForwarders(network, dnsServers);
1321 mLog.log(String.format(
1322 "SET DNS forwarders: network=%s dnsServers=%s",
1323 network, Arrays.toString(dnsServers)));
1324 } catch (Exception e) {
1325 // TODO: Investigate how this can fail and what exactly
1326 // happens if/when such failures occur.
1327 mLog.e("setting DNS forwarders failed, " + e);
1328 transitionTo(mSetDnsForwardersErrorState);
1329 }
1330 }
Erik Kline00019f42016-06-30 19:31:46 +09001331
Erik Kline3a5278f2017-06-24 19:29:10 +09001332 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
1333 if (DBG) Log.d(TAG, "Notifying tethered with upstream=" + ifaceName);
1334 mCurrentUpstreamIface = ifaceName;
1335 for (TetherInterfaceStateMachine sm : mNotifyList) {
1336 sm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
1337 ifaceName);
Erik Kline00019f42016-06-30 19:31:46 +09001338 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001339 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001340
Erik Kline3a5278f2017-06-24 19:29:10 +09001341 protected void handleNewUpstreamNetworkState(NetworkState ns) {
1342 mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
1343 mOffloadController.setUpstreamLinkProperties((ns != null) ? ns.linkProperties : null);
1344 }
1345
Erik Klineea9cc482017-03-10 19:35:34 +09001346 private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) {
1347 if (mNotifyList.indexOf(who) < 0) {
1348 mNotifyList.add(who);
1349 mIPv6TetheringCoordinator.addActiveDownstream(who, mode);
1350 }
1351
1352 if (mode == IControlsTethering.STATE_TETHERED) {
1353 mForwardedDownstreams.add(who);
1354 } else {
Erik Kline6e9a1012017-06-06 19:24:21 +09001355 mOffloadController.removeDownstreamInterface(who.interfaceName());
Erik Klineea9cc482017-03-10 19:35:34 +09001356 mForwardedDownstreams.remove(who);
1357 }
Erik Kline216af6d2017-04-27 20:57:23 +09001358
1359 // If this is a Wi-Fi interface, notify WifiManager of the active serving state.
1360 if (who.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
1361 final WifiManager mgr = getWifiManager();
1362 final String iface = who.interfaceName();
1363 switch (mode) {
1364 case IControlsTethering.STATE_TETHERED:
Erik Kline2efb8272017-05-31 15:53:53 +09001365 mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +09001366 break;
1367 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Kline2efb8272017-05-31 15:53:53 +09001368 mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +09001369 break;
1370 default:
1371 Log.wtf(TAG, "Unknown active serving mode: " + mode);
1372 break;
1373 }
1374 }
Erik Klineea9cc482017-03-10 19:35:34 +09001375 }
1376
1377 private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) {
1378 mNotifyList.remove(who);
1379 mIPv6TetheringCoordinator.removeActiveDownstream(who);
Erik Kline6e9a1012017-06-06 19:24:21 +09001380 mOffloadController.removeDownstreamInterface(who.interfaceName());
Erik Klineea9cc482017-03-10 19:35:34 +09001381 mForwardedDownstreams.remove(who);
Erik Kline216af6d2017-04-27 20:57:23 +09001382
1383 // If this is a Wi-Fi interface, tell WifiManager of any errors.
1384 if (who.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
1385 if (who.lastError() != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
1386 getWifiManager().updateInterfaceIpState(
Erik Kline2efb8272017-05-31 15:53:53 +09001387 who.interfaceName(), IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline216af6d2017-04-27 20:57:23 +09001388 }
1389 }
Erik Klineea9cc482017-03-10 19:35:34 +09001390 }
1391
Erik Kline3a5278f2017-06-24 19:29:10 +09001392 private void handleUpstreamNetworkMonitorCallback(int arg1, Object o) {
1393 if (arg1 == UpstreamNetworkMonitor.NOTIFY_EXEMPT_PREFIXES) {
1394 mOffloadController.updateExemptPrefixes((Set<IpPrefix>) o);
1395 return;
1396 }
1397
1398 final NetworkState ns = (NetworkState) o;
1399
1400 if (ns == null || !pertainsToCurrentUpstream(ns)) {
1401 // TODO: In future, this is where upstream evaluation and selection
1402 // could be handled for notifications which include sufficient data.
1403 // For example, after CONNECTIVITY_ACTION listening is removed, here
1404 // is where we could observe a Wi-Fi network becoming available and
1405 // passing validation.
1406 if (mCurrentUpstreamIface == null) {
1407 // If we have no upstream interface, try to run through upstream
1408 // selection again. If, for example, IPv4 connectivity has shown up
1409 // after IPv6 (e.g., 464xlat became available) we want the chance to
1410 // notice and act accordingly.
1411 chooseUpstreamType(false);
1412 }
1413 return;
1414 }
1415
1416 switch (arg1) {
1417 case UpstreamNetworkMonitor.EVENT_ON_AVAILABLE:
1418 // The default network changed, or DUN connected
1419 // before this callback was processed. Updates
1420 // for the current NetworkCapabilities and
1421 // LinkProperties have been requested (default
1422 // request) or are being sent shortly (DUN). Do
1423 // nothing until they arrive; if no updates
1424 // arrive there's nothing to do.
1425 break;
1426 case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES:
1427 handleNewUpstreamNetworkState(ns);
1428 break;
1429 case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
1430 setDnsForwarders(ns.network, ns.linkProperties);
1431 handleNewUpstreamNetworkState(ns);
1432 break;
1433 case UpstreamNetworkMonitor.EVENT_ON_LOST:
1434 // TODO: Re-evaluate possible upstreams. Currently upstream
1435 // reevaluation is triggered via received CONNECTIVITY_ACTION
1436 // broadcasts that result in being passed a
1437 // TetherMasterSM.CMD_UPSTREAM_CHANGED.
1438 handleNewUpstreamNetworkState(null);
1439 break;
1440 default:
1441 mLog.e("Unknown arg1 value: " + arg1);
1442 break;
1443 }
1444 }
1445
1446 class TetherModeAliveState extends State {
Erik Klineea9cc482017-03-10 19:35:34 +09001447 boolean mUpstreamWanted = false;
Erik Kline6ff17f72015-12-10 20:42:12 +09001448 boolean mTryCell = true;
Erik Klinee0cce212017-03-06 14:05:23 +09001449
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001450 @Override
1451 public void enter() {
Erik Kline1fdc2e22017-05-08 17:56:35 +09001452 // If turning on master tether settings fails, we have already
1453 // transitioned to an error state; exit early.
1454 if (!turnOnMasterTetherSettings()) {
1455 return;
1456 }
1457
Erik Kline227648f2017-01-20 20:26:10 +09001458 mSimChange.startListening();
Erik Kline6ff17f72015-12-10 20:42:12 +09001459 mUpstreamNetworkMonitor.start();
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001460
Erik Klinef4b6e342017-04-25 19:19:59 +09001461 // TODO: De-duplicate with updateUpstreamWanted() below.
Erik Klineea9cc482017-03-10 19:35:34 +09001462 if (upstreamWanted()) {
1463 mUpstreamWanted = true;
Erik Kline3a5278f2017-06-24 19:29:10 +09001464 startOffloadController();
Erik Klineea9cc482017-03-10 19:35:34 +09001465 chooseUpstreamType(true);
1466 mTryCell = false;
1467 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001468 }
Erik Klinefa37b2f2016-08-02 18:27:03 +09001469
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001470 @Override
1471 public void exit() {
Erik Klinee0cce212017-03-06 14:05:23 +09001472 mOffloadController.stop();
Erik Kline6ff17f72015-12-10 20:42:12 +09001473 mUpstreamNetworkMonitor.stop();
Erik Kline227648f2017-01-20 20:26:10 +09001474 mSimChange.stopListening();
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001475 notifyTetheredOfNewUpstreamIface(null);
Erik Klinefa37b2f2016-08-02 18:27:03 +09001476 handleNewUpstreamNetworkState(null);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001477 }
Erik Klinefa37b2f2016-08-02 18:27:03 +09001478
Erik Klineea9cc482017-03-10 19:35:34 +09001479 private boolean updateUpstreamWanted() {
1480 final boolean previousUpstreamWanted = mUpstreamWanted;
1481 mUpstreamWanted = upstreamWanted();
Erik Klinef4b6e342017-04-25 19:19:59 +09001482 if (mUpstreamWanted != previousUpstreamWanted) {
1483 if (mUpstreamWanted) {
Erik Kline3a5278f2017-06-24 19:29:10 +09001484 startOffloadController();
Erik Klinef4b6e342017-04-25 19:19:59 +09001485 } else {
1486 mOffloadController.stop();
1487 }
1488 }
Erik Klineea9cc482017-03-10 19:35:34 +09001489 return previousUpstreamWanted;
1490 }
1491
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001492 @Override
1493 public boolean processMessage(Message message) {
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001494 maybeLogMessage(this, message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001495 boolean retValue = true;
1496 switch (message.what) {
Erik Klineea9cc482017-03-10 19:35:34 +09001497 case EVENT_IFACE_SERVING_STATE_ACTIVE: {
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001498 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001499 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
Erik Klineea9cc482017-03-10 19:35:34 +09001500 handleInterfaceServingStateActive(message.arg1, who);
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001501 who.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
Erik Kline6ff17f72015-12-10 20:42:12 +09001502 mCurrentUpstreamIface);
Erik Klineea9cc482017-03-10 19:35:34 +09001503 // If there has been a change and an upstream is now
1504 // desired, kick off the selection process.
1505 final boolean previousUpstreamWanted = updateUpstreamWanted();
1506 if (!previousUpstreamWanted && mUpstreamWanted) {
1507 chooseUpstreamType(true);
1508 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001509 break;
Erik Kline6e29bf02016-08-15 16:16:18 +09001510 }
Erik Klineea9cc482017-03-10 19:35:34 +09001511 case EVENT_IFACE_SERVING_STATE_INACTIVE: {
Erik Kline6e29bf02016-08-15 16:16:18 +09001512 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001513 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
Erik Klineea9cc482017-03-10 19:35:34 +09001514 handleInterfaceServingStateInactive(who);
1515
1516 if (mNotifyList.isEmpty()) {
Erik Kline47222fc2017-04-30 19:36:15 +09001517 // This transitions us out of TetherModeAliveState,
1518 // either to InitialState or an error state.
Erik Kline1fdc2e22017-05-08 17:56:35 +09001519 turnOffMasterTetherSettings();
1520 break;
1521 }
1522
1523 if (DBG) {
1524 Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
1525 " live requests:");
1526 for (TetherInterfaceStateMachine o : mNotifyList) {
1527 Log.d(TAG, " " + o);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001528 }
1529 }
Erik Klineea9cc482017-03-10 19:35:34 +09001530 // If there has been a change and an upstream is no
1531 // longer desired, release any mobile requests.
1532 final boolean previousUpstreamWanted = updateUpstreamWanted();
1533 if (previousUpstreamWanted && !mUpstreamWanted) {
1534 mUpstreamNetworkMonitor.releaseMobileNetworkRequest();
1535 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001536 break;
Erik Kline6e29bf02016-08-15 16:16:18 +09001537 }
Erik Kline6e9a1012017-06-06 19:24:21 +09001538 case EVENT_IFACE_UPDATE_LINKPROPERTIES: {
1539 final LinkProperties newLp = (LinkProperties) message.obj;
1540 if (message.arg1 == IControlsTethering.STATE_TETHERED) {
1541 mOffloadController.notifyDownstreamLinkProperties(newLp);
1542 } else {
1543 mOffloadController.removeDownstreamInterface(newLp.getInterfaceName());
1544 }
1545 break;
1546 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001547 case CMD_UPSTREAM_CHANGED:
Erik Klineea9cc482017-03-10 19:35:34 +09001548 updateUpstreamWanted();
1549 if (!mUpstreamWanted) break;
1550
Erik Klinefb413432017-02-14 18:26:04 +09001551 // Need to try DUN immediately if Wi-Fi goes down.
1552 chooseUpstreamType(true);
1553 mTryCell = false;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001554 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001555 case CMD_RETRY_UPSTREAM:
Erik Klineea9cc482017-03-10 19:35:34 +09001556 updateUpstreamWanted();
1557 if (!mUpstreamWanted) break;
1558
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001559 chooseUpstreamType(mTryCell);
1560 mTryCell = !mTryCell;
1561 break;
Erik Kline00019f42016-06-30 19:31:46 +09001562 case EVENT_UPSTREAM_CALLBACK: {
Erik Klineea9cc482017-03-10 19:35:34 +09001563 updateUpstreamWanted();
Erik Kline3a5278f2017-06-24 19:29:10 +09001564 if (mUpstreamWanted) {
1565 handleUpstreamNetworkMonitorCallback(message.arg1, message.obj);
Erik Kline6ff17f72015-12-10 20:42:12 +09001566 }
1567 break;
Erik Kline00019f42016-06-30 19:31:46 +09001568 }
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001569 default:
1570 retValue = false;
1571 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001572 }
1573 return retValue;
1574 }
1575 }
1576
Wink Saville64c42ca2011-04-18 14:55:10 -07001577 class ErrorState extends State {
Erik Kline8351faa2017-04-17 16:47:23 +09001578 private int mErrorNotification;
1579
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001580 @Override
1581 public boolean processMessage(Message message) {
1582 boolean retValue = true;
1583 switch (message.what) {
Erik Klineea9cc482017-03-10 19:35:34 +09001584 case EVENT_IFACE_SERVING_STATE_ACTIVE:
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001585 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001586 who.sendMessage(mErrorNotification);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001587 break;
Yohei, Oshima977aad52016-12-08 13:39:20 +09001588 case CMD_CLEAR_ERROR:
1589 mErrorNotification = ConnectivityManager.TETHER_ERROR_NO_ERROR;
1590 transitionTo(mInitialState);
1591 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001592 default:
1593 retValue = false;
1594 }
1595 return retValue;
1596 }
Erik Kline8351faa2017-04-17 16:47:23 +09001597
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001598 void notify(int msgType) {
1599 mErrorNotification = msgType;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001600 for (TetherInterfaceStateMachine sm : mNotifyList) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001601 sm.sendMessage(msgType);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001602 }
1603 }
1604
1605 }
Erik Kline8351faa2017-04-17 16:47:23 +09001606
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001607 class SetIpForwardingEnabledErrorState extends ErrorState {
1608 @Override
1609 public void enter() {
1610 Log.e(TAG, "Error in setIpForwardingEnabled");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001611 notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001612 }
1613 }
1614
1615 class SetIpForwardingDisabledErrorState extends ErrorState {
1616 @Override
1617 public void enter() {
1618 Log.e(TAG, "Error in setIpForwardingDisabled");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001619 notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001620 }
1621 }
1622
1623 class StartTetheringErrorState extends ErrorState {
1624 @Override
1625 public void enter() {
1626 Log.e(TAG, "Error in startTethering");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001627 notify(TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001628 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001629 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001630 } catch (Exception e) {}
1631 }
1632 }
1633
1634 class StopTetheringErrorState extends ErrorState {
1635 @Override
1636 public void enter() {
1637 Log.e(TAG, "Error in stopTethering");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001638 notify(TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001639 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001640 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001641 } catch (Exception e) {}
1642 }
1643 }
1644
1645 class SetDnsForwardersErrorState extends ErrorState {
1646 @Override
1647 public void enter() {
1648 Log.e(TAG, "Error in setDnsForwarders");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001649 notify(TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001650 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001651 mNMService.stopTethering();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001652 } catch (Exception e) {}
1653 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001654 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001655 } catch (Exception e) {}
1656 }
1657 }
1658 }
1659
Christopher Wiley499a57a2016-05-16 16:19:07 -07001660 @Override
Lorenzo Colittie3805462015-06-03 11:18:24 +09001661 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Christopher Wiley499a57a2016-05-16 16:19:07 -07001662 // Binder.java closes the resource for us.
1663 @SuppressWarnings("resource")
Lorenzo Colittie3805462015-06-03 11:18:24 +09001664 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06001665 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001666
Lorenzo Colittie3805462015-06-03 11:18:24 +09001667 pw.println("Tethering:");
1668 pw.increaseIndent();
Lorenzo Colittie3805462015-06-03 11:18:24 +09001669
Erik Kline9db1b542017-03-16 14:10:27 +09001670 pw.println("Configuration:");
1671 pw.increaseIndent();
1672 final TetheringConfiguration cfg = mConfig;
1673 cfg.dump(pw);
1674 pw.decreaseIndent();
1675
1676 synchronized (mPublicSync) {
Robert Greenwaltb4453622011-11-03 16:01:40 -07001677 pw.println("Tether state:");
Lorenzo Colittie3805462015-06-03 11:18:24 +09001678 pw.increaseIndent();
Christopher Wileyd985dde2016-05-31 10:44:35 -07001679 for (int i = 0; i < mTetherStates.size(); i++) {
1680 final String iface = mTetherStates.keyAt(i);
1681 final TetherState tetherState = mTetherStates.valueAt(i);
1682 pw.print(iface + " - ");
1683
Hugo Benichib55fb222017-03-10 14:20:57 +09001684 switch (tetherState.lastState) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001685 case IControlsTethering.STATE_UNAVAILABLE:
1686 pw.print("UnavailableState");
1687 break;
1688 case IControlsTethering.STATE_AVAILABLE:
1689 pw.print("AvailableState");
1690 break;
1691 case IControlsTethering.STATE_TETHERED:
1692 pw.print("TetheredState");
1693 break;
Erik Klineca41be72017-04-20 22:59:16 +09001694 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Klineea9cc482017-03-10 19:35:34 +09001695 pw.print("LocalHotspotState");
1696 break;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001697 default:
1698 pw.print("UnknownState");
1699 break;
1700 }
Hugo Benichib55fb222017-03-10 14:20:57 +09001701 pw.println(" - lastError = " + tetherState.lastError);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001702 }
Erik Klineea9cc482017-03-10 19:35:34 +09001703 pw.println("Upstream wanted: " + upstreamWanted());
Erik Klineee363c42017-05-29 09:11:03 +09001704 pw.println("Current upstream interface: " + mCurrentUpstreamIface);
Lorenzo Colittie3805462015-06-03 11:18:24 +09001705 pw.decreaseIndent();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001706 }
Erik Kline1fdc2e22017-05-08 17:56:35 +09001707
1708 pw.println("Log:");
1709 pw.increaseIndent();
Erik Kline7747fd42017-05-12 16:52:48 +09001710 if (argsContain(args, SHORT_ARG)) {
1711 pw.println("<log removed for brevity>");
1712 } else {
1713 mLog.dump(fd, pw, args);
1714 }
Erik Kline1fdc2e22017-05-08 17:56:35 +09001715 pw.decreaseIndent();
1716
Lorenzo Colittie3805462015-06-03 11:18:24 +09001717 pw.decreaseIndent();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001718 }
Christopher Wileye03fb442016-05-18 13:45:20 -07001719
Erik Kline7747fd42017-05-12 16:52:48 +09001720 private static boolean argsContain(String[] args, String target) {
1721 for (String arg : args) {
Erik Klineee363c42017-05-29 09:11:03 +09001722 if (target.equals(arg)) return true;
Erik Kline7747fd42017-05-12 16:52:48 +09001723 }
1724 return false;
1725 }
1726
Erik Kline6e9a1012017-06-06 19:24:21 +09001727 private IControlsTethering makeControlCallback(String ifname) {
1728 return new IControlsTethering() {
1729 @Override
1730 public void updateInterfaceState(
1731 TetherInterfaceStateMachine who, int state, int lastError) {
1732 notifyInterfaceStateChange(ifname, who, state, lastError);
1733 }
1734
1735 @Override
1736 public void updateLinkProperties(
1737 TetherInterfaceStateMachine who, LinkProperties newLp) {
1738 notifyLinkPropertiesChanged(ifname, who, newLp);
1739 }
1740 };
1741 }
1742
1743 // TODO: Move into TetherMasterSM.
1744 private void notifyInterfaceStateChange(
1745 String iface, TetherInterfaceStateMachine who, int state, int error) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001746 synchronized (mPublicSync) {
Erik Kline216af6d2017-04-27 20:57:23 +09001747 final TetherState tetherState = mTetherStates.get(iface);
Hugo Benichib55fb222017-03-10 14:20:57 +09001748 if (tetherState != null && tetherState.stateMachine.equals(who)) {
1749 tetherState.lastState = state;
1750 tetherState.lastError = error;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001751 } else {
1752 if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
1753 }
1754 }
1755
Erik Kline7747fd42017-05-12 16:52:48 +09001756 mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
Christopher Wileyd985dde2016-05-31 10:44:35 -07001757
Christopher Wileydeebfec2016-09-16 11:14:36 -07001758 try {
1759 // Notify that we're tethering (or not) this interface.
1760 // This is how data saver for instance knows if the user explicitly
1761 // turned on tethering (thus keeping us from being in data saver mode).
1762 mPolicyManager.onTetheringChanged(iface, state == IControlsTethering.STATE_TETHERED);
1763 } catch (RemoteException e) {
1764 // Not really very much we can do here.
1765 }
1766
Yohei, Oshima977aad52016-12-08 13:39:20 +09001767 // If TetherMasterSM is in ErrorState, TetherMasterSM stays there.
1768 // Thus we give a chance for TetherMasterSM to recover to InitialState
1769 // by sending CMD_CLEAR_ERROR
1770 if (error == ConnectivityManager.TETHER_ERROR_MASTER_ERROR) {
1771 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_CLEAR_ERROR, who);
1772 }
Erik Klineea9cc482017-03-10 19:35:34 +09001773 int which;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001774 switch (state) {
1775 case IControlsTethering.STATE_UNAVAILABLE:
1776 case IControlsTethering.STATE_AVAILABLE:
Erik Klineea9cc482017-03-10 19:35:34 +09001777 which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001778 break;
1779 case IControlsTethering.STATE_TETHERED:
Erik Klineca41be72017-04-20 22:59:16 +09001780 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Klineea9cc482017-03-10 19:35:34 +09001781 which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001782 break;
Erik Klineea9cc482017-03-10 19:35:34 +09001783 default:
1784 Log.wtf(TAG, "Unknown interface state: " + state);
1785 return;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001786 }
Erik Klineea9cc482017-03-10 19:35:34 +09001787 mTetherMasterSM.sendMessage(which, state, 0, who);
Christopher Wileyd985dde2016-05-31 10:44:35 -07001788 sendTetherStateChangedBroadcast();
1789 }
1790
Erik Kline6e9a1012017-06-06 19:24:21 +09001791 private void notifyLinkPropertiesChanged(String iface, TetherInterfaceStateMachine who,
1792 LinkProperties newLp) {
1793 final int state;
1794 synchronized (mPublicSync) {
1795 final TetherState tetherState = mTetherStates.get(iface);
1796 if (tetherState != null && tetherState.stateMachine.equals(who)) {
1797 state = tetherState.lastState;
1798 } else {
1799 mLog.log("got notification from stale iface " + iface);
1800 return;
1801 }
1802 }
1803
Erik Kline7fd696c2017-06-12 18:20:08 +09001804 mLog.log(String.format(
1805 "OBSERVED LinkProperties update iface=%s state=%s lp=%s",
1806 iface, IControlsTethering.getStateString(state), newLp));
Erik Kline6e9a1012017-06-06 19:24:21 +09001807 final int which = TetherMasterSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
1808 mTetherMasterSM.sendMessage(which, state, 0, newLp);
1809 }
1810
Erik Kline4dd9bb82017-04-26 11:11:07 +09001811 private void maybeTrackNewInterfaceLocked(final String iface) {
1812 // If we don't care about this type of interface, ignore.
1813 final int interfaceType = ifaceNameToType(iface);
1814 if (interfaceType == ConnectivityManager.TETHERING_INVALID) {
1815 mLog.log(iface + " is not a tetherable iface, ignoring");
1816 return;
1817 }
Erik Klinea9cde8b2017-06-20 21:18:31 +09001818 maybeTrackNewInterfaceLocked(iface, interfaceType);
1819 }
Erik Kline4dd9bb82017-04-26 11:11:07 +09001820
Erik Klinea9cde8b2017-06-20 21:18:31 +09001821 private void maybeTrackNewInterfaceLocked(final String iface, int interfaceType) {
Erik Kline4dd9bb82017-04-26 11:11:07 +09001822 // If we have already started a TISM for this interface, skip.
1823 if (mTetherStates.containsKey(iface)) {
1824 mLog.log("active iface (" + iface + ") reported as added, ignoring");
1825 return;
1826 }
1827
1828 mLog.log("adding TetheringInterfaceStateMachine for: " + iface);
1829 final TetherState tetherState = new TetherState(
1830 new TetherInterfaceStateMachine(
Erik Kline6e9a1012017-06-06 19:24:21 +09001831 iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
Erik Klinea8e2e792017-06-13 21:32:10 +09001832 makeControlCallback(iface)));
Christopher Wileyd985dde2016-05-31 10:44:35 -07001833 mTetherStates.put(iface, tetherState);
Hugo Benichib55fb222017-03-10 14:20:57 +09001834 tetherState.stateMachine.start();
Christopher Wileye03fb442016-05-18 13:45:20 -07001835 }
Erik Kline3e756652017-01-17 13:42:19 +09001836
Erik Kline4dd9bb82017-04-26 11:11:07 +09001837 private void stopTrackingInterfaceLocked(final String iface) {
1838 final TetherState tetherState = mTetherStates.get(iface);
1839 if (tetherState == null) {
1840 mLog.log("attempting to remove unknown iface (" + iface + "), ignoring");
1841 return;
1842 }
Erik Kline6e9a1012017-06-06 19:24:21 +09001843 tetherState.stateMachine.stop();
Erik Kline4dd9bb82017-04-26 11:11:07 +09001844 mLog.log("removing TetheringInterfaceStateMachine for: " + iface);
1845 mTetherStates.remove(iface);
1846 }
1847
Erik Kline3e756652017-01-17 13:42:19 +09001848 private static String[] copy(String[] strarray) {
1849 return Arrays.copyOf(strarray, strarray.length);
1850 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001851}