blob: a985b4fb10b8d4c12d226fa30bda7e3c0cd97f28 [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 Klinec438e302017-07-04 22:02:49 +090019import static android.hardware.usb.UsbManager.USB_CONFIGURED;
Erik Kline2e88b5e2017-01-18 11:57:45 +090020import static android.hardware.usb.UsbManager.USB_CONNECTED;
21import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
Erik Kline93c4afa2017-06-04 11:36:01 +090022import static android.net.ConnectivityManager.getNetworkTypeName;
Erik Kline2efb8272017-05-31 15:53:53 +090023import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
24import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
Erik Kline2e88b5e2017-01-18 11:57:45 +090025import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
Erik Kline2efb8272017-05-31 15:53:53 +090026import static android.net.wifi.WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR;
27import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
28import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
29import static android.net.wifi.WifiManager.IFACE_IP_MODE_UNSPECIFIED;
Erik Kline2e88b5e2017-01-18 11:57:45 +090030import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
Erik Kline7747fd42017-05-12 16:52:48 +090031import static com.android.server.ConnectivityService.SHORT_ARG;
Erik Kline2e88b5e2017-01-18 11:57:45 +090032
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080033import android.app.Notification;
34import android.app.NotificationManager;
35import android.app.PendingIntent;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080036import android.bluetooth.BluetoothAdapter;
37import android.bluetooth.BluetoothPan;
38import android.bluetooth.BluetoothProfile;
39import android.bluetooth.BluetoothProfile.ServiceListener;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080040import android.content.BroadcastReceiver;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -080041import android.content.ComponentName;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080042import android.content.Context;
43import android.content.Intent;
44import android.content.IntentFilter;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080045import android.content.pm.PackageManager;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080046import android.content.res.Resources;
Mike Lockwoodc4308f02011-03-01 08:04:54 -080047import android.hardware.usb.UsbManager;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080048import android.net.ConnectivityManager;
Christopher Wileydeebfec2016-09-16 11:14:36 -070049import android.net.INetworkPolicyManager;
Jeff Sharkey367d15a2011-09-22 14:59:51 -070050import android.net.INetworkStatsService;
Erik Kline3a5278f2017-06-24 19:29:10 +090051import android.net.IpPrefix;
Erik Klineed962a82017-07-06 19:49:35 +090052import android.net.LinkAddress;
Robert Greenwalt05d89362011-01-23 16:04:05 -080053import android.net.LinkProperties;
Lorenzo Colittib57edc52014-08-22 17:10:50 -070054import android.net.Network;
Erik Kline0c9cb2b2015-11-20 17:47:08 +090055import android.net.NetworkCapabilities;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080056import android.net.NetworkInfo;
Erik Kline0c9cb2b2015-11-20 17:47:08 +090057import android.net.NetworkRequest;
Erik Kline6ff17f72015-12-10 20:42:12 +090058import android.net.NetworkState;
Robert Greenwalte5903732011-02-22 16:00:42 -080059import android.net.NetworkUtils;
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090060import android.net.RouteInfo;
Erik Kline32179ff2017-07-04 18:28:11 +090061import android.net.util.PrefixUtils;
Erik Kline7747fd42017-05-12 16:52:48 +090062import android.net.util.SharedLog;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080063import android.net.wifi.WifiManager;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080064import android.os.Binder;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080065import android.os.Bundle;
Erik Klinef4b6e342017-04-25 19:19:59 +090066import android.os.Handler;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080067import android.os.INetworkManagementService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -080068import android.os.Looper;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080069import android.os.Message;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080070import android.os.Parcel;
Christopher Wileydeebfec2016-09-16 11:14:36 -070071import android.os.RemoteException;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080072import android.os.ResultReceiver;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070073import android.os.UserHandle;
Jeremy Klein15f3d212016-01-24 17:01:09 -080074import android.provider.Settings;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080075import android.telephony.CarrierConfigManager;
Junda Liu38531582014-10-28 13:52:51 -070076import android.telephony.TelephonyManager;
Lorenzo Colitticd63d242016-04-10 15:39:53 +090077import android.text.TextUtils;
Christopher Wileye9490392016-05-26 15:57:29 -070078import android.util.ArrayMap;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080079import android.util.Log;
Lorenzo Colitticd63d242016-04-10 15:39:53 +090080import android.util.SparseArray;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080081
Christopher Wiley497c1472016-10-11 13:26:03 -070082import com.android.internal.annotations.VisibleForTesting;
Chris Wren282cfef2017-03-27 15:01:44 -040083import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
Geoffrey Pitschaf759c52017-02-15 09:35:38 -050084import com.android.internal.notification.SystemNotificationChannels;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -080085import com.android.internal.telephony.IccCardConstants;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -080086import com.android.internal.telephony.TelephonyIntents;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060087import com.android.internal.util.DumpUtils;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080088import com.android.internal.util.IndentingPrintWriter;
Lorenzo Colitticd63d242016-04-10 15:39:53 +090089import com.android.internal.util.MessageUtils;
90import com.android.internal.util.Protocol;
Wink Saville64c42ca2011-04-18 14:55:10 -070091import com.android.internal.util.State;
92import com.android.internal.util.StateMachine;
Christopher Wileye03fb442016-05-18 13:45:20 -070093import com.android.server.connectivity.tethering.IControlsTethering;
Erik Kline1eb8c692016-07-08 17:21:26 +090094import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Klinee0cce212017-03-06 14:05:23 +090095import com.android.server.connectivity.tethering.OffloadController;
Erik Kline227648f2017-01-20 20:26:10 +090096import com.android.server.connectivity.tethering.SimChangeListener;
Mitchell Wills7040b4e2016-05-23 16:40:10 -070097import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
Hugo Benichib55fb222017-03-10 14:20:57 +090098import com.android.server.connectivity.tethering.TetheringConfiguration;
Erik Kline47222fc2017-04-30 19:36:15 +090099import com.android.server.connectivity.tethering.TetheringDependencies;
Erik Kline9bba3402017-01-13 16:46:52 +0900100import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Lorenzo Colittif4e90ea2013-10-31 23:30:47 +0900101import com.android.server.net.BaseNetworkObserver;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800102
103import java.io.FileDescriptor;
104import java.io.PrintWriter;
Robert Greenwalt4f74d552011-12-19 16:59:31 -0800105import java.net.Inet4Address;
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800106import java.net.InetAddress;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800107import java.util.ArrayList;
Lorenzo Colittib57edc52014-08-22 17:10:50 -0700108import java.util.Arrays;
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700109import java.util.Collection;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800110import java.util.HashMap;
Erik Klineea9cc482017-03-10 19:35:34 +0900111import java.util.HashSet;
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700112import java.util.Iterator;
Erik Klineea9cc482017-03-10 19:35:34 +0900113import java.util.Map;
Erik Kline3a5278f2017-06-24 19:29:10 +0900114import java.util.Set;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800115import java.util.concurrent.atomic.AtomicInteger;
116
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700117
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800118/**
119 * @hide
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800120 *
Christopher Wiley3b1d9222016-05-20 16:44:04 -0700121 * This class holds much of the business logic to allow Android devices
122 * to act as IP gateways via USB, BT, and WiFi interfaces.
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800123 */
Erik Kline6e9a1012017-06-06 19:24:21 +0900124public class Tethering extends BaseNetworkObserver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800125
Hugo Benichib55fb222017-03-10 14:20:57 +0900126 private final static String TAG = Tethering.class.getSimpleName();
Joe Onorato12acbd72016-02-01 17:49:31 -0800127 private final static boolean DBG = false;
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800128 private final static boolean VDBG = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800129
Christopher Wiley497c1472016-10-11 13:26:03 -0700130 protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning";
131
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900132 private static final Class[] messageClasses = {
Mitchell Wills7040b4e2016-05-23 16:40:10 -0700133 Tethering.class, TetherMasterSM.class, TetherInterfaceStateMachine.class
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900134 };
135 private static final SparseArray<String> sMagicDecoderRing =
136 MessageUtils.findMessageNames(messageClasses);
137
Hugo Benichib55fb222017-03-10 14:20:57 +0900138 // {@link ComponentName} of the Service used to run tether provisioning.
139 private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources
140 .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
141
142 private static class TetherState {
143 public final TetherInterfaceStateMachine stateMachine;
144 public int lastState;
145 public int lastError;
Erik Klineea9cc482017-03-10 19:35:34 +0900146
Hugo Benichib55fb222017-03-10 14:20:57 +0900147 public TetherState(TetherInterfaceStateMachine sm) {
148 stateMachine = sm;
149 // Assume all state machines start out available and with no errors.
150 lastState = IControlsTethering.STATE_AVAILABLE;
151 lastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
152 }
Erik Klineea9cc482017-03-10 19:35:34 +0900153
154 public boolean isCurrentlyServing() {
155 switch (lastState) {
156 case IControlsTethering.STATE_TETHERED:
Erik Klineca41be72017-04-20 22:59:16 +0900157 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Klineea9cc482017-03-10 19:35:34 +0900158 return true;
159 default:
160 return false;
161 }
162 }
Hugo Benichib55fb222017-03-10 14:20:57 +0900163 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700164
Erik Kline7747fd42017-05-12 16:52:48 +0900165 private final SharedLog mLog = new SharedLog(TAG);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900166
Robert Greenwaltb4453622011-11-03 16:01:40 -0700167 // used to synchronize public access to members
Erik Kline6ff17f72015-12-10 20:42:12 +0900168 private final Object mPublicSync;
Hugo Benichib55fb222017-03-10 14:20:57 +0900169 private final Context mContext;
170 private final ArrayMap<String, TetherState> mTetherStates;
171 private final BroadcastReceiver mStateReceiver;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700172 private final INetworkManagementService mNMService;
173 private final INetworkStatsService mStatsService;
Christopher Wileydeebfec2016-09-16 11:14:36 -0700174 private final INetworkPolicyManager mPolicyManager;
Erik Kline6ff17f72015-12-10 20:42:12 +0900175 private final Looper mLooper;
Christopher Wiley497c1472016-10-11 13:26:03 -0700176 private final MockableSystemProperties mSystemProperties;
Erik Kline6ff17f72015-12-10 20:42:12 +0900177 private final StateMachine mTetherMasterSM;
Erik Klinee0cce212017-03-06 14:05:23 +0900178 private final OffloadController mOffloadController;
Erik Kline6ff17f72015-12-10 20:42:12 +0900179 private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
Erik Kline6e9a1012017-06-06 19:24:21 +0900180 // TODO: Figure out how to merge this and other downstream-tracking objects
181 // into a single coherent structure.
Erik Klineea9cc482017-03-10 19:35:34 +0900182 private final HashSet<TetherInterfaceStateMachine> mForwardedDownstreams;
Erik Kline227648f2017-01-20 20:26:10 +0900183 private final SimChangeListener mSimChange;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800184
Hugo Benichib55fb222017-03-10 14:20:57 +0900185 private volatile TetheringConfiguration mConfig;
186 private String mCurrentUpstreamIface;
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400187 private Notification.Builder mTetheredNotificationBuilder;
188 private int mLastNotificationId;
Erik Klineea9cc482017-03-10 19:35:34 +0900189
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700190 private boolean mRndisEnabled; // track the RNDIS function enabled state
191 private boolean mUsbTetherRequested; // true if USB tethering should be started
192 // when RNDIS is enabled
Erik Kline6e9a1012017-06-06 19:24:21 +0900193 // True iff. WiFi tethering should be started when soft AP is ready.
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700194 private boolean mWifiTetherRequested;
195
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700196 public Tethering(Context context, INetworkManagementService nmService,
Christopher Wiley497c1472016-10-11 13:26:03 -0700197 INetworkStatsService statsService, INetworkPolicyManager policyManager,
Erik Kline47222fc2017-04-30 19:36:15 +0900198 Looper looper, MockableSystemProperties systemProperties,
199 TetheringDependencies deps) {
Erik Kline7747fd42017-05-12 16:52:48 +0900200 mLog.mark("constructed");
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800201 mContext = context;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700202 mNMService = nmService;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700203 mStatsService = statsService;
Christopher Wileydeebfec2016-09-16 11:14:36 -0700204 mPolicyManager = policyManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700205 mLooper = looper;
206 mSystemProperties = systemProperties;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800207
Robert Greenwaltb4453622011-11-03 16:01:40 -0700208 mPublicSync = new Object();
209
Christopher Wileyd985dde2016-05-31 10:44:35 -0700210 mTetherStates = new ArrayMap<>();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800211
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800212 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800213 mTetherMasterSM.start();
214
Erik Klinef4b6e342017-04-25 19:19:59 +0900215 final Handler smHandler = mTetherMasterSM.getHandler();
216 mOffloadController = new OffloadController(smHandler,
217 deps.getOffloadHardwareInterface(smHandler, mLog),
Lorenzo Colitti5a7dea12017-07-12 15:48:07 +0900218 mContext.getContentResolver(), mNMService,
Erik Klinef4b6e342017-04-25 19:19:59 +0900219 mLog);
Erik Klineebdb8c82017-01-10 17:37:54 +0900220 mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
Erik Kline32179ff2017-07-04 18:28:11 +0900221 mContext, mTetherMasterSM, mLog, TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
Erik Klineea9cc482017-03-10 19:35:34 +0900222 mForwardedDownstreams = new HashSet<>();
Erik Kline227648f2017-01-20 20:26:10 +0900223 mSimChange = new SimChangeListener(
Erik Kline32179ff2017-07-04 18:28:11 +0900224 mContext, smHandler, () -> reevaluateSimCardProvisioning());
Erik Kline6ff17f72015-12-10 20:42:12 +0900225
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800226 mStateReceiver = new StateReceiver();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800227 IntentFilter filter = new IntentFilter();
Mike Lockwood770126a2010-12-09 22:30:37 -0800228 filter.addAction(UsbManager.ACTION_USB_STATE);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800229 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700230 filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700231 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
Erik Kline32179ff2017-07-04 18:28:11 +0900232 mContext.registerReceiver(mStateReceiver, filter, null, smHandler);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800233
234 filter = new IntentFilter();
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800235 filter.addAction(Intent.ACTION_MEDIA_SHARED);
236 filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800237 filter.addDataScheme("file");
Erik Kline32179ff2017-07-04 18:28:11 +0900238 mContext.registerReceiver(mStateReceiver, filter, null, smHandler);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800239
Robert Greenwalt49348e72011-10-21 16:54:26 -0700240 // load device config info
241 updateConfiguration();
Robert Greenwalt49348e72011-10-21 16:54:26 -0700242 }
243
Sreeram Ramachandran62a61312014-07-24 16:05:17 -0700244 // We can't do this once in the Tethering() constructor and cache the value, because the
245 // CONNECTIVITY_SERVICE is registered only after the Tethering() constructor has completed.
246 private ConnectivityManager getConnectivityManager() {
247 return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
248 }
249
Erik Kline216af6d2017-04-27 20:57:23 +0900250 private WifiManager getWifiManager() {
251 return (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
252 }
253
Erik Kline93c4afa2017-06-04 11:36:01 +0900254 // NOTE: This is always invoked on the mLooper thread.
Erik Klined781fba2017-01-23 13:01:58 +0900255 private void updateConfiguration() {
Erik Kline6bd74532017-05-19 10:10:41 +0900256 mConfig = new TetheringConfiguration(mContext, mLog);
Erik Kline93c4afa2017-06-04 11:36:01 +0900257 mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800258 }
259
Erik Kline6ee73da2017-07-08 20:36:37 +0900260 private void maybeUpdateConfiguration() {
261 final int dunCheck = TetheringConfiguration.checkDunRequired(mContext);
262 if (dunCheck == mConfig.dunCheck) return;
263 updateConfiguration();
264 }
265
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900266 @Override
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700267 public void interfaceStatusChanged(String iface, boolean up) {
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900268 // Never called directly: only called from interfaceLinkStateChanged.
269 // See NetlinkHandler.cpp:71.
Wink Savillec9acde92011-09-21 11:05:43 -0700270 if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700271 synchronized (mPublicSync) {
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700272 if (up) {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900273 maybeTrackNewInterfaceLocked(iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800274 } else {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900275 if (ifaceNameToType(iface) == ConnectivityManager.TETHERING_BLUETOOTH) {
276 stopTrackingInterfaceLocked(iface);
Christopher Wileyd30aaeb2016-07-08 09:33:50 -0700277 } else {
278 // Ignore usb0 down after enabling RNDIS.
279 // We will handle disconnect in interfaceRemoved.
280 // Similarly, ignore interface down for WiFi. We monitor WiFi AP status
281 // through the WifiManager.WIFI_AP_STATE_CHANGED_ACTION intent.
282 if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800283 }
284 }
285 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800286 }
287
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900288 @Override
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700289 public void interfaceLinkStateChanged(String iface, boolean up) {
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700290 interfaceStatusChanged(iface, up);
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700291 }
292
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700293 private int ifaceNameToType(String iface) {
Erik Kline3e756652017-01-17 13:42:19 +0900294 final TetheringConfiguration cfg = mConfig;
295
296 if (cfg.isWifi(iface)) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700297 return ConnectivityManager.TETHERING_WIFI;
Erik Kline3e756652017-01-17 13:42:19 +0900298 } else if (cfg.isUsb(iface)) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700299 return ConnectivityManager.TETHERING_USB;
Erik Kline3e756652017-01-17 13:42:19 +0900300 } else if (cfg.isBluetooth(iface)) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700301 return ConnectivityManager.TETHERING_BLUETOOTH;
302 }
303 return ConnectivityManager.TETHERING_INVALID;
304 }
305
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900306 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800307 public void interfaceAdded(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700308 if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700309 synchronized (mPublicSync) {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900310 maybeTrackNewInterfaceLocked(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800311 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800312 }
313
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900314 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800315 public void interfaceRemoved(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700316 if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700317 synchronized (mPublicSync) {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900318 stopTrackingInterfaceLocked(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800319 }
320 }
321
Hugo Benichib55fb222017-03-10 14:20:57 +0900322 public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800323 if (!isTetherProvisioningRequired()) {
324 enableTetheringInternal(type, true, receiver);
325 return;
326 }
327
328 if (showProvisioningUi) {
329 runUiTetherProvisioningAndEnable(type, receiver);
330 } else {
331 runSilentTetherProvisioningAndEnable(type, receiver);
332 }
333 }
334
335 public void stopTethering(int type) {
336 enableTetheringInternal(type, false, null);
337 if (isTetherProvisioningRequired()) {
338 cancelTetherProvisioningRechecks(type);
339 }
340 }
341
342 /**
343 * Check if the device requires a provisioning check in order to enable tethering.
344 *
345 * @return a boolean - {@code true} indicating tether provisioning is required by the carrier.
346 */
Christopher Wiley497c1472016-10-11 13:26:03 -0700347 @VisibleForTesting
348 protected boolean isTetherProvisioningRequired() {
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800349 String[] provisionApp = mContext.getResources().getStringArray(
350 com.android.internal.R.array.config_mobile_hotspot_provision_app);
Christopher Wiley497c1472016-10-11 13:26:03 -0700351 if (mSystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false)
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800352 || provisionApp == null) {
353 return false;
354 }
355
356 // Check carrier config for entitlement checks
357 final CarrierConfigManager configManager = (CarrierConfigManager) mContext
358 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
Rebecca Silbersteinb07f1402016-10-04 13:53:33 -0700359 if (configManager != null && configManager.getConfig() != null) {
360 // we do have a CarrierConfigManager and it has a config.
361 boolean isEntitlementCheckRequired = configManager.getConfig().getBoolean(
362 CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
363 if (!isEntitlementCheckRequired) {
364 return false;
365 }
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800366 }
367 return (provisionApp.length == 2);
368 }
369
Erik Kline227648f2017-01-20 20:26:10 +0900370 // Used by the SIM card change observation code.
371 // TODO: De-duplicate above code.
372 private boolean hasMobileHotspotProvisionApp() {
373 try {
374 if (!mContext.getResources().getString(com.android.internal.R.string.
375 config_mobile_hotspot_provision_app_no_ui).isEmpty()) {
376 Log.d(TAG, "re-evaluate provisioning");
377 return true;
378 }
379 } catch (Resources.NotFoundException e) {}
380 Log.d(TAG, "no prov-check needed for new SIM");
381 return false;
382 }
383
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800384 /**
385 * Enables or disables tethering for the given type. This should only be called once
386 * provisioning has succeeded or is not necessary. It will also schedule provisioning rechecks
387 * for the specified interface.
388 */
389 private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700390 boolean isProvisioningRequired = enable && isTetherProvisioningRequired();
391 int result;
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800392 switch (type) {
393 case ConnectivityManager.TETHERING_WIFI:
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700394 result = setWifiTethering(enable);
395 if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
396 scheduleProvisioningRechecks(type);
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800397 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700398 sendTetherResult(receiver, result);
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800399 break;
400 case ConnectivityManager.TETHERING_USB:
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700401 result = setUsbTethering(enable);
402 if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800403 scheduleProvisioningRechecks(type);
404 }
405 sendTetherResult(receiver, result);
406 break;
407 case ConnectivityManager.TETHERING_BLUETOOTH:
408 setBluetoothTethering(enable, receiver);
409 break;
410 default:
411 Log.w(TAG, "Invalid tether type.");
412 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE);
413 }
414 }
415
416 private void sendTetherResult(ResultReceiver receiver, int result) {
417 if (receiver != null) {
418 receiver.send(result, null);
419 }
420 }
421
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700422 private int setWifiTethering(final boolean enable) {
Erik Kline256be782017-04-29 13:20:04 +0900423 int rval = ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
424 final long ident = Binder.clearCallingIdentity();
425 try {
426 synchronized (mPublicSync) {
427 mWifiTetherRequested = enable;
428 final WifiManager mgr = getWifiManager();
429 if ((enable && mgr.startSoftAp(null /* use existing wifi config */)) ||
430 (!enable && mgr.stopSoftAp())) {
431 rval = ConnectivityManager.TETHER_ERROR_NO_ERROR;
432 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700433 }
Erik Kline256be782017-04-29 13:20:04 +0900434 } finally {
435 Binder.restoreCallingIdentity(ident);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700436 }
Erik Kline256be782017-04-29 13:20:04 +0900437 return rval;
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700438 }
439
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800440 private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) {
441 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
442 if (adapter == null || !adapter.isEnabled()) {
443 Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: " +
444 (adapter == null));
445 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL);
446 return;
447 }
448
449 adapter.getProfileProxy(mContext, new ServiceListener() {
450 @Override
451 public void onServiceDisconnected(int profile) { }
452
453 @Override
454 public void onServiceConnected(int profile, BluetoothProfile proxy) {
455 ((BluetoothPan) proxy).setBluetoothTethering(enable);
456 // TODO: Enabling bluetooth tethering can fail asynchronously here.
457 // We should figure out a way to bubble up that failure instead of sending success.
Jeremy Klein45ae04a2016-02-05 10:37:32 -0800458 int result = ((BluetoothPan) proxy).isTetheringOn() == enable ?
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800459 ConnectivityManager.TETHER_ERROR_NO_ERROR :
460 ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
461 sendTetherResult(receiver, result);
462 if (enable && isTetherProvisioningRequired()) {
463 scheduleProvisioningRechecks(ConnectivityManager.TETHERING_BLUETOOTH);
464 }
465 adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
466 }
467 }, BluetoothProfile.PAN);
468 }
469
470 private void runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
Jeremy Klein15f3d212016-01-24 17:01:09 -0800471 ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
472 sendUiTetherProvisionIntent(type, proxyReceiver);
473 }
474
475 private void sendUiTetherProvisionIntent(int type, ResultReceiver receiver) {
476 Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
477 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
478 intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver);
479 final long ident = Binder.clearCallingIdentity();
480 try {
481 mContext.startActivityAsUser(intent, UserHandle.CURRENT);
482 } finally {
483 Binder.restoreCallingIdentity(ident);
484 }
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800485 }
486
487 /**
Erik Klinefdd41112017-01-12 17:02:51 +0900488 * Creates a proxy {@link ResultReceiver} which enables tethering if the provisioning result
489 * is successful before firing back up to the wrapped receiver.
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800490 *
491 * @param type The type of tethering being enabled.
492 * @param receiver A ResultReceiver which will be called back with an int resultCode.
493 * @return The proxy receiver.
494 */
495 private ResultReceiver getProxyReceiver(final int type, final ResultReceiver receiver) {
496 ResultReceiver rr = new ResultReceiver(null) {
497 @Override
498 protected void onReceiveResult(int resultCode, Bundle resultData) {
499 // If provisioning is successful, enable tethering, otherwise just send the error.
500 if (resultCode == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
501 enableTetheringInternal(type, true, receiver);
502 } else {
503 sendTetherResult(receiver, resultCode);
504 }
505 }
506 };
507
508 // The following is necessary to avoid unmarshalling issues when sending the receiver
Erik Kline6ff17f72015-12-10 20:42:12 +0900509 // across processes.
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800510 Parcel parcel = Parcel.obtain();
511 rr.writeToParcel(parcel,0);
512 parcel.setDataPosition(0);
513 ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel);
514 parcel.recycle();
515 return receiverForSending;
516 }
517
518 private void scheduleProvisioningRechecks(int type) {
519 Intent intent = new Intent();
520 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
521 intent.putExtra(ConnectivityManager.EXTRA_SET_ALARM, true);
522 intent.setComponent(TETHER_SERVICE);
523 final long ident = Binder.clearCallingIdentity();
524 try {
525 mContext.startServiceAsUser(intent, UserHandle.CURRENT);
526 } finally {
527 Binder.restoreCallingIdentity(ident);
528 }
529 }
530
531 private void runSilentTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
532 ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
533 sendSilentTetherProvisionIntent(type, proxyReceiver);
534 }
535
536 private void sendSilentTetherProvisionIntent(int type, ResultReceiver receiver) {
537 Intent intent = new Intent();
538 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
539 intent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
540 intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver);
541 intent.setComponent(TETHER_SERVICE);
542 final long ident = Binder.clearCallingIdentity();
543 try {
544 mContext.startServiceAsUser(intent, UserHandle.CURRENT);
545 } finally {
546 Binder.restoreCallingIdentity(ident);
547 }
548 }
549
550 private void cancelTetherProvisioningRechecks(int type) {
551 if (getConnectivityManager().isTetheringSupported()) {
552 Intent intent = new Intent();
553 intent.putExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE, type);
554 intent.setComponent(TETHER_SERVICE);
555 final long ident = Binder.clearCallingIdentity();
556 try {
557 mContext.startServiceAsUser(intent, UserHandle.CURRENT);
558 } finally {
559 Binder.restoreCallingIdentity(ident);
560 }
561 }
562 }
Erik Kline6ff17f72015-12-10 20:42:12 +0900563
Erik Kline227648f2017-01-20 20:26:10 +0900564 // Used by the SIM card change observation code.
565 // TODO: De-duplicate with above code, where possible.
566 private void startProvisionIntent(int tetherType) {
567 final Intent startProvIntent = new Intent();
568 startProvIntent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType);
569 startProvIntent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
570 startProvIntent.setComponent(TETHER_SERVICE);
571 mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT);
572 }
573
Robert Greenwalt5a735062010-03-02 17:25:02 -0800574 public int tether(String iface) {
Erik Klineea9cc482017-03-10 19:35:34 +0900575 return tether(iface, IControlsTethering.STATE_TETHERED);
576 }
577
578 private int tether(String iface, int requestedState) {
Wink Savillec9acde92011-09-21 11:05:43 -0700579 if (DBG) Log.d(TAG, "Tethering " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700580 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700581 TetherState tetherState = mTetherStates.get(iface);
582 if (tetherState == null) {
Erik Kline00019f42016-06-30 19:31:46 +0900583 Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring");
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700584 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
585 }
586 // Ignore the error status of the interface. If the interface is available,
587 // the errors are referring to past tethering attempts anyway.
Hugo Benichib55fb222017-03-10 14:20:57 +0900588 if (tetherState.lastState != IControlsTethering.STATE_AVAILABLE) {
Erik Kline00019f42016-06-30 19:31:46 +0900589 Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700590 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700591 }
Erik Klineea9cc482017-03-10 19:35:34 +0900592 // NOTE: If a CMD_TETHER_REQUESTED message is already in the TISM's
593 // queue but not yet processed, this will be a no-op and it will not
594 // return an error.
595 //
596 // TODO: reexamine the threading and messaging model.
597 tetherState.stateMachine.sendMessage(
598 TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, requestedState);
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700599 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800600 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800601 }
602
Robert Greenwalt5a735062010-03-02 17:25:02 -0800603 public int untether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700604 if (DBG) Log.d(TAG, "Untethering " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700605 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700606 TetherState tetherState = mTetherStates.get(iface);
607 if (tetherState == null) {
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700608 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
609 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
610 }
Erik Klineea9cc482017-03-10 19:35:34 +0900611 if (!tetherState.isCurrentlyServing()) {
612 Log.e(TAG, "Tried to untether an inactive iface :" + iface + ", ignoring");
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700613 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
614 }
Hugo Benichib55fb222017-03-10 14:20:57 +0900615 tetherState.stateMachine.sendMessage(
Christopher Wileyd985dde2016-05-31 10:44:35 -0700616 TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700617 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800618 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800619 }
620
Felipe Leme70c8b9b2016-04-25 14:41:31 -0700621 public void untetherAll() {
Christopher Wileyfa6a4862016-09-19 08:58:06 -0700622 stopTethering(ConnectivityManager.TETHERING_WIFI);
623 stopTethering(ConnectivityManager.TETHERING_USB);
624 stopTethering(ConnectivityManager.TETHERING_BLUETOOTH);
Felipe Leme70c8b9b2016-04-25 14:41:31 -0700625 }
626
Robert Greenwalt5a735062010-03-02 17:25:02 -0800627 public int getLastTetherError(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700628 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700629 TetherState tetherState = mTetherStates.get(iface);
630 if (tetherState == null) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700631 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
632 ", ignoring");
633 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
634 }
Hugo Benichib55fb222017-03-10 14:20:57 +0900635 return tetherState.lastError;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800636 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800637 }
638
Erik Klineea9cc482017-03-10 19:35:34 +0900639 // TODO: Figure out how to update for local hotspot mode interfaces.
Christopher Wileyd985dde2016-05-31 10:44:35 -0700640 private void sendTetherStateChangedBroadcast() {
Sreeram Ramachandran62a61312014-07-24 16:05:17 -0700641 if (!getConnectivityManager().isTetheringSupported()) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800642
Erik Kline8351faa2017-04-17 16:47:23 +0900643 final ArrayList<String> availableList = new ArrayList<>();
644 final ArrayList<String> tetherList = new ArrayList<>();
645 final ArrayList<String> localOnlyList = new ArrayList<>();
646 final ArrayList<String> erroredList = new ArrayList<>();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800647
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800648 boolean wifiTethered = false;
649 boolean usbTethered = false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700650 boolean bluetoothTethered = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800651
Erik Kline3e756652017-01-17 13:42:19 +0900652 final TetheringConfiguration cfg = mConfig;
653
Robert Greenwaltb4453622011-11-03 16:01:40 -0700654 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700655 for (int i = 0; i < mTetherStates.size(); i++) {
656 TetherState tetherState = mTetherStates.valueAt(i);
657 String iface = mTetherStates.keyAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +0900658 if (tetherState.lastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700659 erroredList.add(iface);
Hugo Benichib55fb222017-03-10 14:20:57 +0900660 } else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700661 availableList.add(iface);
Erik Klineca41be72017-04-20 22:59:16 +0900662 } else if (tetherState.lastState == IControlsTethering.STATE_LOCAL_ONLY) {
Erik Kline8351faa2017-04-17 16:47:23 +0900663 localOnlyList.add(iface);
Hugo Benichib55fb222017-03-10 14:20:57 +0900664 } else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
Erik Kline3e756652017-01-17 13:42:19 +0900665 if (cfg.isUsb(iface)) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700666 usbTethered = true;
Erik Kline3e756652017-01-17 13:42:19 +0900667 } else if (cfg.isWifi(iface)) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700668 wifiTethered = true;
Erik Kline3e756652017-01-17 13:42:19 +0900669 } else if (cfg.isBluetooth(iface)) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700670 bluetoothTethered = true;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800671 }
Erik Kline8351faa2017-04-17 16:47:23 +0900672 tetherList.add(iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800673 }
674 }
675 }
Erik Kline8351faa2017-04-17 16:47:23 +0900676 final Intent bcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
677 bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
Robert Greenwalt98c79e52011-07-28 11:51:11 -0700678 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Erik Kline8351faa2017-04-17 16:47:23 +0900679 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, availableList);
680 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList);
681 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, tetherList);
682 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, erroredList);
683 mContext.sendStickyBroadcastAsUser(bcast, UserHandle.ALL);
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800684 if (DBG) {
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900685 Log.d(TAG, String.format(
Erik Kline8351faa2017-04-17 16:47:23 +0900686 "sendTetherStateChangedBroadcast %s=[%s] %s=[%s] %s=[%s] %s=[%s]",
687 "avail", TextUtils.join(",", availableList),
688 "local_only", TextUtils.join(",", localOnlyList),
689 "tether", TextUtils.join(",", tetherList),
690 "error", TextUtils.join(",", erroredList)));
Robert Greenwalt924cc942010-06-28 10:26:19 -0700691 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800692
693 if (usbTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700694 if (wifiTethered || bluetoothTethered) {
Chris Wren282cfef2017-03-27 15:01:44 -0400695 showTetheredNotification(SystemMessage.NOTE_TETHER_GENERAL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800696 } else {
Chris Wren282cfef2017-03-27 15:01:44 -0400697 showTetheredNotification(SystemMessage.NOTE_TETHER_USB);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800698 }
699 } else if (wifiTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700700 if (bluetoothTethered) {
Chris Wren282cfef2017-03-27 15:01:44 -0400701 showTetheredNotification(SystemMessage.NOTE_TETHER_GENERAL);
Danica Chang6fdd0c62010-08-11 14:54:43 -0700702 } else {
Vinit Deshpande2576a802014-11-18 13:56:15 -0800703 /* We now have a status bar icon for WifiTethering, so drop the notification */
704 clearTetheredNotification();
Danica Chang6fdd0c62010-08-11 14:54:43 -0700705 }
706 } else if (bluetoothTethered) {
Chris Wren282cfef2017-03-27 15:01:44 -0400707 showTetheredNotification(SystemMessage.NOTE_TETHER_BLUETOOTH);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800708 } else {
709 clearTetheredNotification();
710 }
711 }
712
Chris Wren282cfef2017-03-27 15:01:44 -0400713 private void showTetheredNotification(int id) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800714 NotificationManager notificationManager =
Erik Klinec438e302017-07-04 22:02:49 +0900715 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800716 if (notificationManager == null) {
717 return;
718 }
Chris Wren282cfef2017-03-27 15:01:44 -0400719 int icon = 0;
720 switch(id) {
721 case SystemMessage.NOTE_TETHER_USB:
722 icon = com.android.internal.R.drawable.stat_sys_tether_usb;
723 break;
724 case SystemMessage.NOTE_TETHER_BLUETOOTH:
725 icon = com.android.internal.R.drawable.stat_sys_tether_bluetooth;
726 break;
727 case SystemMessage.NOTE_TETHER_GENERAL:
728 default:
729 icon = com.android.internal.R.drawable.stat_sys_tether_general;
730 break;
731 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800732
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400733 if (mLastNotificationId != 0) {
734 if (mLastNotificationId == icon) {
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700735 return;
736 }
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400737 notificationManager.cancelAsUser(null, mLastNotificationId,
Robert Greenwalt3cab6b02012-10-04 16:44:26 -0700738 UserHandle.ALL);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400739 mLastNotificationId = 0;
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700740 }
741
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800742 Intent intent = new Intent();
743 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
744 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
745
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700746 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
747 null, UserHandle.CURRENT);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800748
749 Resources r = Resources.getSystem();
750 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
751 CharSequence message = r.getText(com.android.internal.R.string.
752 tethered_notification_message);
753
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400754 if (mTetheredNotificationBuilder == null) {
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500755 mTetheredNotificationBuilder =
756 new Notification.Builder(mContext, SystemNotificationChannels.NETWORK_STATUS);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400757 mTetheredNotificationBuilder.setWhen(0)
758 .setOngoing(true)
759 .setColor(mContext.getColor(
760 com.android.internal.R.color.system_notification_accent_color))
761 .setVisibility(Notification.VISIBILITY_PUBLIC)
762 .setCategory(Notification.CATEGORY_STATUS);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800763 }
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400764 mTetheredNotificationBuilder.setSmallIcon(icon)
765 .setContentTitle(title)
766 .setContentText(message)
767 .setContentIntent(pi);
Chris Wren282cfef2017-03-27 15:01:44 -0400768 mLastNotificationId = id;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800769
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400770 notificationManager.notifyAsUser(null, mLastNotificationId,
zhouzhijie130d4592017-05-18 10:02:59 +0800771 mTetheredNotificationBuilder.buildInto(new Notification()), UserHandle.ALL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800772 }
773
774 private void clearTetheredNotification() {
775 NotificationManager notificationManager =
Erik Klinec438e302017-07-04 22:02:49 +0900776 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400777 if (notificationManager != null && mLastNotificationId != 0) {
778 notificationManager.cancelAsUser(null, mLastNotificationId,
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700779 UserHandle.ALL);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400780 mLastNotificationId = 0;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800781 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800782 }
783
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800784 private class StateReceiver extends BroadcastReceiver {
Nick Kralevich70c117a2014-05-27 15:30:02 -0700785 @Override
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800786 public void onReceive(Context content, Intent intent) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900787 final String action = intent.getAction();
788 if (action == null) return;
789
Mike Lockwood770126a2010-12-09 22:30:37 -0800790 if (action.equals(UsbManager.ACTION_USB_STATE)) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900791 handleUsbAction(intent);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800792 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900793 handleConnectivityAction(intent);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700794 } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900795 handleWifiApAction(intent);
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700796 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
797 updateConfiguration();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800798 }
799 }
Erik Kline2e88b5e2017-01-18 11:57:45 +0900800
801 private void handleConnectivityAction(Intent intent) {
802 final NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
803 ConnectivityManager.EXTRA_NETWORK_INFO);
804 if (networkInfo == null ||
805 networkInfo.getDetailedState() == NetworkInfo.DetailedState.FAILED) {
806 return;
807 }
808
809 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION: " + networkInfo.toString());
810 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
811 }
812
813 private void handleUsbAction(Intent intent) {
814 final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false);
Erik Klinec438e302017-07-04 22:02:49 +0900815 final boolean usbConfigured = intent.getBooleanExtra(USB_CONFIGURED, false);
Erik Kline2e88b5e2017-01-18 11:57:45 +0900816 final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false);
Erik Klinec438e302017-07-04 22:02:49 +0900817
818 mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s",
819 usbConnected, usbConfigured, rndisEnabled));
820
821 // There are three types of ACTION_USB_STATE:
822 //
823 // - DISCONNECTED (USB_CONNECTED and USB_CONFIGURED are 0)
824 // Meaning: USB connection has ended either because of
825 // software reset or hard unplug.
826 //
827 // - CONNECTED (USB_CONNECTED is 1, USB_CONFIGURED is 0)
828 // Meaning: the first stage of USB protocol handshake has
829 // occurred but it is not complete.
830 //
831 // - CONFIGURED (USB_CONNECTED and USB_CONFIGURED are 1)
832 // Meaning: the USB handshake is completely done and all the
833 // functions are ready to use.
834 //
835 // For more explanation, see b/62552150 .
Erik Kline2e88b5e2017-01-18 11:57:45 +0900836 synchronized (Tethering.this.mPublicSync) {
Erik Kline3897dc12017-08-07 18:11:22 -0700837 // Always record the state of RNDIS.
Erik Kline12905682017-08-08 20:53:46 -0700838 // TODO: consider:
839 // final boolean disconnected = !usbConnected;
840 // if (disconnected) {
841 // mRndisEnabled = false;
842 // mUsbTetherRequested = false;
843 // return;
844 // }
845 // final boolean configured = usbConnected && usbConfigured;
846 // mRndisEnabled = configured ? rndisEnabled : false;
847 // if (!configured) return;
Erik Kline2e88b5e2017-01-18 11:57:45 +0900848 mRndisEnabled = rndisEnabled;
Erik Kline3897dc12017-08-07 18:11:22 -0700849
850 if (usbConnected && !usbConfigured) {
851 // Nothing to do here (only CONNECTED, not yet CONFIGURED).
852 return;
853 }
854
Erik Kline2e88b5e2017-01-18 11:57:45 +0900855 // start tethering if we have a request pending
Erik Klinec438e302017-07-04 22:02:49 +0900856 if (usbConfigured && mRndisEnabled && mUsbTetherRequested) {
Erik Klineea9cc482017-03-10 19:35:34 +0900857 tetherMatchingInterfaces(
858 IControlsTethering.STATE_TETHERED,
859 ConnectivityManager.TETHERING_USB);
Erik Kline2e88b5e2017-01-18 11:57:45 +0900860 }
Erik Kline3897dc12017-08-07 18:11:22 -0700861
862 // TODO: Figure out how to remove the need for this variable.
Erik Kline2e88b5e2017-01-18 11:57:45 +0900863 mUsbTetherRequested = false;
864 }
865 }
866
867 private void handleWifiApAction(Intent intent) {
Erik Kline2efb8272017-05-31 15:53:53 +0900868 final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
869 final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
870 final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED);
871
Erik Kline2e88b5e2017-01-18 11:57:45 +0900872 synchronized (Tethering.this.mPublicSync) {
873 switch (curState) {
874 case WifiManager.WIFI_AP_STATE_ENABLING:
875 // We can see this state on the way to both enabled and failure states.
876 break;
877 case WifiManager.WIFI_AP_STATE_ENABLED:
Erik Kline2efb8272017-05-31 15:53:53 +0900878 enableWifiIpServingLocked(ifname, ipmode);
Erik Kline2e88b5e2017-01-18 11:57:45 +0900879 break;
880 case WifiManager.WIFI_AP_STATE_DISABLED:
881 case WifiManager.WIFI_AP_STATE_DISABLING:
882 case WifiManager.WIFI_AP_STATE_FAILED:
883 default:
Erik Kline562e0c12017-06-09 16:36:29 +0900884 disableWifiIpServingLocked(ifname, curState);
Erik Kline2efb8272017-05-31 15:53:53 +0900885 break;
Erik Kline2e88b5e2017-01-18 11:57:45 +0900886 }
887 }
888 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800889 }
890
Erik Kline562e0c12017-06-09 16:36:29 +0900891 private void disableWifiIpServingLocked(String ifname, int apState) {
892 mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState);
Erik Kline2efb8272017-05-31 15:53:53 +0900893
Erik Kline562e0c12017-06-09 16:36:29 +0900894 // Regardless of whether we requested this transition, the AP has gone
895 // down. Don't try to tether again unless we're requested to do so.
896 // TODO: Remove this altogether, once Wi-Fi reliably gives us an
897 // interface name with every broadcast.
898 mWifiTetherRequested = false;
899
900 if (!TextUtils.isEmpty(ifname)) {
901 final TetherState ts = mTetherStates.get(ifname);
902 if (ts != null) {
903 ts.stateMachine.unwanted();
904 return;
905 }
906 }
907
Erik Kline2efb8272017-05-31 15:53:53 +0900908 for (int i = 0; i < mTetherStates.size(); i++) {
909 TetherInterfaceStateMachine tism = mTetherStates.valueAt(i).stateMachine;
910 if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
Erik Kline562e0c12017-06-09 16:36:29 +0900911 tism.unwanted();
912 return;
Erik Kline2efb8272017-05-31 15:53:53 +0900913 }
914 }
Erik Kline562e0c12017-06-09 16:36:29 +0900915
916 mLog.log("Error disabling Wi-Fi IP serving; " +
917 (TextUtils.isEmpty(ifname) ? "no interface name specified"
918 : "specified interface: " + ifname));
Erik Kline2efb8272017-05-31 15:53:53 +0900919 }
920
921 private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
922 // Map wifiIpMode values to IControlsTethering serving states, inferring
923 // from mWifiTetherRequested as a final "best guess".
924 final int ipServingMode;
925 switch (wifiIpMode) {
926 case IFACE_IP_MODE_TETHERED:
927 ipServingMode = IControlsTethering.STATE_TETHERED;
928 break;
929 case IFACE_IP_MODE_LOCAL_ONLY:
930 ipServingMode = IControlsTethering.STATE_LOCAL_ONLY;
931 break;
932 default:
Erik Kline9e225542017-06-08 17:48:48 +0900933 mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode);
934 return;
Erik Kline2efb8272017-05-31 15:53:53 +0900935 }
936
937 if (!TextUtils.isEmpty(ifname)) {
Erik Klinea9cde8b2017-06-20 21:18:31 +0900938 maybeTrackNewInterfaceLocked(ifname, ConnectivityManager.TETHERING_WIFI);
Erik Kline2efb8272017-05-31 15:53:53 +0900939 changeInterfaceState(ifname, ipServingMode);
940 } else {
Erik Kline9e225542017-06-08 17:48:48 +0900941 mLog.e(String.format(
942 "Cannot enable IP serving in mode %s on missing interface name",
943 ipServingMode));
Erik Kline2efb8272017-05-31 15:53:53 +0900944 }
945 }
946
Erik Klineea9cc482017-03-10 19:35:34 +0900947 // TODO: Consider renaming to something more accurate in its description.
948 // This method:
949 // - allows requesting either tethering or local hotspot serving states
950 // - handles both enabling and disabling serving states
951 // - only tethers the first matching interface in listInterfaces()
952 // order of a given type
953 private void tetherMatchingInterfaces(int requestedState, int interfaceType) {
954 if (VDBG) {
955 Log.d(TAG, "tetherMatchingInterfaces(" + requestedState + ", " + interfaceType + ")");
956 }
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700957
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700958 String[] ifaces = null;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800959 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700960 ifaces = mNMService.listInterfaces();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800961 } catch (Exception e) {
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700962 Log.e(TAG, "Error listing Interfaces", e);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800963 return;
964 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700965 String chosenIface = null;
966 if (ifaces != null) {
967 for (String iface : ifaces) {
968 if (ifaceNameToType(iface) == interfaceType) {
969 chosenIface = iface;
970 break;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800971 }
972 }
973 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700974 if (chosenIface == null) {
975 Log.e(TAG, "could not find iface of type " + interfaceType);
976 return;
977 }
978
Erik Kline2efb8272017-05-31 15:53:53 +0900979 changeInterfaceState(chosenIface, requestedState);
980 }
981
982 private void changeInterfaceState(String ifname, int requestedState) {
Erik Klineea9cc482017-03-10 19:35:34 +0900983 final int result;
984 switch (requestedState) {
985 case IControlsTethering.STATE_UNAVAILABLE:
986 case IControlsTethering.STATE_AVAILABLE:
Erik Kline2efb8272017-05-31 15:53:53 +0900987 result = untether(ifname);
Erik Klineea9cc482017-03-10 19:35:34 +0900988 break;
989 case IControlsTethering.STATE_TETHERED:
Erik Klineca41be72017-04-20 22:59:16 +0900990 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Kline2efb8272017-05-31 15:53:53 +0900991 result = tether(ifname, requestedState);
Erik Klineea9cc482017-03-10 19:35:34 +0900992 break;
993 default:
994 Log.wtf(TAG, "Unknown interface state: " + requestedState);
995 return;
996 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700997 if (result != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Erik Kline2efb8272017-05-31 15:53:53 +0900998 Log.e(TAG, "unable start or stop tethering on iface " + ifname);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700999 return;
1000 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001001 }
1002
Erik Kline3e756652017-01-17 13:42:19 +09001003 public TetheringConfiguration getTetheringConfiguration() {
1004 return mConfig;
1005 }
1006
Erik Klined781fba2017-01-23 13:01:58 +09001007 public boolean hasTetherableConfiguration() {
1008 final TetheringConfiguration cfg = mConfig;
1009 final boolean hasDownstreamConfiguration =
1010 (cfg.tetherableUsbRegexs.length != 0) ||
1011 (cfg.tetherableWifiRegexs.length != 0) ||
1012 (cfg.tetherableBluetoothRegexs.length != 0);
1013 final boolean hasUpstreamConfiguration = !cfg.preferredUpstreamIfaceTypes.isEmpty();
1014
1015 return hasDownstreamConfiguration && hasUpstreamConfiguration;
1016 }
1017
Erik Kline3e756652017-01-17 13:42:19 +09001018 // TODO - update callers to use getTetheringConfiguration(),
1019 // which has only final members.
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001020 public String[] getTetherableUsbRegexs() {
Erik Kline3e756652017-01-17 13:42:19 +09001021 return copy(mConfig.tetherableUsbRegexs);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001022 }
1023
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001024 public String[] getTetherableWifiRegexs() {
Erik Kline3e756652017-01-17 13:42:19 +09001025 return copy(mConfig.tetherableWifiRegexs);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001026 }
1027
Danica Chang6fdd0c62010-08-11 14:54:43 -07001028 public String[] getTetherableBluetoothRegexs() {
Erik Kline3e756652017-01-17 13:42:19 +09001029 return copy(mConfig.tetherableBluetoothRegexs);
Danica Chang6fdd0c62010-08-11 14:54:43 -07001030 }
1031
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001032 public int setUsbTethering(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -07001033 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
Erik Klinec438e302017-07-04 22:02:49 +09001034 UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001035
Robert Greenwaltb4453622011-11-03 16:01:40 -07001036 synchronized (mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001037 if (enable) {
1038 if (mRndisEnabled) {
Jeremy Klein36c7aa02016-01-22 14:11:45 -08001039 final long ident = Binder.clearCallingIdentity();
1040 try {
Erik Klineea9cc482017-03-10 19:35:34 +09001041 tetherMatchingInterfaces(IControlsTethering.STATE_TETHERED,
1042 ConnectivityManager.TETHERING_USB);
Jeremy Klein36c7aa02016-01-22 14:11:45 -08001043 } finally {
1044 Binder.restoreCallingIdentity(ident);
1045 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001046 } else {
1047 mUsbTetherRequested = true;
Jerry Zhang935372b2016-10-12 15:49:32 -07001048 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001049 }
1050 } else {
Jeremy Klein36c7aa02016-01-22 14:11:45 -08001051 final long ident = Binder.clearCallingIdentity();
1052 try {
Erik Klineea9cc482017-03-10 19:35:34 +09001053 tetherMatchingInterfaces(IControlsTethering.STATE_AVAILABLE,
1054 ConnectivityManager.TETHERING_USB);
Jeremy Klein36c7aa02016-01-22 14:11:45 -08001055 } finally {
1056 Binder.restoreCallingIdentity(ident);
1057 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001058 if (mRndisEnabled) {
Jerry Zhang935372b2016-10-12 15:49:32 -07001059 usbManager.setCurrentFunction(null, false);
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001060 }
1061 mUsbTetherRequested = false;
1062 }
1063 }
1064 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
1065 }
1066
Erik Kline1fdc2e22017-05-08 17:56:35 +09001067 // TODO review API - figure out how to delete these entirely.
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001068 public String[] getTetheredIfaces() {
1069 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -07001070 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001071 for (int i = 0; i < mTetherStates.size(); i++) {
1072 TetherState tetherState = mTetherStates.valueAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +09001073 if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001074 list.add(mTetherStates.keyAt(i));
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001075 }
1076 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001077 }
Christopher Wileyd985dde2016-05-31 10:44:35 -07001078 return list.toArray(new String[list.size()]);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001079 }
1080
1081 public String[] getTetherableIfaces() {
1082 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -07001083 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001084 for (int i = 0; i < mTetherStates.size(); i++) {
1085 TetherState tetherState = mTetherStates.valueAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +09001086 if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001087 list.add(mTetherStates.keyAt(i));
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001088 }
1089 }
1090 }
Christopher Wileyd985dde2016-05-31 10:44:35 -07001091 return list.toArray(new String[list.size()]);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001092 }
1093
Robert Greenwalt9c7e2c22014-06-23 14:53:42 -07001094 public String[] getTetheredDhcpRanges() {
Erik Kline3e756652017-01-17 13:42:19 +09001095 return mConfig.dhcpRanges;
Robert Greenwalt9c7e2c22014-06-23 14:53:42 -07001096 }
1097
Robert Greenwalt5a735062010-03-02 17:25:02 -08001098 public String[] getErroredIfaces() {
1099 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -07001100 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001101 for (int i = 0; i < mTetherStates.size(); i++) {
1102 TetherState tetherState = mTetherStates.valueAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +09001103 if (tetherState.lastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001104 list.add(mTetherStates.keyAt(i));
Robert Greenwalt5a735062010-03-02 17:25:02 -08001105 }
1106 }
1107 }
Christopher Wileyd985dde2016-05-31 10:44:35 -07001108 return list.toArray(new String[list.size()]);
Robert Greenwalt5a735062010-03-02 17:25:02 -08001109 }
1110
Erik Kline22108902017-07-06 16:40:06 +09001111 private void logMessage(State state, int what) {
1112 mLog.log(state.getName() + " got " + sMagicDecoderRing.get(what, Integer.toString(what)));
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001113 }
1114
Erik Klineea9cc482017-03-10 19:35:34 +09001115 private boolean upstreamWanted() {
1116 if (!mForwardedDownstreams.isEmpty()) return true;
1117
1118 synchronized (mPublicSync) {
1119 return mUsbTetherRequested || mWifiTetherRequested;
1120 }
1121 }
1122
Erik Kline00019f42016-06-30 19:31:46 +09001123 // Needed because the canonical source of upstream truth is just the
1124 // upstream interface name, |mCurrentUpstreamIface|. This is ripe for
1125 // future simplification, once the upstream Network is canonical.
Erik Kline3a5278f2017-06-24 19:29:10 +09001126 private boolean pertainsToCurrentUpstream(NetworkState ns) {
Erik Kline00019f42016-06-30 19:31:46 +09001127 if (ns != null && ns.linkProperties != null && mCurrentUpstreamIface != null) {
1128 for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
1129 if (mCurrentUpstreamIface.equals(ifname)) {
1130 return true;
Erik Kline6ff17f72015-12-10 20:42:12 +09001131 }
1132 }
Erik Kline6ff17f72015-12-10 20:42:12 +09001133 }
Erik Kline00019f42016-06-30 19:31:46 +09001134 return false;
Erik Kline6ff17f72015-12-10 20:42:12 +09001135 }
1136
Erik Kline227648f2017-01-20 20:26:10 +09001137 private void reevaluateSimCardProvisioning() {
1138 if (!hasMobileHotspotProvisionApp()) return;
1139
1140 ArrayList<Integer> tethered = new ArrayList<>();
1141 synchronized (mPublicSync) {
1142 for (int i = 0; i < mTetherStates.size(); i++) {
1143 TetherState tetherState = mTetherStates.valueAt(i);
1144 if (tetherState.lastState != IControlsTethering.STATE_TETHERED) {
1145 continue; // Skip interfaces that aren't tethered.
1146 }
1147 String iface = mTetherStates.keyAt(i);
1148 int interfaceType = ifaceNameToType(iface);
1149 if (interfaceType != ConnectivityManager.TETHERING_INVALID) {
1150 tethered.add(interfaceType);
1151 }
1152 }
1153 }
1154
1155 for (int tetherType : tethered) {
1156 startProvisionIntent(tetherType);
1157 }
1158 }
1159
Wink Saville64c42ca2011-04-18 14:55:10 -07001160 class TetherMasterSM extends StateMachine {
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001161 private static final int BASE_MASTER = Protocol.BASE_TETHERING;
Erik Klineea9cc482017-03-10 19:35:34 +09001162 // an interface SM has requested Tethering/Local Hotspot
1163 static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MASTER + 1;
1164 // an interface SM has unrequested Tethering/Local Hotspot
1165 static final int EVENT_IFACE_SERVING_STATE_INACTIVE = BASE_MASTER + 2;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001166 // upstream connection change - do the right thing
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001167 static final int CMD_UPSTREAM_CHANGED = BASE_MASTER + 3;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001168 // we don't have a valid upstream conn, check again after a delay
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001169 static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4;
Erik Kline6ff17f72015-12-10 20:42:12 +09001170 // Events from NetworkCallbacks that we process on the master state
1171 // machine thread on behalf of the UpstreamNetworkMonitor.
Erik Kline00019f42016-06-30 19:31:46 +09001172 static final int EVENT_UPSTREAM_CALLBACK = BASE_MASTER + 5;
Yohei, Oshima977aad52016-12-08 13:39:20 +09001173 // we treated the error and want now to clear it
1174 static final int CMD_CLEAR_ERROR = BASE_MASTER + 6;
Erik Kline6e9a1012017-06-06 19:24:21 +09001175 static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MASTER + 7;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001176
Erik Kline32179ff2017-07-04 18:28:11 +09001177 private final State mInitialState;
1178 private final State mTetherModeAliveState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001179
Erik Kline32179ff2017-07-04 18:28:11 +09001180 private final State mSetIpForwardingEnabledErrorState;
1181 private final State mSetIpForwardingDisabledErrorState;
1182 private final State mStartTetheringErrorState;
1183 private final State mStopTetheringErrorState;
1184 private final State mSetDnsForwardersErrorState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001185
Christopher Wileyd985dde2016-05-31 10:44:35 -07001186 // This list is a little subtle. It contains all the interfaces that currently are
1187 // requesting tethering, regardless of whether these interfaces are still members of
1188 // mTetherStates. This allows us to maintain the following predicates:
1189 //
1190 // 1) mTetherStates contains the set of all currently existing, tetherable, link state up
1191 // interfaces.
1192 // 2) mNotifyList contains all state machines that may have outstanding tethering state
1193 // that needs to be torn down.
1194 //
1195 // Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList
1196 // so that the garbage collector does not clean up the state machine before it has a chance
1197 // to tear itself down.
Erik Kline1eb8c692016-07-08 17:21:26 +09001198 private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
1199 private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
Erik Klineed962a82017-07-06 19:49:35 +09001200 private final OffloadWrapper mOffload;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001201
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001202 private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001203
Robert Greenwaltdfadaea2010-03-11 15:03:08 -08001204 TetherMasterSM(String name, Looper looper) {
1205 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001206
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001207 mInitialState = new InitialState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001208 mTetherModeAliveState = new TetherModeAliveState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001209 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001210 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001211 mStartTetheringErrorState = new StartTetheringErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001212 mStopTetheringErrorState = new StopTetheringErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001213 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
Erik Kline1fdc2e22017-05-08 17:56:35 +09001214
1215 addState(mInitialState);
1216 addState(mTetherModeAliveState);
1217 addState(mSetIpForwardingEnabledErrorState);
1218 addState(mSetIpForwardingDisabledErrorState);
1219 addState(mStartTetheringErrorState);
1220 addState(mStopTetheringErrorState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001221 addState(mSetDnsForwardersErrorState);
1222
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001223 mNotifyList = new ArrayList<>();
Erik Kline7747fd42017-05-12 16:52:48 +09001224 mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList, mLog);
Erik Klineed962a82017-07-06 19:49:35 +09001225 mOffload = new OffloadWrapper();
Erik Kline32179ff2017-07-04 18:28:11 +09001226
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001227 setInitialState(mInitialState);
1228 }
1229
Erik Kline1fdc2e22017-05-08 17:56:35 +09001230 class InitialState extends State {
1231 @Override
1232 public boolean processMessage(Message message) {
Erik Kline22108902017-07-06 16:40:06 +09001233 logMessage(this, message.what);
Erik Kline1fdc2e22017-05-08 17:56:35 +09001234 switch (message.what) {
1235 case EVENT_IFACE_SERVING_STATE_ACTIVE:
Erik Kline32179ff2017-07-04 18:28:11 +09001236 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
Erik Kline1fdc2e22017-05-08 17:56:35 +09001237 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
1238 handleInterfaceServingStateActive(message.arg1, who);
1239 transitionTo(mTetherModeAliveState);
1240 break;
1241 case EVENT_IFACE_SERVING_STATE_INACTIVE:
Erik Kline32179ff2017-07-04 18:28:11 +09001242 who = (TetherInterfaceStateMachine) message.obj;
Erik Kline1fdc2e22017-05-08 17:56:35 +09001243 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
1244 handleInterfaceServingStateInactive(who);
1245 break;
Erik Kline6e9a1012017-06-06 19:24:21 +09001246 case EVENT_IFACE_UPDATE_LINKPROPERTIES:
1247 // Silently ignore these for now.
1248 break;
Erik Kline1fdc2e22017-05-08 17:56:35 +09001249 default:
1250 return NOT_HANDLED;
1251 }
1252 return HANDLED;
1253 }
1254 }
1255
Erik Kline3a5278f2017-06-24 19:29:10 +09001256 protected boolean turnOnMasterTetherSettings() {
1257 final TetheringConfiguration cfg = mConfig;
1258 try {
1259 mNMService.setIpForwardingEnabled(true);
1260 } catch (Exception e) {
1261 mLog.e(e);
1262 transitionTo(mSetIpForwardingEnabledErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001263 return false;
1264 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001265 // TODO: Randomize DHCPv4 ranges, especially in hotspot mode.
1266 try {
1267 // TODO: Find a more accurate method name (startDHCPv4()?).
1268 mNMService.startTethering(cfg.dhcpRanges);
1269 } catch (Exception e) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001270 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001271 mNMService.stopTethering();
Erik Kline3a5278f2017-06-24 19:29:10 +09001272 mNMService.startTethering(cfg.dhcpRanges);
1273 } catch (Exception ee) {
1274 mLog.e(ee);
1275 transitionTo(mStartTetheringErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001276 return false;
1277 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001278 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001279 mLog.log("SET master tether settings: ON");
1280 return true;
1281 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001282
Erik Kline3a5278f2017-06-24 19:29:10 +09001283 protected boolean turnOffMasterTetherSettings() {
1284 try {
1285 mNMService.stopTethering();
1286 } catch (Exception e) {
1287 mLog.e(e);
1288 transitionTo(mStopTetheringErrorState);
1289 return false;
Erik Kline14f7faf2017-02-14 19:03:09 +09001290 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001291 try {
1292 mNMService.setIpForwardingEnabled(false);
1293 } catch (Exception e) {
1294 mLog.e(e);
1295 transitionTo(mSetIpForwardingDisabledErrorState);
1296 return false;
1297 }
1298 transitionTo(mInitialState);
1299 mLog.log("SET master tether settings: OFF");
1300 return true;
1301 }
Erik Kline14f7faf2017-02-14 19:03:09 +09001302
Erik Kline3a5278f2017-06-24 19:29:10 +09001303 protected void chooseUpstreamType(boolean tryCell) {
Erik Kline6ee73da2017-07-08 20:36:37 +09001304 // We rebuild configuration on ACTION_CONFIGURATION_CHANGED, but we
1305 // do not currently know how to watch for changes in DUN settings.
1306 maybeUpdateConfiguration();
Erik Kline1e2897d2017-06-09 17:08:52 +09001307
Erik Kline3a5278f2017-06-24 19:29:10 +09001308 final NetworkState ns = mUpstreamNetworkMonitor.selectPreferredUpstreamType(
1309 mConfig.preferredUpstreamIfaceTypes);
1310 if (ns == null) {
1311 if (tryCell) {
1312 mUpstreamNetworkMonitor.registerMobileNetworkRequest();
1313 // We think mobile should be coming up; don't set a retry.
1314 } else {
1315 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
Erik Kline1e2897d2017-06-09 17:08:52 +09001316 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001317 }
1318 setUpstreamNetwork(ns);
1319 }
1320
1321 protected void setUpstreamNetwork(NetworkState ns) {
1322 String iface = null;
1323 if (ns != null && ns.linkProperties != null) {
1324 // Find the interface with the default IPv4 route. It may be the
1325 // interface described by linkProperties, or one of the interfaces
1326 // stacked on top of it.
Erik Kline22108902017-07-06 16:40:06 +09001327 mLog.i("Finding IPv4 upstream interface on: " + ns.linkProperties);
Erik Kline3a5278f2017-06-24 19:29:10 +09001328 RouteInfo ipv4Default = RouteInfo.selectBestRoute(
1329 ns.linkProperties.getAllRoutes(), Inet4Address.ANY);
1330 if (ipv4Default != null) {
1331 iface = ipv4Default.getInterface();
Erik Kline22108902017-07-06 16:40:06 +09001332 mLog.i("Found interface " + ipv4Default.getInterface());
Erik Kline3a5278f2017-06-24 19:29:10 +09001333 } else {
Erik Kline22108902017-07-06 16:40:06 +09001334 mLog.i("No IPv4 upstream interface, giving up.");
Erik Kline00019f42016-06-30 19:31:46 +09001335 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001336 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001337
Erik Kline3a5278f2017-06-24 19:29:10 +09001338 if (iface != null) {
1339 setDnsForwarders(ns.network, ns.linkProperties);
Erik Kline6ff17f72015-12-10 20:42:12 +09001340 }
Erik Kline22108902017-07-06 16:40:06 +09001341 notifyDownstreamsOfNewUpstreamIface(iface);
Erik Kline3a5278f2017-06-24 19:29:10 +09001342 if (ns != null && pertainsToCurrentUpstream(ns)) {
1343 // If we already have NetworkState for this network examine
1344 // it immediately, because there likely will be no second
1345 // EVENT_ON_AVAILABLE (it was already received).
1346 handleNewUpstreamNetworkState(ns);
1347 } else if (mCurrentUpstreamIface == null) {
1348 // There are no available upstream networks, or none that
1349 // have an IPv4 default route (current metric for success).
1350 handleNewUpstreamNetworkState(null);
1351 }
1352 }
Erik Kline6ff17f72015-12-10 20:42:12 +09001353
Erik Kline3a5278f2017-06-24 19:29:10 +09001354 protected void setDnsForwarders(final Network network, final LinkProperties lp) {
1355 // TODO: Set v4 and/or v6 DNS per available connectivity.
1356 String[] dnsServers = mConfig.defaultIPv4DNS;
1357 final Collection<InetAddress> dnses = lp.getDnsServers();
1358 // TODO: Properly support the absence of DNS servers.
1359 if (dnses != null && !dnses.isEmpty()) {
1360 // TODO: remove this invocation of NetworkUtils.makeStrings().
1361 dnsServers = NetworkUtils.makeStrings(dnses);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001362 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001363 try {
1364 mNMService.setDnsForwarders(network, dnsServers);
1365 mLog.log(String.format(
1366 "SET DNS forwarders: network=%s dnsServers=%s",
1367 network, Arrays.toString(dnsServers)));
1368 } catch (Exception e) {
1369 // TODO: Investigate how this can fail and what exactly
1370 // happens if/when such failures occur.
1371 mLog.e("setting DNS forwarders failed, " + e);
1372 transitionTo(mSetDnsForwardersErrorState);
1373 }
1374 }
Erik Kline00019f42016-06-30 19:31:46 +09001375
Erik Kline22108902017-07-06 16:40:06 +09001376 protected void notifyDownstreamsOfNewUpstreamIface(String ifaceName) {
1377 mLog.log("Notifying downstreams of upstream=" + ifaceName);
Erik Kline3a5278f2017-06-24 19:29:10 +09001378 mCurrentUpstreamIface = ifaceName;
1379 for (TetherInterfaceStateMachine sm : mNotifyList) {
1380 sm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
1381 ifaceName);
Erik Kline00019f42016-06-30 19:31:46 +09001382 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001383 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001384
Erik Kline3a5278f2017-06-24 19:29:10 +09001385 protected void handleNewUpstreamNetworkState(NetworkState ns) {
1386 mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
Erik Klineed962a82017-07-06 19:49:35 +09001387 mOffload.updateUpstreamNetworkState(ns);
Erik Kline3a5278f2017-06-24 19:29:10 +09001388 }
1389
Erik Klineea9cc482017-03-10 19:35:34 +09001390 private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) {
1391 if (mNotifyList.indexOf(who) < 0) {
1392 mNotifyList.add(who);
1393 mIPv6TetheringCoordinator.addActiveDownstream(who, mode);
1394 }
1395
1396 if (mode == IControlsTethering.STATE_TETHERED) {
Erik Klineed962a82017-07-06 19:49:35 +09001397 // No need to notify OffloadController just yet as there are no
1398 // "offload-able" prefixes to pass along. This will handled
1399 // when the TISM informs Tethering of its LinkProperties.
Erik Klineea9cc482017-03-10 19:35:34 +09001400 mForwardedDownstreams.add(who);
1401 } else {
Erik Klineed962a82017-07-06 19:49:35 +09001402 mOffload.excludeDownstreamInterface(who.interfaceName());
Erik Klineea9cc482017-03-10 19:35:34 +09001403 mForwardedDownstreams.remove(who);
1404 }
Erik Kline216af6d2017-04-27 20:57:23 +09001405
1406 // If this is a Wi-Fi interface, notify WifiManager of the active serving state.
1407 if (who.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
1408 final WifiManager mgr = getWifiManager();
1409 final String iface = who.interfaceName();
1410 switch (mode) {
1411 case IControlsTethering.STATE_TETHERED:
Erik Kline2efb8272017-05-31 15:53:53 +09001412 mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +09001413 break;
1414 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Kline2efb8272017-05-31 15:53:53 +09001415 mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +09001416 break;
1417 default:
1418 Log.wtf(TAG, "Unknown active serving mode: " + mode);
1419 break;
1420 }
1421 }
Erik Klineea9cc482017-03-10 19:35:34 +09001422 }
1423
1424 private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) {
1425 mNotifyList.remove(who);
1426 mIPv6TetheringCoordinator.removeActiveDownstream(who);
Erik Klineed962a82017-07-06 19:49:35 +09001427 mOffload.excludeDownstreamInterface(who.interfaceName());
Erik Klineea9cc482017-03-10 19:35:34 +09001428 mForwardedDownstreams.remove(who);
Erik Kline216af6d2017-04-27 20:57:23 +09001429
1430 // If this is a Wi-Fi interface, tell WifiManager of any errors.
1431 if (who.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
1432 if (who.lastError() != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
1433 getWifiManager().updateInterfaceIpState(
Erik Kline2efb8272017-05-31 15:53:53 +09001434 who.interfaceName(), IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline216af6d2017-04-27 20:57:23 +09001435 }
1436 }
Erik Klineea9cc482017-03-10 19:35:34 +09001437 }
1438
Erik Kline3a5278f2017-06-24 19:29:10 +09001439 private void handleUpstreamNetworkMonitorCallback(int arg1, Object o) {
Erik Kline32179ff2017-07-04 18:28:11 +09001440 if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) {
Erik Klineed962a82017-07-06 19:49:35 +09001441 mOffload.sendOffloadExemptPrefixes((Set<IpPrefix>) o);
Erik Kline3a5278f2017-06-24 19:29:10 +09001442 return;
1443 }
1444
1445 final NetworkState ns = (NetworkState) o;
1446
1447 if (ns == null || !pertainsToCurrentUpstream(ns)) {
1448 // TODO: In future, this is where upstream evaluation and selection
1449 // could be handled for notifications which include sufficient data.
1450 // For example, after CONNECTIVITY_ACTION listening is removed, here
1451 // is where we could observe a Wi-Fi network becoming available and
1452 // passing validation.
1453 if (mCurrentUpstreamIface == null) {
1454 // If we have no upstream interface, try to run through upstream
1455 // selection again. If, for example, IPv4 connectivity has shown up
1456 // after IPv6 (e.g., 464xlat became available) we want the chance to
1457 // notice and act accordingly.
1458 chooseUpstreamType(false);
1459 }
1460 return;
1461 }
1462
1463 switch (arg1) {
1464 case UpstreamNetworkMonitor.EVENT_ON_AVAILABLE:
1465 // The default network changed, or DUN connected
1466 // before this callback was processed. Updates
1467 // for the current NetworkCapabilities and
1468 // LinkProperties have been requested (default
1469 // request) or are being sent shortly (DUN). Do
1470 // nothing until they arrive; if no updates
1471 // arrive there's nothing to do.
1472 break;
1473 case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES:
1474 handleNewUpstreamNetworkState(ns);
1475 break;
1476 case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
1477 setDnsForwarders(ns.network, ns.linkProperties);
1478 handleNewUpstreamNetworkState(ns);
1479 break;
1480 case UpstreamNetworkMonitor.EVENT_ON_LOST:
1481 // TODO: Re-evaluate possible upstreams. Currently upstream
1482 // reevaluation is triggered via received CONNECTIVITY_ACTION
1483 // broadcasts that result in being passed a
1484 // TetherMasterSM.CMD_UPSTREAM_CHANGED.
1485 handleNewUpstreamNetworkState(null);
1486 break;
1487 default:
1488 mLog.e("Unknown arg1 value: " + arg1);
1489 break;
1490 }
1491 }
1492
1493 class TetherModeAliveState extends State {
Erik Klineea9cc482017-03-10 19:35:34 +09001494 boolean mUpstreamWanted = false;
Erik Kline6ff17f72015-12-10 20:42:12 +09001495 boolean mTryCell = true;
Erik Klinee0cce212017-03-06 14:05:23 +09001496
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001497 @Override
1498 public void enter() {
Erik Kline1fdc2e22017-05-08 17:56:35 +09001499 // If turning on master tether settings fails, we have already
1500 // transitioned to an error state; exit early.
1501 if (!turnOnMasterTetherSettings()) {
1502 return;
1503 }
1504
Erik Kline227648f2017-01-20 20:26:10 +09001505 mSimChange.startListening();
Erik Kline6ff17f72015-12-10 20:42:12 +09001506 mUpstreamNetworkMonitor.start();
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001507
Erik Klinef4b6e342017-04-25 19:19:59 +09001508 // TODO: De-duplicate with updateUpstreamWanted() below.
Erik Klineea9cc482017-03-10 19:35:34 +09001509 if (upstreamWanted()) {
1510 mUpstreamWanted = true;
Erik Klineed962a82017-07-06 19:49:35 +09001511 mOffload.start();
Erik Klineea9cc482017-03-10 19:35:34 +09001512 chooseUpstreamType(true);
1513 mTryCell = false;
1514 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001515 }
Erik Klinefa37b2f2016-08-02 18:27:03 +09001516
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001517 @Override
1518 public void exit() {
Erik Klineed962a82017-07-06 19:49:35 +09001519 mOffload.stop();
Erik Kline6ff17f72015-12-10 20:42:12 +09001520 mUpstreamNetworkMonitor.stop();
Erik Kline227648f2017-01-20 20:26:10 +09001521 mSimChange.stopListening();
Erik Kline22108902017-07-06 16:40:06 +09001522 notifyDownstreamsOfNewUpstreamIface(null);
Erik Klinefa37b2f2016-08-02 18:27:03 +09001523 handleNewUpstreamNetworkState(null);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001524 }
Erik Klinefa37b2f2016-08-02 18:27:03 +09001525
Erik Klineea9cc482017-03-10 19:35:34 +09001526 private boolean updateUpstreamWanted() {
1527 final boolean previousUpstreamWanted = mUpstreamWanted;
1528 mUpstreamWanted = upstreamWanted();
Erik Klinef4b6e342017-04-25 19:19:59 +09001529 if (mUpstreamWanted != previousUpstreamWanted) {
1530 if (mUpstreamWanted) {
Erik Klineed962a82017-07-06 19:49:35 +09001531 mOffload.start();
Erik Klinef4b6e342017-04-25 19:19:59 +09001532 } else {
Erik Klineed962a82017-07-06 19:49:35 +09001533 mOffload.stop();
Erik Klinef4b6e342017-04-25 19:19:59 +09001534 }
1535 }
Erik Klineea9cc482017-03-10 19:35:34 +09001536 return previousUpstreamWanted;
1537 }
1538
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001539 @Override
1540 public boolean processMessage(Message message) {
Erik Kline22108902017-07-06 16:40:06 +09001541 logMessage(this, message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001542 boolean retValue = true;
1543 switch (message.what) {
Erik Klineea9cc482017-03-10 19:35:34 +09001544 case EVENT_IFACE_SERVING_STATE_ACTIVE: {
Erik Kline32179ff2017-07-04 18:28:11 +09001545 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001546 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
Erik Klineea9cc482017-03-10 19:35:34 +09001547 handleInterfaceServingStateActive(message.arg1, who);
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001548 who.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
Erik Kline6ff17f72015-12-10 20:42:12 +09001549 mCurrentUpstreamIface);
Erik Klineea9cc482017-03-10 19:35:34 +09001550 // If there has been a change and an upstream is now
1551 // desired, kick off the selection process.
1552 final boolean previousUpstreamWanted = updateUpstreamWanted();
1553 if (!previousUpstreamWanted && mUpstreamWanted) {
1554 chooseUpstreamType(true);
1555 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001556 break;
Erik Kline6e29bf02016-08-15 16:16:18 +09001557 }
Erik Klineea9cc482017-03-10 19:35:34 +09001558 case EVENT_IFACE_SERVING_STATE_INACTIVE: {
Erik Kline32179ff2017-07-04 18:28:11 +09001559 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001560 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
Erik Klineea9cc482017-03-10 19:35:34 +09001561 handleInterfaceServingStateInactive(who);
1562
1563 if (mNotifyList.isEmpty()) {
Erik Kline47222fc2017-04-30 19:36:15 +09001564 // This transitions us out of TetherModeAliveState,
1565 // either to InitialState or an error state.
Erik Kline1fdc2e22017-05-08 17:56:35 +09001566 turnOffMasterTetherSettings();
1567 break;
1568 }
1569
1570 if (DBG) {
1571 Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
1572 " live requests:");
1573 for (TetherInterfaceStateMachine o : mNotifyList) {
1574 Log.d(TAG, " " + o);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001575 }
1576 }
Erik Klineea9cc482017-03-10 19:35:34 +09001577 // If there has been a change and an upstream is no
1578 // longer desired, release any mobile requests.
1579 final boolean previousUpstreamWanted = updateUpstreamWanted();
1580 if (previousUpstreamWanted && !mUpstreamWanted) {
1581 mUpstreamNetworkMonitor.releaseMobileNetworkRequest();
1582 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001583 break;
Erik Kline6e29bf02016-08-15 16:16:18 +09001584 }
Erik Kline6e9a1012017-06-06 19:24:21 +09001585 case EVENT_IFACE_UPDATE_LINKPROPERTIES: {
1586 final LinkProperties newLp = (LinkProperties) message.obj;
1587 if (message.arg1 == IControlsTethering.STATE_TETHERED) {
Erik Klineed962a82017-07-06 19:49:35 +09001588 mOffload.updateDownstreamLinkProperties(newLp);
Erik Kline6e9a1012017-06-06 19:24:21 +09001589 } else {
Erik Klineed962a82017-07-06 19:49:35 +09001590 mOffload.excludeDownstreamInterface(newLp.getInterfaceName());
Erik Kline6e9a1012017-06-06 19:24:21 +09001591 }
1592 break;
1593 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001594 case CMD_UPSTREAM_CHANGED:
Erik Klineea9cc482017-03-10 19:35:34 +09001595 updateUpstreamWanted();
1596 if (!mUpstreamWanted) break;
1597
Erik Klinefb413432017-02-14 18:26:04 +09001598 // Need to try DUN immediately if Wi-Fi goes down.
1599 chooseUpstreamType(true);
1600 mTryCell = false;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001601 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001602 case CMD_RETRY_UPSTREAM:
Erik Klineea9cc482017-03-10 19:35:34 +09001603 updateUpstreamWanted();
1604 if (!mUpstreamWanted) break;
1605
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001606 chooseUpstreamType(mTryCell);
1607 mTryCell = !mTryCell;
1608 break;
Erik Kline00019f42016-06-30 19:31:46 +09001609 case EVENT_UPSTREAM_CALLBACK: {
Erik Klineea9cc482017-03-10 19:35:34 +09001610 updateUpstreamWanted();
Erik Kline3a5278f2017-06-24 19:29:10 +09001611 if (mUpstreamWanted) {
1612 handleUpstreamNetworkMonitorCallback(message.arg1, message.obj);
Erik Kline6ff17f72015-12-10 20:42:12 +09001613 }
1614 break;
Erik Kline00019f42016-06-30 19:31:46 +09001615 }
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001616 default:
1617 retValue = false;
1618 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001619 }
1620 return retValue;
1621 }
1622 }
1623
Wink Saville64c42ca2011-04-18 14:55:10 -07001624 class ErrorState extends State {
Erik Kline8351faa2017-04-17 16:47:23 +09001625 private int mErrorNotification;
1626
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001627 @Override
1628 public boolean processMessage(Message message) {
1629 boolean retValue = true;
1630 switch (message.what) {
Erik Klineea9cc482017-03-10 19:35:34 +09001631 case EVENT_IFACE_SERVING_STATE_ACTIVE:
Erik Kline32179ff2017-07-04 18:28:11 +09001632 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine) message.obj;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001633 who.sendMessage(mErrorNotification);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001634 break;
Yohei, Oshima977aad52016-12-08 13:39:20 +09001635 case CMD_CLEAR_ERROR:
1636 mErrorNotification = ConnectivityManager.TETHER_ERROR_NO_ERROR;
1637 transitionTo(mInitialState);
1638 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001639 default:
1640 retValue = false;
1641 }
1642 return retValue;
1643 }
Erik Kline8351faa2017-04-17 16:47:23 +09001644
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001645 void notify(int msgType) {
1646 mErrorNotification = msgType;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001647 for (TetherInterfaceStateMachine sm : mNotifyList) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001648 sm.sendMessage(msgType);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001649 }
1650 }
1651
1652 }
Erik Kline8351faa2017-04-17 16:47:23 +09001653
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001654 class SetIpForwardingEnabledErrorState extends ErrorState {
1655 @Override
1656 public void enter() {
1657 Log.e(TAG, "Error in setIpForwardingEnabled");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001658 notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001659 }
1660 }
1661
1662 class SetIpForwardingDisabledErrorState extends ErrorState {
1663 @Override
1664 public void enter() {
1665 Log.e(TAG, "Error in setIpForwardingDisabled");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001666 notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001667 }
1668 }
1669
1670 class StartTetheringErrorState extends ErrorState {
1671 @Override
1672 public void enter() {
1673 Log.e(TAG, "Error in startTethering");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001674 notify(TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001675 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001676 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001677 } catch (Exception e) {}
1678 }
1679 }
1680
1681 class StopTetheringErrorState extends ErrorState {
1682 @Override
1683 public void enter() {
1684 Log.e(TAG, "Error in stopTethering");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001685 notify(TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001686 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001687 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001688 } catch (Exception e) {}
1689 }
1690 }
1691
1692 class SetDnsForwardersErrorState extends ErrorState {
1693 @Override
1694 public void enter() {
1695 Log.e(TAG, "Error in setDnsForwarders");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001696 notify(TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001697 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001698 mNMService.stopTethering();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001699 } catch (Exception e) {}
1700 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001701 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001702 } catch (Exception e) {}
1703 }
1704 }
Erik Klineed962a82017-07-06 19:49:35 +09001705
1706 // A wrapper class to handle multiple situations where several calls to
1707 // the OffloadController need to happen together.
1708 //
1709 // TODO: This suggests that the interface between OffloadController and
1710 // Tethering is in need of improvement. Refactor these calls into the
1711 // OffloadController implementation.
1712 class OffloadWrapper {
1713 public void start() {
1714 mOffloadController.start();
1715 sendOffloadExemptPrefixes();
1716 }
1717
1718 public void stop() {
1719 mOffloadController.stop();
1720 }
1721
1722 public void updateUpstreamNetworkState(NetworkState ns) {
1723 mOffloadController.setUpstreamLinkProperties(
1724 (ns != null) ? ns.linkProperties : null);
1725 }
1726
1727 public void updateDownstreamLinkProperties(LinkProperties newLp) {
1728 // Update the list of offload-exempt prefixes before adding
1729 // new prefixes on downstream interfaces to the offload HAL.
1730 sendOffloadExemptPrefixes();
1731 mOffloadController.notifyDownstreamLinkProperties(newLp);
1732 }
1733
1734 public void excludeDownstreamInterface(String ifname) {
1735 // This and other interfaces may be in local-only hotspot mode;
1736 // resend all local prefixes to the OffloadController.
1737 sendOffloadExemptPrefixes();
1738 mOffloadController.removeDownstreamInterface(ifname);
1739 }
1740
1741 public void sendOffloadExemptPrefixes() {
1742 sendOffloadExemptPrefixes(mUpstreamNetworkMonitor.getLocalPrefixes());
1743 }
1744
1745 public void sendOffloadExemptPrefixes(final Set<IpPrefix> localPrefixes) {
1746 // Add in well-known minimum set.
1747 PrefixUtils.addNonForwardablePrefixes(localPrefixes);
1748 // Add tragically hardcoded prefixes.
1749 localPrefixes.add(PrefixUtils.DEFAULT_WIFI_P2P_PREFIX);
1750
1751 // Maybe add prefixes or addresses for downstreams, depending on
1752 // the IP serving mode of each.
1753 for (TetherInterfaceStateMachine tism : mNotifyList) {
1754 final LinkProperties lp = tism.linkProperties();
1755
1756 switch (tism.servingMode()) {
1757 case IControlsTethering.STATE_UNAVAILABLE:
1758 case IControlsTethering.STATE_AVAILABLE:
1759 // No usable LinkProperties in these states.
1760 continue;
1761 case IControlsTethering.STATE_TETHERED:
1762 // Only add IPv4 /32 and IPv6 /128 prefixes. The
1763 // directly-connected prefixes will be sent as
1764 // downstream "offload-able" prefixes.
1765 for (LinkAddress addr : lp.getAllLinkAddresses()) {
1766 final InetAddress ip = addr.getAddress();
1767 if (ip.isLinkLocalAddress()) continue;
1768 localPrefixes.add(PrefixUtils.ipAddressAsPrefix(ip));
1769 }
1770 break;
1771 case IControlsTethering.STATE_LOCAL_ONLY:
1772 // Add prefixes covering all local IPs.
1773 localPrefixes.addAll(PrefixUtils.localPrefixesFrom(lp));
1774 break;
1775 }
1776 }
1777
1778 mOffloadController.setLocalPrefixes(localPrefixes);
1779 }
1780 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001781 }
1782
Christopher Wiley499a57a2016-05-16 16:19:07 -07001783 @Override
Lorenzo Colittie3805462015-06-03 11:18:24 +09001784 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Christopher Wiley499a57a2016-05-16 16:19:07 -07001785 // Binder.java closes the resource for us.
1786 @SuppressWarnings("resource")
Lorenzo Colittie3805462015-06-03 11:18:24 +09001787 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06001788 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001789
Lorenzo Colittie3805462015-06-03 11:18:24 +09001790 pw.println("Tethering:");
1791 pw.increaseIndent();
Lorenzo Colittie3805462015-06-03 11:18:24 +09001792
Erik Kline9db1b542017-03-16 14:10:27 +09001793 pw.println("Configuration:");
1794 pw.increaseIndent();
1795 final TetheringConfiguration cfg = mConfig;
1796 cfg.dump(pw);
1797 pw.decreaseIndent();
1798
1799 synchronized (mPublicSync) {
Robert Greenwaltb4453622011-11-03 16:01:40 -07001800 pw.println("Tether state:");
Lorenzo Colittie3805462015-06-03 11:18:24 +09001801 pw.increaseIndent();
Christopher Wileyd985dde2016-05-31 10:44:35 -07001802 for (int i = 0; i < mTetherStates.size(); i++) {
1803 final String iface = mTetherStates.keyAt(i);
1804 final TetherState tetherState = mTetherStates.valueAt(i);
1805 pw.print(iface + " - ");
1806
Hugo Benichib55fb222017-03-10 14:20:57 +09001807 switch (tetherState.lastState) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001808 case IControlsTethering.STATE_UNAVAILABLE:
1809 pw.print("UnavailableState");
1810 break;
1811 case IControlsTethering.STATE_AVAILABLE:
1812 pw.print("AvailableState");
1813 break;
1814 case IControlsTethering.STATE_TETHERED:
1815 pw.print("TetheredState");
1816 break;
Erik Klineca41be72017-04-20 22:59:16 +09001817 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Klineea9cc482017-03-10 19:35:34 +09001818 pw.print("LocalHotspotState");
1819 break;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001820 default:
1821 pw.print("UnknownState");
1822 break;
1823 }
Hugo Benichib55fb222017-03-10 14:20:57 +09001824 pw.println(" - lastError = " + tetherState.lastError);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001825 }
Erik Klineea9cc482017-03-10 19:35:34 +09001826 pw.println("Upstream wanted: " + upstreamWanted());
Erik Klineee363c42017-05-29 09:11:03 +09001827 pw.println("Current upstream interface: " + mCurrentUpstreamIface);
Lorenzo Colittie3805462015-06-03 11:18:24 +09001828 pw.decreaseIndent();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001829 }
Erik Kline1fdc2e22017-05-08 17:56:35 +09001830
Lorenzo Colittic2519c52017-07-13 01:48:26 +09001831 pw.println("Hardware offload:");
1832 pw.increaseIndent();
1833 mOffloadController.dump(pw);
1834 pw.decreaseIndent();
1835
Erik Kline1fdc2e22017-05-08 17:56:35 +09001836 pw.println("Log:");
1837 pw.increaseIndent();
Erik Kline7747fd42017-05-12 16:52:48 +09001838 if (argsContain(args, SHORT_ARG)) {
1839 pw.println("<log removed for brevity>");
1840 } else {
1841 mLog.dump(fd, pw, args);
1842 }
Erik Kline1fdc2e22017-05-08 17:56:35 +09001843 pw.decreaseIndent();
1844
Lorenzo Colittie3805462015-06-03 11:18:24 +09001845 pw.decreaseIndent();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001846 }
Christopher Wileye03fb442016-05-18 13:45:20 -07001847
Erik Kline7747fd42017-05-12 16:52:48 +09001848 private static boolean argsContain(String[] args, String target) {
1849 for (String arg : args) {
Erik Klineee363c42017-05-29 09:11:03 +09001850 if (target.equals(arg)) return true;
Erik Kline7747fd42017-05-12 16:52:48 +09001851 }
1852 return false;
1853 }
1854
Erik Kline6e9a1012017-06-06 19:24:21 +09001855 private IControlsTethering makeControlCallback(String ifname) {
1856 return new IControlsTethering() {
1857 @Override
1858 public void updateInterfaceState(
1859 TetherInterfaceStateMachine who, int state, int lastError) {
1860 notifyInterfaceStateChange(ifname, who, state, lastError);
1861 }
1862
1863 @Override
1864 public void updateLinkProperties(
1865 TetherInterfaceStateMachine who, LinkProperties newLp) {
1866 notifyLinkPropertiesChanged(ifname, who, newLp);
1867 }
1868 };
1869 }
1870
1871 // TODO: Move into TetherMasterSM.
1872 private void notifyInterfaceStateChange(
1873 String iface, TetherInterfaceStateMachine who, int state, int error) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001874 synchronized (mPublicSync) {
Erik Kline216af6d2017-04-27 20:57:23 +09001875 final TetherState tetherState = mTetherStates.get(iface);
Hugo Benichib55fb222017-03-10 14:20:57 +09001876 if (tetherState != null && tetherState.stateMachine.equals(who)) {
1877 tetherState.lastState = state;
1878 tetherState.lastError = error;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001879 } else {
1880 if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
1881 }
1882 }
1883
Erik Kline7747fd42017-05-12 16:52:48 +09001884 mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
Christopher Wileyd985dde2016-05-31 10:44:35 -07001885
Christopher Wileydeebfec2016-09-16 11:14:36 -07001886 try {
1887 // Notify that we're tethering (or not) this interface.
1888 // This is how data saver for instance knows if the user explicitly
1889 // turned on tethering (thus keeping us from being in data saver mode).
1890 mPolicyManager.onTetheringChanged(iface, state == IControlsTethering.STATE_TETHERED);
1891 } catch (RemoteException e) {
1892 // Not really very much we can do here.
1893 }
1894
Yohei, Oshima977aad52016-12-08 13:39:20 +09001895 // If TetherMasterSM is in ErrorState, TetherMasterSM stays there.
1896 // Thus we give a chance for TetherMasterSM to recover to InitialState
1897 // by sending CMD_CLEAR_ERROR
1898 if (error == ConnectivityManager.TETHER_ERROR_MASTER_ERROR) {
1899 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_CLEAR_ERROR, who);
1900 }
Erik Klineea9cc482017-03-10 19:35:34 +09001901 int which;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001902 switch (state) {
1903 case IControlsTethering.STATE_UNAVAILABLE:
1904 case IControlsTethering.STATE_AVAILABLE:
Erik Klineea9cc482017-03-10 19:35:34 +09001905 which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001906 break;
1907 case IControlsTethering.STATE_TETHERED:
Erik Klineca41be72017-04-20 22:59:16 +09001908 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Klineea9cc482017-03-10 19:35:34 +09001909 which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001910 break;
Erik Klineea9cc482017-03-10 19:35:34 +09001911 default:
1912 Log.wtf(TAG, "Unknown interface state: " + state);
1913 return;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001914 }
Erik Klineea9cc482017-03-10 19:35:34 +09001915 mTetherMasterSM.sendMessage(which, state, 0, who);
Christopher Wileyd985dde2016-05-31 10:44:35 -07001916 sendTetherStateChangedBroadcast();
1917 }
1918
Erik Kline6e9a1012017-06-06 19:24:21 +09001919 private void notifyLinkPropertiesChanged(String iface, TetherInterfaceStateMachine who,
1920 LinkProperties newLp) {
1921 final int state;
1922 synchronized (mPublicSync) {
1923 final TetherState tetherState = mTetherStates.get(iface);
1924 if (tetherState != null && tetherState.stateMachine.equals(who)) {
1925 state = tetherState.lastState;
1926 } else {
1927 mLog.log("got notification from stale iface " + iface);
1928 return;
1929 }
1930 }
1931
Erik Kline7fd696c2017-06-12 18:20:08 +09001932 mLog.log(String.format(
1933 "OBSERVED LinkProperties update iface=%s state=%s lp=%s",
1934 iface, IControlsTethering.getStateString(state), newLp));
Erik Kline6e9a1012017-06-06 19:24:21 +09001935 final int which = TetherMasterSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
1936 mTetherMasterSM.sendMessage(which, state, 0, newLp);
1937 }
1938
Erik Kline4dd9bb82017-04-26 11:11:07 +09001939 private void maybeTrackNewInterfaceLocked(final String iface) {
1940 // If we don't care about this type of interface, ignore.
1941 final int interfaceType = ifaceNameToType(iface);
1942 if (interfaceType == ConnectivityManager.TETHERING_INVALID) {
1943 mLog.log(iface + " is not a tetherable iface, ignoring");
1944 return;
1945 }
Erik Klinea9cde8b2017-06-20 21:18:31 +09001946 maybeTrackNewInterfaceLocked(iface, interfaceType);
1947 }
Erik Kline4dd9bb82017-04-26 11:11:07 +09001948
Erik Klinea9cde8b2017-06-20 21:18:31 +09001949 private void maybeTrackNewInterfaceLocked(final String iface, int interfaceType) {
Erik Kline4dd9bb82017-04-26 11:11:07 +09001950 // If we have already started a TISM for this interface, skip.
1951 if (mTetherStates.containsKey(iface)) {
1952 mLog.log("active iface (" + iface + ") reported as added, ignoring");
1953 return;
1954 }
1955
1956 mLog.log("adding TetheringInterfaceStateMachine for: " + iface);
1957 final TetherState tetherState = new TetherState(
1958 new TetherInterfaceStateMachine(
Erik Kline6e9a1012017-06-06 19:24:21 +09001959 iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
Erik Klinea8e2e792017-06-13 21:32:10 +09001960 makeControlCallback(iface)));
Christopher Wileyd985dde2016-05-31 10:44:35 -07001961 mTetherStates.put(iface, tetherState);
Hugo Benichib55fb222017-03-10 14:20:57 +09001962 tetherState.stateMachine.start();
Christopher Wileye03fb442016-05-18 13:45:20 -07001963 }
Erik Kline3e756652017-01-17 13:42:19 +09001964
Erik Kline4dd9bb82017-04-26 11:11:07 +09001965 private void stopTrackingInterfaceLocked(final String iface) {
1966 final TetherState tetherState = mTetherStates.get(iface);
1967 if (tetherState == null) {
1968 mLog.log("attempting to remove unknown iface (" + iface + "), ignoring");
1969 return;
1970 }
Erik Kline6e9a1012017-06-06 19:24:21 +09001971 tetherState.stateMachine.stop();
Erik Kline4dd9bb82017-04-26 11:11:07 +09001972 mLog.log("removing TetheringInterfaceStateMachine for: " + iface);
1973 mTetherStates.remove(iface);
1974 }
1975
Erik Kline3e756652017-01-17 13:42:19 +09001976 private static String[] copy(String[] strarray) {
1977 return Arrays.copyOf(strarray, strarray.length);
1978 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001979}