blob: b6573352a4825865c40c14b740040d906b9b5910 [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;
Robert Greenwalt05d89362011-01-23 16:04:05 -080052import android.net.LinkProperties;
Lorenzo Colittib57edc52014-08-22 17:10:50 -070053import android.net.Network;
Erik Kline0c9cb2b2015-11-20 17:47:08 +090054import android.net.NetworkCapabilities;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080055import android.net.NetworkInfo;
Erik Kline0c9cb2b2015-11-20 17:47:08 +090056import android.net.NetworkRequest;
Erik Kline6ff17f72015-12-10 20:42:12 +090057import android.net.NetworkState;
Robert Greenwalte5903732011-02-22 16:00:42 -080058import android.net.NetworkUtils;
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090059import android.net.RouteInfo;
Erik Kline7747fd42017-05-12 16:52:48 +090060import android.net.util.SharedLog;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080061import android.net.wifi.WifiManager;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080062import android.os.Binder;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080063import android.os.Bundle;
Erik Klinef4b6e342017-04-25 19:19:59 +090064import android.os.Handler;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080065import android.os.INetworkManagementService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -080066import android.os.Looper;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080067import android.os.Message;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080068import android.os.Parcel;
Christopher Wileydeebfec2016-09-16 11:14:36 -070069import android.os.RemoteException;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080070import android.os.ResultReceiver;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070071import android.os.UserHandle;
Jeremy Klein15f3d212016-01-24 17:01:09 -080072import android.provider.Settings;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080073import android.telephony.CarrierConfigManager;
Junda Liu38531582014-10-28 13:52:51 -070074import android.telephony.TelephonyManager;
Lorenzo Colitticd63d242016-04-10 15:39:53 +090075import android.text.TextUtils;
Christopher Wileye9490392016-05-26 15:57:29 -070076import android.util.ArrayMap;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080077import android.util.Log;
Lorenzo Colitticd63d242016-04-10 15:39:53 +090078import android.util.SparseArray;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080079
Christopher Wiley497c1472016-10-11 13:26:03 -070080import com.android.internal.annotations.VisibleForTesting;
Chris Wren282cfef2017-03-27 15:01:44 -040081import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
Geoffrey Pitschaf759c52017-02-15 09:35:38 -050082import com.android.internal.notification.SystemNotificationChannels;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -080083import com.android.internal.telephony.IccCardConstants;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -080084import com.android.internal.telephony.TelephonyIntents;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060085import com.android.internal.util.DumpUtils;
Jeremy Klein36c7aa02016-01-22 14:11:45 -080086import com.android.internal.util.IndentingPrintWriter;
Lorenzo Colitticd63d242016-04-10 15:39:53 +090087import com.android.internal.util.MessageUtils;
88import com.android.internal.util.Protocol;
Wink Saville64c42ca2011-04-18 14:55:10 -070089import com.android.internal.util.State;
90import com.android.internal.util.StateMachine;
Christopher Wileye03fb442016-05-18 13:45:20 -070091import com.android.server.connectivity.tethering.IControlsTethering;
Erik Kline1eb8c692016-07-08 17:21:26 +090092import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Klinee0cce212017-03-06 14:05:23 +090093import com.android.server.connectivity.tethering.OffloadController;
Erik Kline227648f2017-01-20 20:26:10 +090094import com.android.server.connectivity.tethering.SimChangeListener;
Mitchell Wills7040b4e2016-05-23 16:40:10 -070095import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
Hugo Benichib55fb222017-03-10 14:20:57 +090096import com.android.server.connectivity.tethering.TetheringConfiguration;
Erik Kline47222fc2017-04-30 19:36:15 +090097import com.android.server.connectivity.tethering.TetheringDependencies;
Erik Kline9bba3402017-01-13 16:46:52 +090098import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Lorenzo Colittif4e90ea2013-10-31 23:30:47 +090099import com.android.server.net.BaseNetworkObserver;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800100
101import java.io.FileDescriptor;
102import java.io.PrintWriter;
Robert Greenwalt4f74d552011-12-19 16:59:31 -0800103import java.net.Inet4Address;
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800104import java.net.InetAddress;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800105import java.util.ArrayList;
Lorenzo Colittib57edc52014-08-22 17:10:50 -0700106import java.util.Arrays;
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700107import java.util.Collection;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800108import java.util.HashMap;
Erik Klineea9cc482017-03-10 19:35:34 +0900109import java.util.HashSet;
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700110import java.util.Iterator;
Erik Klineea9cc482017-03-10 19:35:34 +0900111import java.util.Map;
Erik Kline3a5278f2017-06-24 19:29:10 +0900112import java.util.Set;
Robert Greenwalt2ffe4122014-12-12 12:22:31 -0800113import java.util.concurrent.atomic.AtomicInteger;
114
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700115
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800116/**
117 * @hide
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800118 *
Christopher Wiley3b1d9222016-05-20 16:44:04 -0700119 * This class holds much of the business logic to allow Android devices
120 * to act as IP gateways via USB, BT, and WiFi interfaces.
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800121 */
Erik Kline6e9a1012017-06-06 19:24:21 +0900122public class Tethering extends BaseNetworkObserver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800123
Hugo Benichib55fb222017-03-10 14:20:57 +0900124 private final static String TAG = Tethering.class.getSimpleName();
Joe Onorato12acbd72016-02-01 17:49:31 -0800125 private final static boolean DBG = false;
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800126 private final static boolean VDBG = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800127
Christopher Wiley497c1472016-10-11 13:26:03 -0700128 protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning";
129
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900130 private static final Class[] messageClasses = {
Mitchell Wills7040b4e2016-05-23 16:40:10 -0700131 Tethering.class, TetherMasterSM.class, TetherInterfaceStateMachine.class
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900132 };
133 private static final SparseArray<String> sMagicDecoderRing =
134 MessageUtils.findMessageNames(messageClasses);
135
Hugo Benichib55fb222017-03-10 14:20:57 +0900136 // {@link ComponentName} of the Service used to run tether provisioning.
137 private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources
138 .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
139
140 private static class TetherState {
141 public final TetherInterfaceStateMachine stateMachine;
142 public int lastState;
143 public int lastError;
Erik Klineea9cc482017-03-10 19:35:34 +0900144
Hugo Benichib55fb222017-03-10 14:20:57 +0900145 public TetherState(TetherInterfaceStateMachine sm) {
146 stateMachine = sm;
147 // Assume all state machines start out available and with no errors.
148 lastState = IControlsTethering.STATE_AVAILABLE;
149 lastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
150 }
Erik Klineea9cc482017-03-10 19:35:34 +0900151
152 public boolean isCurrentlyServing() {
153 switch (lastState) {
154 case IControlsTethering.STATE_TETHERED:
Erik Klineca41be72017-04-20 22:59:16 +0900155 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Klineea9cc482017-03-10 19:35:34 +0900156 return true;
157 default:
158 return false;
159 }
160 }
Hugo Benichib55fb222017-03-10 14:20:57 +0900161 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700162
Erik Kline7747fd42017-05-12 16:52:48 +0900163 private final SharedLog mLog = new SharedLog(TAG);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900164
Robert Greenwaltb4453622011-11-03 16:01:40 -0700165 // used to synchronize public access to members
Erik Kline6ff17f72015-12-10 20:42:12 +0900166 private final Object mPublicSync;
Hugo Benichib55fb222017-03-10 14:20:57 +0900167 private final Context mContext;
168 private final ArrayMap<String, TetherState> mTetherStates;
169 private final BroadcastReceiver mStateReceiver;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700170 private final INetworkManagementService mNMService;
171 private final INetworkStatsService mStatsService;
Christopher Wileydeebfec2016-09-16 11:14:36 -0700172 private final INetworkPolicyManager mPolicyManager;
Erik Kline6ff17f72015-12-10 20:42:12 +0900173 private final Looper mLooper;
Christopher Wiley497c1472016-10-11 13:26:03 -0700174 private final MockableSystemProperties mSystemProperties;
Erik Kline6ff17f72015-12-10 20:42:12 +0900175 private final StateMachine mTetherMasterSM;
Erik Klinee0cce212017-03-06 14:05:23 +0900176 private final OffloadController mOffloadController;
Erik Kline6ff17f72015-12-10 20:42:12 +0900177 private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
Erik Kline6e9a1012017-06-06 19:24:21 +0900178 // TODO: Figure out how to merge this and other downstream-tracking objects
179 // into a single coherent structure.
Erik Klineea9cc482017-03-10 19:35:34 +0900180 private final HashSet<TetherInterfaceStateMachine> mForwardedDownstreams;
Erik Kline227648f2017-01-20 20:26:10 +0900181 private final SimChangeListener mSimChange;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800182
Hugo Benichib55fb222017-03-10 14:20:57 +0900183 private volatile TetheringConfiguration mConfig;
184 private String mCurrentUpstreamIface;
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400185 private Notification.Builder mTetheredNotificationBuilder;
186 private int mLastNotificationId;
Erik Klineea9cc482017-03-10 19:35:34 +0900187
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700188 private boolean mRndisEnabled; // track the RNDIS function enabled state
189 private boolean mUsbTetherRequested; // true if USB tethering should be started
190 // when RNDIS is enabled
Erik Kline6e9a1012017-06-06 19:24:21 +0900191 // True iff. WiFi tethering should be started when soft AP is ready.
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700192 private boolean mWifiTetherRequested;
193
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700194 public Tethering(Context context, INetworkManagementService nmService,
Christopher Wiley497c1472016-10-11 13:26:03 -0700195 INetworkStatsService statsService, INetworkPolicyManager policyManager,
Erik Kline47222fc2017-04-30 19:36:15 +0900196 Looper looper, MockableSystemProperties systemProperties,
197 TetheringDependencies deps) {
Erik Kline7747fd42017-05-12 16:52:48 +0900198 mLog.mark("constructed");
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800199 mContext = context;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700200 mNMService = nmService;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700201 mStatsService = statsService;
Christopher Wileydeebfec2016-09-16 11:14:36 -0700202 mPolicyManager = policyManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700203 mLooper = looper;
204 mSystemProperties = systemProperties;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800205
Robert Greenwaltb4453622011-11-03 16:01:40 -0700206 mPublicSync = new Object();
207
Christopher Wileyd985dde2016-05-31 10:44:35 -0700208 mTetherStates = new ArrayMap<>();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800209
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800210 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800211 mTetherMasterSM.start();
212
Erik Klinef4b6e342017-04-25 19:19:59 +0900213 final Handler smHandler = mTetherMasterSM.getHandler();
214 mOffloadController = new OffloadController(smHandler,
215 deps.getOffloadHardwareInterface(smHandler, mLog),
Erik Kline92c4db02017-05-31 10:21:32 +0900216 mContext.getContentResolver(),
Erik Klinef4b6e342017-04-25 19:19:59 +0900217 mLog);
Erik Klineebdb8c82017-01-10 17:37:54 +0900218 mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
Erik Kline3a5278f2017-06-24 19:29:10 +0900219 mContext, mTetherMasterSM, mLog, TetherMasterSM.EVENT_UPSTREAM_CALLBACK );
Erik Klineea9cc482017-03-10 19:35:34 +0900220 mForwardedDownstreams = new HashSet<>();
Erik Kline227648f2017-01-20 20:26:10 +0900221 mSimChange = new SimChangeListener(
222 mContext, mTetherMasterSM.getHandler(), () -> reevaluateSimCardProvisioning());
Erik Kline6ff17f72015-12-10 20:42:12 +0900223
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800224 mStateReceiver = new StateReceiver();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800225 IntentFilter filter = new IntentFilter();
Mike Lockwood770126a2010-12-09 22:30:37 -0800226 filter.addAction(UsbManager.ACTION_USB_STATE);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800227 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700228 filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700229 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
Erik Kline2e88b5e2017-01-18 11:57:45 +0900230 mContext.registerReceiver(mStateReceiver, filter, null, mTetherMasterSM.getHandler());
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800231
232 filter = new IntentFilter();
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800233 filter.addAction(Intent.ACTION_MEDIA_SHARED);
234 filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800235 filter.addDataScheme("file");
Erik Kline2e88b5e2017-01-18 11:57:45 +0900236 mContext.registerReceiver(mStateReceiver, filter, null, mTetherMasterSM.getHandler());
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800237
Robert Greenwalt49348e72011-10-21 16:54:26 -0700238 // load device config info
239 updateConfiguration();
Robert Greenwalt49348e72011-10-21 16:54:26 -0700240 }
241
Sreeram Ramachandran62a61312014-07-24 16:05:17 -0700242 // We can't do this once in the Tethering() constructor and cache the value, because the
243 // CONNECTIVITY_SERVICE is registered only after the Tethering() constructor has completed.
244 private ConnectivityManager getConnectivityManager() {
245 return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
246 }
247
Erik Kline216af6d2017-04-27 20:57:23 +0900248 private WifiManager getWifiManager() {
249 return (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
250 }
251
Erik Kline93c4afa2017-06-04 11:36:01 +0900252 // NOTE: This is always invoked on the mLooper thread.
Erik Klined781fba2017-01-23 13:01:58 +0900253 private void updateConfiguration() {
Erik Kline6bd74532017-05-19 10:10:41 +0900254 mConfig = new TetheringConfiguration(mContext, mLog);
Erik Kline93c4afa2017-06-04 11:36:01 +0900255 mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800256 }
257
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900258 @Override
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700259 public void interfaceStatusChanged(String iface, boolean up) {
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900260 // Never called directly: only called from interfaceLinkStateChanged.
261 // See NetlinkHandler.cpp:71.
Wink Savillec9acde92011-09-21 11:05:43 -0700262 if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700263 synchronized (mPublicSync) {
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700264 if (up) {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900265 maybeTrackNewInterfaceLocked(iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800266 } else {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900267 if (ifaceNameToType(iface) == ConnectivityManager.TETHERING_BLUETOOTH) {
268 stopTrackingInterfaceLocked(iface);
Christopher Wileyd30aaeb2016-07-08 09:33:50 -0700269 } else {
270 // Ignore usb0 down after enabling RNDIS.
271 // We will handle disconnect in interfaceRemoved.
272 // Similarly, ignore interface down for WiFi. We monitor WiFi AP status
273 // through the WifiManager.WIFI_AP_STATE_CHANGED_ACTION intent.
274 if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800275 }
276 }
277 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800278 }
279
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900280 @Override
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700281 public void interfaceLinkStateChanged(String iface, boolean up) {
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700282 interfaceStatusChanged(iface, up);
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700283 }
284
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700285 private int ifaceNameToType(String iface) {
Erik Kline3e756652017-01-17 13:42:19 +0900286 final TetheringConfiguration cfg = mConfig;
287
288 if (cfg.isWifi(iface)) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700289 return ConnectivityManager.TETHERING_WIFI;
Erik Kline3e756652017-01-17 13:42:19 +0900290 } else if (cfg.isUsb(iface)) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700291 return ConnectivityManager.TETHERING_USB;
Erik Kline3e756652017-01-17 13:42:19 +0900292 } else if (cfg.isBluetooth(iface)) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700293 return ConnectivityManager.TETHERING_BLUETOOTH;
294 }
295 return ConnectivityManager.TETHERING_INVALID;
296 }
297
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900298 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800299 public void interfaceAdded(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700300 if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700301 synchronized (mPublicSync) {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900302 maybeTrackNewInterfaceLocked(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800303 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800304 }
305
Erik Kline0c9cb2b2015-11-20 17:47:08 +0900306 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800307 public void interfaceRemoved(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700308 if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700309 synchronized (mPublicSync) {
Erik Kline4dd9bb82017-04-26 11:11:07 +0900310 stopTrackingInterfaceLocked(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800311 }
312 }
313
Hugo Benichib55fb222017-03-10 14:20:57 +0900314 public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800315 if (!isTetherProvisioningRequired()) {
316 enableTetheringInternal(type, true, receiver);
317 return;
318 }
319
320 if (showProvisioningUi) {
321 runUiTetherProvisioningAndEnable(type, receiver);
322 } else {
323 runSilentTetherProvisioningAndEnable(type, receiver);
324 }
325 }
326
327 public void stopTethering(int type) {
328 enableTetheringInternal(type, false, null);
329 if (isTetherProvisioningRequired()) {
330 cancelTetherProvisioningRechecks(type);
331 }
332 }
333
334 /**
335 * Check if the device requires a provisioning check in order to enable tethering.
336 *
337 * @return a boolean - {@code true} indicating tether provisioning is required by the carrier.
338 */
Christopher Wiley497c1472016-10-11 13:26:03 -0700339 @VisibleForTesting
340 protected boolean isTetherProvisioningRequired() {
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800341 String[] provisionApp = mContext.getResources().getStringArray(
342 com.android.internal.R.array.config_mobile_hotspot_provision_app);
Christopher Wiley497c1472016-10-11 13:26:03 -0700343 if (mSystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false)
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800344 || provisionApp == null) {
345 return false;
346 }
347
348 // Check carrier config for entitlement checks
349 final CarrierConfigManager configManager = (CarrierConfigManager) mContext
350 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
Rebecca Silbersteinb07f1402016-10-04 13:53:33 -0700351 if (configManager != null && configManager.getConfig() != null) {
352 // we do have a CarrierConfigManager and it has a config.
353 boolean isEntitlementCheckRequired = configManager.getConfig().getBoolean(
354 CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
355 if (!isEntitlementCheckRequired) {
356 return false;
357 }
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800358 }
359 return (provisionApp.length == 2);
360 }
361
Erik Kline227648f2017-01-20 20:26:10 +0900362 // Used by the SIM card change observation code.
363 // TODO: De-duplicate above code.
364 private boolean hasMobileHotspotProvisionApp() {
365 try {
366 if (!mContext.getResources().getString(com.android.internal.R.string.
367 config_mobile_hotspot_provision_app_no_ui).isEmpty()) {
368 Log.d(TAG, "re-evaluate provisioning");
369 return true;
370 }
371 } catch (Resources.NotFoundException e) {}
372 Log.d(TAG, "no prov-check needed for new SIM");
373 return false;
374 }
375
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800376 /**
377 * Enables or disables tethering for the given type. This should only be called once
378 * provisioning has succeeded or is not necessary. It will also schedule provisioning rechecks
379 * for the specified interface.
380 */
381 private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700382 boolean isProvisioningRequired = enable && isTetherProvisioningRequired();
383 int result;
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800384 switch (type) {
385 case ConnectivityManager.TETHERING_WIFI:
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700386 result = setWifiTethering(enable);
387 if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
388 scheduleProvisioningRechecks(type);
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800389 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700390 sendTetherResult(receiver, result);
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800391 break;
392 case ConnectivityManager.TETHERING_USB:
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700393 result = setUsbTethering(enable);
394 if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800395 scheduleProvisioningRechecks(type);
396 }
397 sendTetherResult(receiver, result);
398 break;
399 case ConnectivityManager.TETHERING_BLUETOOTH:
400 setBluetoothTethering(enable, receiver);
401 break;
402 default:
403 Log.w(TAG, "Invalid tether type.");
404 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE);
405 }
406 }
407
408 private void sendTetherResult(ResultReceiver receiver, int result) {
409 if (receiver != null) {
410 receiver.send(result, null);
411 }
412 }
413
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700414 private int setWifiTethering(final boolean enable) {
Erik Kline256be782017-04-29 13:20:04 +0900415 int rval = ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
416 final long ident = Binder.clearCallingIdentity();
417 try {
418 synchronized (mPublicSync) {
419 mWifiTetherRequested = enable;
420 final WifiManager mgr = getWifiManager();
421 if ((enable && mgr.startSoftAp(null /* use existing wifi config */)) ||
422 (!enable && mgr.stopSoftAp())) {
423 rval = ConnectivityManager.TETHER_ERROR_NO_ERROR;
424 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700425 }
Erik Kline256be782017-04-29 13:20:04 +0900426 } finally {
427 Binder.restoreCallingIdentity(ident);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700428 }
Erik Kline256be782017-04-29 13:20:04 +0900429 return rval;
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700430 }
431
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800432 private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) {
433 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
434 if (adapter == null || !adapter.isEnabled()) {
435 Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: " +
436 (adapter == null));
437 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL);
438 return;
439 }
440
441 adapter.getProfileProxy(mContext, new ServiceListener() {
442 @Override
443 public void onServiceDisconnected(int profile) { }
444
445 @Override
446 public void onServiceConnected(int profile, BluetoothProfile proxy) {
447 ((BluetoothPan) proxy).setBluetoothTethering(enable);
448 // TODO: Enabling bluetooth tethering can fail asynchronously here.
449 // We should figure out a way to bubble up that failure instead of sending success.
Jeremy Klein45ae04a2016-02-05 10:37:32 -0800450 int result = ((BluetoothPan) proxy).isTetheringOn() == enable ?
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800451 ConnectivityManager.TETHER_ERROR_NO_ERROR :
452 ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
453 sendTetherResult(receiver, result);
454 if (enable && isTetherProvisioningRequired()) {
455 scheduleProvisioningRechecks(ConnectivityManager.TETHERING_BLUETOOTH);
456 }
457 adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
458 }
459 }, BluetoothProfile.PAN);
460 }
461
462 private void runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
Jeremy Klein15f3d212016-01-24 17:01:09 -0800463 ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
464 sendUiTetherProvisionIntent(type, proxyReceiver);
465 }
466
467 private void sendUiTetherProvisionIntent(int type, ResultReceiver receiver) {
468 Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
469 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
470 intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver);
471 final long ident = Binder.clearCallingIdentity();
472 try {
473 mContext.startActivityAsUser(intent, UserHandle.CURRENT);
474 } finally {
475 Binder.restoreCallingIdentity(ident);
476 }
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800477 }
478
479 /**
Erik Klinefdd41112017-01-12 17:02:51 +0900480 * Creates a proxy {@link ResultReceiver} which enables tethering if the provisioning result
481 * is successful before firing back up to the wrapped receiver.
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800482 *
483 * @param type The type of tethering being enabled.
484 * @param receiver A ResultReceiver which will be called back with an int resultCode.
485 * @return The proxy receiver.
486 */
487 private ResultReceiver getProxyReceiver(final int type, final ResultReceiver receiver) {
488 ResultReceiver rr = new ResultReceiver(null) {
489 @Override
490 protected void onReceiveResult(int resultCode, Bundle resultData) {
491 // If provisioning is successful, enable tethering, otherwise just send the error.
492 if (resultCode == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
493 enableTetheringInternal(type, true, receiver);
494 } else {
495 sendTetherResult(receiver, resultCode);
496 }
497 }
498 };
499
500 // The following is necessary to avoid unmarshalling issues when sending the receiver
Erik Kline6ff17f72015-12-10 20:42:12 +0900501 // across processes.
Jeremy Klein36c7aa02016-01-22 14:11:45 -0800502 Parcel parcel = Parcel.obtain();
503 rr.writeToParcel(parcel,0);
504 parcel.setDataPosition(0);
505 ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel);
506 parcel.recycle();
507 return receiverForSending;
508 }
509
510 private void scheduleProvisioningRechecks(int type) {
511 Intent intent = new Intent();
512 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
513 intent.putExtra(ConnectivityManager.EXTRA_SET_ALARM, true);
514 intent.setComponent(TETHER_SERVICE);
515 final long ident = Binder.clearCallingIdentity();
516 try {
517 mContext.startServiceAsUser(intent, UserHandle.CURRENT);
518 } finally {
519 Binder.restoreCallingIdentity(ident);
520 }
521 }
522
523 private void runSilentTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
524 ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
525 sendSilentTetherProvisionIntent(type, proxyReceiver);
526 }
527
528 private void sendSilentTetherProvisionIntent(int type, ResultReceiver receiver) {
529 Intent intent = new Intent();
530 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
531 intent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
532 intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver);
533 intent.setComponent(TETHER_SERVICE);
534 final long ident = Binder.clearCallingIdentity();
535 try {
536 mContext.startServiceAsUser(intent, UserHandle.CURRENT);
537 } finally {
538 Binder.restoreCallingIdentity(ident);
539 }
540 }
541
542 private void cancelTetherProvisioningRechecks(int type) {
543 if (getConnectivityManager().isTetheringSupported()) {
544 Intent intent = new Intent();
545 intent.putExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE, type);
546 intent.setComponent(TETHER_SERVICE);
547 final long ident = Binder.clearCallingIdentity();
548 try {
549 mContext.startServiceAsUser(intent, UserHandle.CURRENT);
550 } finally {
551 Binder.restoreCallingIdentity(ident);
552 }
553 }
554 }
Erik Kline6ff17f72015-12-10 20:42:12 +0900555
Erik Kline227648f2017-01-20 20:26:10 +0900556 // Used by the SIM card change observation code.
557 // TODO: De-duplicate with above code, where possible.
558 private void startProvisionIntent(int tetherType) {
559 final Intent startProvIntent = new Intent();
560 startProvIntent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType);
561 startProvIntent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
562 startProvIntent.setComponent(TETHER_SERVICE);
563 mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT);
564 }
565
Robert Greenwalt5a735062010-03-02 17:25:02 -0800566 public int tether(String iface) {
Erik Klineea9cc482017-03-10 19:35:34 +0900567 return tether(iface, IControlsTethering.STATE_TETHERED);
568 }
569
570 private int tether(String iface, int requestedState) {
Wink Savillec9acde92011-09-21 11:05:43 -0700571 if (DBG) Log.d(TAG, "Tethering " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700572 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700573 TetherState tetherState = mTetherStates.get(iface);
574 if (tetherState == null) {
Erik Kline00019f42016-06-30 19:31:46 +0900575 Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring");
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700576 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
577 }
578 // Ignore the error status of the interface. If the interface is available,
579 // the errors are referring to past tethering attempts anyway.
Hugo Benichib55fb222017-03-10 14:20:57 +0900580 if (tetherState.lastState != IControlsTethering.STATE_AVAILABLE) {
Erik Kline00019f42016-06-30 19:31:46 +0900581 Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700582 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700583 }
Erik Klineea9cc482017-03-10 19:35:34 +0900584 // NOTE: If a CMD_TETHER_REQUESTED message is already in the TISM's
585 // queue but not yet processed, this will be a no-op and it will not
586 // return an error.
587 //
588 // TODO: reexamine the threading and messaging model.
589 tetherState.stateMachine.sendMessage(
590 TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, requestedState);
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700591 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800592 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800593 }
594
Robert Greenwalt5a735062010-03-02 17:25:02 -0800595 public int untether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700596 if (DBG) Log.d(TAG, "Untethering " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700597 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700598 TetherState tetherState = mTetherStates.get(iface);
599 if (tetherState == null) {
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700600 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
601 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
602 }
Erik Klineea9cc482017-03-10 19:35:34 +0900603 if (!tetherState.isCurrentlyServing()) {
604 Log.e(TAG, "Tried to untether an inactive iface :" + iface + ", ignoring");
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700605 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
606 }
Hugo Benichib55fb222017-03-10 14:20:57 +0900607 tetherState.stateMachine.sendMessage(
Christopher Wileyd985dde2016-05-31 10:44:35 -0700608 TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
Christopher Wiley4312a4c2016-05-23 13:58:00 -0700609 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800610 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800611 }
612
Felipe Leme70c8b9b2016-04-25 14:41:31 -0700613 public void untetherAll() {
Christopher Wileyfa6a4862016-09-19 08:58:06 -0700614 stopTethering(ConnectivityManager.TETHERING_WIFI);
615 stopTethering(ConnectivityManager.TETHERING_USB);
616 stopTethering(ConnectivityManager.TETHERING_BLUETOOTH);
Felipe Leme70c8b9b2016-04-25 14:41:31 -0700617 }
618
Robert Greenwalt5a735062010-03-02 17:25:02 -0800619 public int getLastTetherError(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700620 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700621 TetherState tetherState = mTetherStates.get(iface);
622 if (tetherState == null) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700623 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
624 ", ignoring");
625 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
626 }
Hugo Benichib55fb222017-03-10 14:20:57 +0900627 return tetherState.lastError;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800628 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800629 }
630
Erik Klineea9cc482017-03-10 19:35:34 +0900631 // TODO: Figure out how to update for local hotspot mode interfaces.
Christopher Wileyd985dde2016-05-31 10:44:35 -0700632 private void sendTetherStateChangedBroadcast() {
Sreeram Ramachandran62a61312014-07-24 16:05:17 -0700633 if (!getConnectivityManager().isTetheringSupported()) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800634
Erik Kline8351faa2017-04-17 16:47:23 +0900635 final ArrayList<String> availableList = new ArrayList<>();
636 final ArrayList<String> tetherList = new ArrayList<>();
637 final ArrayList<String> localOnlyList = new ArrayList<>();
638 final ArrayList<String> erroredList = new ArrayList<>();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800639
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800640 boolean wifiTethered = false;
641 boolean usbTethered = false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700642 boolean bluetoothTethered = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800643
Erik Kline3e756652017-01-17 13:42:19 +0900644 final TetheringConfiguration cfg = mConfig;
645
Robert Greenwaltb4453622011-11-03 16:01:40 -0700646 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700647 for (int i = 0; i < mTetherStates.size(); i++) {
648 TetherState tetherState = mTetherStates.valueAt(i);
649 String iface = mTetherStates.keyAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +0900650 if (tetherState.lastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700651 erroredList.add(iface);
Hugo Benichib55fb222017-03-10 14:20:57 +0900652 } else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700653 availableList.add(iface);
Erik Klineca41be72017-04-20 22:59:16 +0900654 } else if (tetherState.lastState == IControlsTethering.STATE_LOCAL_ONLY) {
Erik Kline8351faa2017-04-17 16:47:23 +0900655 localOnlyList.add(iface);
Hugo Benichib55fb222017-03-10 14:20:57 +0900656 } else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
Erik Kline3e756652017-01-17 13:42:19 +0900657 if (cfg.isUsb(iface)) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700658 usbTethered = true;
Erik Kline3e756652017-01-17 13:42:19 +0900659 } else if (cfg.isWifi(iface)) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700660 wifiTethered = true;
Erik Kline3e756652017-01-17 13:42:19 +0900661 } else if (cfg.isBluetooth(iface)) {
Christopher Wileyd985dde2016-05-31 10:44:35 -0700662 bluetoothTethered = true;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800663 }
Erik Kline8351faa2017-04-17 16:47:23 +0900664 tetherList.add(iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800665 }
666 }
667 }
Erik Kline8351faa2017-04-17 16:47:23 +0900668 final Intent bcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
669 bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
Robert Greenwalt98c79e52011-07-28 11:51:11 -0700670 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Erik Kline8351faa2017-04-17 16:47:23 +0900671 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, availableList);
672 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList);
673 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, tetherList);
674 bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, erroredList);
675 mContext.sendStickyBroadcastAsUser(bcast, UserHandle.ALL);
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800676 if (DBG) {
Lorenzo Colitticd63d242016-04-10 15:39:53 +0900677 Log.d(TAG, String.format(
Erik Kline8351faa2017-04-17 16:47:23 +0900678 "sendTetherStateChangedBroadcast %s=[%s] %s=[%s] %s=[%s] %s=[%s]",
679 "avail", TextUtils.join(",", availableList),
680 "local_only", TextUtils.join(",", localOnlyList),
681 "tether", TextUtils.join(",", tetherList),
682 "error", TextUtils.join(",", erroredList)));
Robert Greenwalt924cc942010-06-28 10:26:19 -0700683 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800684
685 if (usbTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700686 if (wifiTethered || bluetoothTethered) {
Chris Wren282cfef2017-03-27 15:01:44 -0400687 showTetheredNotification(SystemMessage.NOTE_TETHER_GENERAL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800688 } else {
Chris Wren282cfef2017-03-27 15:01:44 -0400689 showTetheredNotification(SystemMessage.NOTE_TETHER_USB);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800690 }
691 } else if (wifiTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700692 if (bluetoothTethered) {
Chris Wren282cfef2017-03-27 15:01:44 -0400693 showTetheredNotification(SystemMessage.NOTE_TETHER_GENERAL);
Danica Chang6fdd0c62010-08-11 14:54:43 -0700694 } else {
Vinit Deshpande2576a802014-11-18 13:56:15 -0800695 /* We now have a status bar icon for WifiTethering, so drop the notification */
696 clearTetheredNotification();
Danica Chang6fdd0c62010-08-11 14:54:43 -0700697 }
698 } else if (bluetoothTethered) {
Chris Wren282cfef2017-03-27 15:01:44 -0400699 showTetheredNotification(SystemMessage.NOTE_TETHER_BLUETOOTH);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800700 } else {
701 clearTetheredNotification();
702 }
703 }
704
Chris Wren282cfef2017-03-27 15:01:44 -0400705 private void showTetheredNotification(int id) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800706 NotificationManager notificationManager =
Erik Klinec438e302017-07-04 22:02:49 +0900707 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800708 if (notificationManager == null) {
709 return;
710 }
Chris Wren282cfef2017-03-27 15:01:44 -0400711 int icon = 0;
712 switch(id) {
713 case SystemMessage.NOTE_TETHER_USB:
714 icon = com.android.internal.R.drawable.stat_sys_tether_usb;
715 break;
716 case SystemMessage.NOTE_TETHER_BLUETOOTH:
717 icon = com.android.internal.R.drawable.stat_sys_tether_bluetooth;
718 break;
719 case SystemMessage.NOTE_TETHER_GENERAL:
720 default:
721 icon = com.android.internal.R.drawable.stat_sys_tether_general;
722 break;
723 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800724
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400725 if (mLastNotificationId != 0) {
726 if (mLastNotificationId == icon) {
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700727 return;
728 }
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400729 notificationManager.cancelAsUser(null, mLastNotificationId,
Robert Greenwalt3cab6b02012-10-04 16:44:26 -0700730 UserHandle.ALL);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400731 mLastNotificationId = 0;
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700732 }
733
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800734 Intent intent = new Intent();
735 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
736 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
737
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700738 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
739 null, UserHandle.CURRENT);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800740
741 Resources r = Resources.getSystem();
742 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
743 CharSequence message = r.getText(com.android.internal.R.string.
744 tethered_notification_message);
745
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400746 if (mTetheredNotificationBuilder == null) {
Geoffrey Pitschaf759c52017-02-15 09:35:38 -0500747 mTetheredNotificationBuilder =
748 new Notification.Builder(mContext, SystemNotificationChannels.NETWORK_STATUS);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400749 mTetheredNotificationBuilder.setWhen(0)
750 .setOngoing(true)
751 .setColor(mContext.getColor(
752 com.android.internal.R.color.system_notification_accent_color))
753 .setVisibility(Notification.VISIBILITY_PUBLIC)
754 .setCategory(Notification.CATEGORY_STATUS);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800755 }
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400756 mTetheredNotificationBuilder.setSmallIcon(icon)
757 .setContentTitle(title)
758 .setContentText(message)
759 .setContentIntent(pi);
Chris Wren282cfef2017-03-27 15:01:44 -0400760 mLastNotificationId = id;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800761
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400762 notificationManager.notifyAsUser(null, mLastNotificationId,
zhouzhijie130d4592017-05-18 10:02:59 +0800763 mTetheredNotificationBuilder.buildInto(new Notification()), UserHandle.ALL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800764 }
765
766 private void clearTetheredNotification() {
767 NotificationManager notificationManager =
Erik Klinec438e302017-07-04 22:02:49 +0900768 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400769 if (notificationManager != null && mLastNotificationId != 0) {
770 notificationManager.cancelAsUser(null, mLastNotificationId,
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700771 UserHandle.ALL);
Chris Wren1ce4b6d2015-06-11 10:19:43 -0400772 mLastNotificationId = 0;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800773 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800774 }
775
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800776 private class StateReceiver extends BroadcastReceiver {
Nick Kralevich70c117a2014-05-27 15:30:02 -0700777 @Override
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800778 public void onReceive(Context content, Intent intent) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900779 final String action = intent.getAction();
780 if (action == null) return;
781
Mike Lockwood770126a2010-12-09 22:30:37 -0800782 if (action.equals(UsbManager.ACTION_USB_STATE)) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900783 handleUsbAction(intent);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800784 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900785 handleConnectivityAction(intent);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700786 } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
Erik Kline2e88b5e2017-01-18 11:57:45 +0900787 handleWifiApAction(intent);
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700788 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
789 updateConfiguration();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800790 }
791 }
Erik Kline2e88b5e2017-01-18 11:57:45 +0900792
793 private void handleConnectivityAction(Intent intent) {
794 final NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
795 ConnectivityManager.EXTRA_NETWORK_INFO);
796 if (networkInfo == null ||
797 networkInfo.getDetailedState() == NetworkInfo.DetailedState.FAILED) {
798 return;
799 }
800
801 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION: " + networkInfo.toString());
802 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
803 }
804
805 private void handleUsbAction(Intent intent) {
806 final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false);
Erik Klinec438e302017-07-04 22:02:49 +0900807 final boolean usbConfigured = intent.getBooleanExtra(USB_CONFIGURED, false);
Erik Kline2e88b5e2017-01-18 11:57:45 +0900808 final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false);
Erik Klinec438e302017-07-04 22:02:49 +0900809
810 mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s",
811 usbConnected, usbConfigured, rndisEnabled));
812
813 // There are three types of ACTION_USB_STATE:
814 //
815 // - DISCONNECTED (USB_CONNECTED and USB_CONFIGURED are 0)
816 // Meaning: USB connection has ended either because of
817 // software reset or hard unplug.
818 //
819 // - CONNECTED (USB_CONNECTED is 1, USB_CONFIGURED is 0)
820 // Meaning: the first stage of USB protocol handshake has
821 // occurred but it is not complete.
822 //
823 // - CONFIGURED (USB_CONNECTED and USB_CONFIGURED are 1)
824 // Meaning: the USB handshake is completely done and all the
825 // functions are ready to use.
826 //
827 // For more explanation, see b/62552150 .
828 if (usbConnected && !usbConfigured) {
829 // Nothing for us to do here.
830 // TODO: consider ignoring DISCONNECTED broadcasts as well.
831 return;
832 }
833
Erik Kline2e88b5e2017-01-18 11:57:45 +0900834 synchronized (Tethering.this.mPublicSync) {
835 mRndisEnabled = rndisEnabled;
836 // start tethering if we have a request pending
Erik Klinec438e302017-07-04 22:02:49 +0900837 if (usbConfigured && mRndisEnabled && mUsbTetherRequested) {
Erik Klineea9cc482017-03-10 19:35:34 +0900838 tetherMatchingInterfaces(
839 IControlsTethering.STATE_TETHERED,
840 ConnectivityManager.TETHERING_USB);
Erik Kline2e88b5e2017-01-18 11:57:45 +0900841 }
842 mUsbTetherRequested = false;
843 }
844 }
845
846 private void handleWifiApAction(Intent intent) {
Erik Kline2efb8272017-05-31 15:53:53 +0900847 final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
848 final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
849 final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED);
850
Erik Kline2e88b5e2017-01-18 11:57:45 +0900851 synchronized (Tethering.this.mPublicSync) {
852 switch (curState) {
853 case WifiManager.WIFI_AP_STATE_ENABLING:
854 // We can see this state on the way to both enabled and failure states.
855 break;
856 case WifiManager.WIFI_AP_STATE_ENABLED:
Erik Kline2efb8272017-05-31 15:53:53 +0900857 enableWifiIpServingLocked(ifname, ipmode);
Erik Kline2e88b5e2017-01-18 11:57:45 +0900858 break;
859 case WifiManager.WIFI_AP_STATE_DISABLED:
860 case WifiManager.WIFI_AP_STATE_DISABLING:
861 case WifiManager.WIFI_AP_STATE_FAILED:
862 default:
Erik Kline562e0c12017-06-09 16:36:29 +0900863 disableWifiIpServingLocked(ifname, curState);
Erik Kline2efb8272017-05-31 15:53:53 +0900864 break;
Erik Kline2e88b5e2017-01-18 11:57:45 +0900865 }
866 }
867 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800868 }
869
Erik Kline562e0c12017-06-09 16:36:29 +0900870 private void disableWifiIpServingLocked(String ifname, int apState) {
871 mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState);
Erik Kline2efb8272017-05-31 15:53:53 +0900872
Erik Kline562e0c12017-06-09 16:36:29 +0900873 // Regardless of whether we requested this transition, the AP has gone
874 // down. Don't try to tether again unless we're requested to do so.
875 // TODO: Remove this altogether, once Wi-Fi reliably gives us an
876 // interface name with every broadcast.
877 mWifiTetherRequested = false;
878
879 if (!TextUtils.isEmpty(ifname)) {
880 final TetherState ts = mTetherStates.get(ifname);
881 if (ts != null) {
882 ts.stateMachine.unwanted();
883 return;
884 }
885 }
886
Erik Kline2efb8272017-05-31 15:53:53 +0900887 for (int i = 0; i < mTetherStates.size(); i++) {
888 TetherInterfaceStateMachine tism = mTetherStates.valueAt(i).stateMachine;
889 if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
Erik Kline562e0c12017-06-09 16:36:29 +0900890 tism.unwanted();
891 return;
Erik Kline2efb8272017-05-31 15:53:53 +0900892 }
893 }
Erik Kline562e0c12017-06-09 16:36:29 +0900894
895 mLog.log("Error disabling Wi-Fi IP serving; " +
896 (TextUtils.isEmpty(ifname) ? "no interface name specified"
897 : "specified interface: " + ifname));
Erik Kline2efb8272017-05-31 15:53:53 +0900898 }
899
900 private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
901 // Map wifiIpMode values to IControlsTethering serving states, inferring
902 // from mWifiTetherRequested as a final "best guess".
903 final int ipServingMode;
904 switch (wifiIpMode) {
905 case IFACE_IP_MODE_TETHERED:
906 ipServingMode = IControlsTethering.STATE_TETHERED;
907 break;
908 case IFACE_IP_MODE_LOCAL_ONLY:
909 ipServingMode = IControlsTethering.STATE_LOCAL_ONLY;
910 break;
911 default:
Erik Kline9e225542017-06-08 17:48:48 +0900912 mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode);
913 return;
Erik Kline2efb8272017-05-31 15:53:53 +0900914 }
915
916 if (!TextUtils.isEmpty(ifname)) {
Erik Klinea9cde8b2017-06-20 21:18:31 +0900917 maybeTrackNewInterfaceLocked(ifname, ConnectivityManager.TETHERING_WIFI);
Erik Kline2efb8272017-05-31 15:53:53 +0900918 changeInterfaceState(ifname, ipServingMode);
919 } else {
Erik Kline9e225542017-06-08 17:48:48 +0900920 mLog.e(String.format(
921 "Cannot enable IP serving in mode %s on missing interface name",
922 ipServingMode));
Erik Kline2efb8272017-05-31 15:53:53 +0900923 }
924 }
925
Erik Klineea9cc482017-03-10 19:35:34 +0900926 // TODO: Consider renaming to something more accurate in its description.
927 // This method:
928 // - allows requesting either tethering or local hotspot serving states
929 // - handles both enabling and disabling serving states
930 // - only tethers the first matching interface in listInterfaces()
931 // order of a given type
932 private void tetherMatchingInterfaces(int requestedState, int interfaceType) {
933 if (VDBG) {
934 Log.d(TAG, "tetherMatchingInterfaces(" + requestedState + ", " + interfaceType + ")");
935 }
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700936
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700937 String[] ifaces = null;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800938 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700939 ifaces = mNMService.listInterfaces();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800940 } catch (Exception e) {
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700941 Log.e(TAG, "Error listing Interfaces", e);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800942 return;
943 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700944 String chosenIface = null;
945 if (ifaces != null) {
946 for (String iface : ifaces) {
947 if (ifaceNameToType(iface) == interfaceType) {
948 chosenIface = iface;
949 break;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800950 }
951 }
952 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700953 if (chosenIface == null) {
954 Log.e(TAG, "could not find iface of type " + interfaceType);
955 return;
956 }
957
Erik Kline2efb8272017-05-31 15:53:53 +0900958 changeInterfaceState(chosenIface, requestedState);
959 }
960
961 private void changeInterfaceState(String ifname, int requestedState) {
Erik Klineea9cc482017-03-10 19:35:34 +0900962 final int result;
963 switch (requestedState) {
964 case IControlsTethering.STATE_UNAVAILABLE:
965 case IControlsTethering.STATE_AVAILABLE:
Erik Kline2efb8272017-05-31 15:53:53 +0900966 result = untether(ifname);
Erik Klineea9cc482017-03-10 19:35:34 +0900967 break;
968 case IControlsTethering.STATE_TETHERED:
Erik Klineca41be72017-04-20 22:59:16 +0900969 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Kline2efb8272017-05-31 15:53:53 +0900970 result = tether(ifname, requestedState);
Erik Klineea9cc482017-03-10 19:35:34 +0900971 break;
972 default:
973 Log.wtf(TAG, "Unknown interface state: " + requestedState);
974 return;
975 }
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700976 if (result != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Erik Kline2efb8272017-05-31 15:53:53 +0900977 Log.e(TAG, "unable start or stop tethering on iface " + ifname);
Christopher Wiley5c0b10a2016-05-31 14:43:08 -0700978 return;
979 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800980 }
981
Erik Kline3e756652017-01-17 13:42:19 +0900982 public TetheringConfiguration getTetheringConfiguration() {
983 return mConfig;
984 }
985
Erik Klined781fba2017-01-23 13:01:58 +0900986 public boolean hasTetherableConfiguration() {
987 final TetheringConfiguration cfg = mConfig;
988 final boolean hasDownstreamConfiguration =
989 (cfg.tetherableUsbRegexs.length != 0) ||
990 (cfg.tetherableWifiRegexs.length != 0) ||
991 (cfg.tetherableBluetoothRegexs.length != 0);
992 final boolean hasUpstreamConfiguration = !cfg.preferredUpstreamIfaceTypes.isEmpty();
993
994 return hasDownstreamConfiguration && hasUpstreamConfiguration;
995 }
996
Erik Kline3e756652017-01-17 13:42:19 +0900997 // TODO - update callers to use getTetheringConfiguration(),
998 // which has only final members.
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800999 public String[] getTetherableUsbRegexs() {
Erik Kline3e756652017-01-17 13:42:19 +09001000 return copy(mConfig.tetherableUsbRegexs);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001001 }
1002
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001003 public String[] getTetherableWifiRegexs() {
Erik Kline3e756652017-01-17 13:42:19 +09001004 return copy(mConfig.tetherableWifiRegexs);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001005 }
1006
Danica Chang6fdd0c62010-08-11 14:54:43 -07001007 public String[] getTetherableBluetoothRegexs() {
Erik Kline3e756652017-01-17 13:42:19 +09001008 return copy(mConfig.tetherableBluetoothRegexs);
Danica Chang6fdd0c62010-08-11 14:54:43 -07001009 }
1010
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001011 public int setUsbTethering(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -07001012 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
Erik Klinec438e302017-07-04 22:02:49 +09001013 UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001014
Robert Greenwaltb4453622011-11-03 16:01:40 -07001015 synchronized (mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001016 if (enable) {
1017 if (mRndisEnabled) {
Jeremy Klein36c7aa02016-01-22 14:11:45 -08001018 final long ident = Binder.clearCallingIdentity();
1019 try {
Erik Klineea9cc482017-03-10 19:35:34 +09001020 tetherMatchingInterfaces(IControlsTethering.STATE_TETHERED,
1021 ConnectivityManager.TETHERING_USB);
Jeremy Klein36c7aa02016-01-22 14:11:45 -08001022 } finally {
1023 Binder.restoreCallingIdentity(ident);
1024 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001025 } else {
1026 mUsbTetherRequested = true;
Jerry Zhang935372b2016-10-12 15:49:32 -07001027 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001028 }
1029 } else {
Jeremy Klein36c7aa02016-01-22 14:11:45 -08001030 final long ident = Binder.clearCallingIdentity();
1031 try {
Erik Klineea9cc482017-03-10 19:35:34 +09001032 tetherMatchingInterfaces(IControlsTethering.STATE_AVAILABLE,
1033 ConnectivityManager.TETHERING_USB);
Jeremy Klein36c7aa02016-01-22 14:11:45 -08001034 } finally {
1035 Binder.restoreCallingIdentity(ident);
1036 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001037 if (mRndisEnabled) {
Jerry Zhang935372b2016-10-12 15:49:32 -07001038 usbManager.setCurrentFunction(null, false);
Mike Lockwood6c2260b2011-07-19 13:04:47 -07001039 }
1040 mUsbTetherRequested = false;
1041 }
1042 }
1043 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
1044 }
1045
Erik Kline1fdc2e22017-05-08 17:56:35 +09001046 // TODO review API - figure out how to delete these entirely.
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001047 public String[] getTetheredIfaces() {
1048 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -07001049 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001050 for (int i = 0; i < mTetherStates.size(); i++) {
1051 TetherState tetherState = mTetherStates.valueAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +09001052 if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001053 list.add(mTetherStates.keyAt(i));
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001054 }
1055 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001056 }
Christopher Wileyd985dde2016-05-31 10:44:35 -07001057 return list.toArray(new String[list.size()]);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001058 }
1059
1060 public String[] getTetherableIfaces() {
1061 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -07001062 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001063 for (int i = 0; i < mTetherStates.size(); i++) {
1064 TetherState tetherState = mTetherStates.valueAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +09001065 if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001066 list.add(mTetherStates.keyAt(i));
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001067 }
1068 }
1069 }
Christopher Wileyd985dde2016-05-31 10:44:35 -07001070 return list.toArray(new String[list.size()]);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001071 }
1072
Robert Greenwalt9c7e2c22014-06-23 14:53:42 -07001073 public String[] getTetheredDhcpRanges() {
Erik Kline3e756652017-01-17 13:42:19 +09001074 return mConfig.dhcpRanges;
Robert Greenwalt9c7e2c22014-06-23 14:53:42 -07001075 }
1076
Robert Greenwalt5a735062010-03-02 17:25:02 -08001077 public String[] getErroredIfaces() {
1078 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -07001079 synchronized (mPublicSync) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001080 for (int i = 0; i < mTetherStates.size(); i++) {
1081 TetherState tetherState = mTetherStates.valueAt(i);
Hugo Benichib55fb222017-03-10 14:20:57 +09001082 if (tetherState.lastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001083 list.add(mTetherStates.keyAt(i));
Robert Greenwalt5a735062010-03-02 17:25:02 -08001084 }
1085 }
1086 }
Christopher Wileyd985dde2016-05-31 10:44:35 -07001087 return list.toArray(new String[list.size()]);
Robert Greenwalt5a735062010-03-02 17:25:02 -08001088 }
1089
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001090 private void maybeLogMessage(State state, int what) {
1091 if (DBG) {
1092 Log.d(TAG, state.getName() + " got " +
1093 sMagicDecoderRing.get(what, Integer.toString(what)));
1094 }
1095 }
1096
Erik Klineea9cc482017-03-10 19:35:34 +09001097 private boolean upstreamWanted() {
1098 if (!mForwardedDownstreams.isEmpty()) return true;
1099
1100 synchronized (mPublicSync) {
1101 return mUsbTetherRequested || mWifiTetherRequested;
1102 }
1103 }
1104
Erik Kline00019f42016-06-30 19:31:46 +09001105 // Needed because the canonical source of upstream truth is just the
1106 // upstream interface name, |mCurrentUpstreamIface|. This is ripe for
1107 // future simplification, once the upstream Network is canonical.
Erik Kline3a5278f2017-06-24 19:29:10 +09001108 private boolean pertainsToCurrentUpstream(NetworkState ns) {
Erik Kline00019f42016-06-30 19:31:46 +09001109 if (ns != null && ns.linkProperties != null && mCurrentUpstreamIface != null) {
1110 for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
1111 if (mCurrentUpstreamIface.equals(ifname)) {
1112 return true;
Erik Kline6ff17f72015-12-10 20:42:12 +09001113 }
1114 }
Erik Kline6ff17f72015-12-10 20:42:12 +09001115 }
Erik Kline00019f42016-06-30 19:31:46 +09001116 return false;
Erik Kline6ff17f72015-12-10 20:42:12 +09001117 }
1118
Erik Kline227648f2017-01-20 20:26:10 +09001119 private void reevaluateSimCardProvisioning() {
1120 if (!hasMobileHotspotProvisionApp()) return;
1121
1122 ArrayList<Integer> tethered = new ArrayList<>();
1123 synchronized (mPublicSync) {
1124 for (int i = 0; i < mTetherStates.size(); i++) {
1125 TetherState tetherState = mTetherStates.valueAt(i);
1126 if (tetherState.lastState != IControlsTethering.STATE_TETHERED) {
1127 continue; // Skip interfaces that aren't tethered.
1128 }
1129 String iface = mTetherStates.keyAt(i);
1130 int interfaceType = ifaceNameToType(iface);
1131 if (interfaceType != ConnectivityManager.TETHERING_INVALID) {
1132 tethered.add(interfaceType);
1133 }
1134 }
1135 }
1136
1137 for (int tetherType : tethered) {
1138 startProvisionIntent(tetherType);
1139 }
1140 }
1141
Erik Kline3a5278f2017-06-24 19:29:10 +09001142 private void startOffloadController() {
1143 mOffloadController.start();
1144 mOffloadController.updateExemptPrefixes(
1145 mUpstreamNetworkMonitor.getOffloadExemptPrefixes());
1146 }
1147
Wink Saville64c42ca2011-04-18 14:55:10 -07001148 class TetherMasterSM extends StateMachine {
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001149 private static final int BASE_MASTER = Protocol.BASE_TETHERING;
Erik Klineea9cc482017-03-10 19:35:34 +09001150 // an interface SM has requested Tethering/Local Hotspot
1151 static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MASTER + 1;
1152 // an interface SM has unrequested Tethering/Local Hotspot
1153 static final int EVENT_IFACE_SERVING_STATE_INACTIVE = BASE_MASTER + 2;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001154 // upstream connection change - do the right thing
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001155 static final int CMD_UPSTREAM_CHANGED = BASE_MASTER + 3;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001156 // we don't have a valid upstream conn, check again after a delay
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001157 static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4;
Erik Kline6ff17f72015-12-10 20:42:12 +09001158 // Events from NetworkCallbacks that we process on the master state
1159 // machine thread on behalf of the UpstreamNetworkMonitor.
Erik Kline00019f42016-06-30 19:31:46 +09001160 static final int EVENT_UPSTREAM_CALLBACK = BASE_MASTER + 5;
Yohei, Oshima977aad52016-12-08 13:39:20 +09001161 // we treated the error and want now to clear it
1162 static final int CMD_CLEAR_ERROR = BASE_MASTER + 6;
Erik Kline6e9a1012017-06-06 19:24:21 +09001163 static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MASTER + 7;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001164
Wink Saville64c42ca2011-04-18 14:55:10 -07001165 private State mInitialState;
1166 private State mTetherModeAliveState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001167
Wink Saville64c42ca2011-04-18 14:55:10 -07001168 private State mSetIpForwardingEnabledErrorState;
1169 private State mSetIpForwardingDisabledErrorState;
1170 private State mStartTetheringErrorState;
1171 private State mStopTetheringErrorState;
1172 private State mSetDnsForwardersErrorState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001173
Christopher Wileyd985dde2016-05-31 10:44:35 -07001174 // This list is a little subtle. It contains all the interfaces that currently are
1175 // requesting tethering, regardless of whether these interfaces are still members of
1176 // mTetherStates. This allows us to maintain the following predicates:
1177 //
1178 // 1) mTetherStates contains the set of all currently existing, tetherable, link state up
1179 // interfaces.
1180 // 2) mNotifyList contains all state machines that may have outstanding tethering state
1181 // that needs to be torn down.
1182 //
1183 // Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList
1184 // so that the garbage collector does not clean up the state machine before it has a chance
1185 // to tear itself down.
Erik Kline1eb8c692016-07-08 17:21:26 +09001186 private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
1187 private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001188
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001189 private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001190
Robert Greenwaltdfadaea2010-03-11 15:03:08 -08001191 TetherMasterSM(String name, Looper looper) {
1192 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001193
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001194 mInitialState = new InitialState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001195 mTetherModeAliveState = new TetherModeAliveState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001196 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001197 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001198 mStartTetheringErrorState = new StartTetheringErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001199 mStopTetheringErrorState = new StopTetheringErrorState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001200 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
Erik Kline1fdc2e22017-05-08 17:56:35 +09001201
1202 addState(mInitialState);
1203 addState(mTetherModeAliveState);
1204 addState(mSetIpForwardingEnabledErrorState);
1205 addState(mSetIpForwardingDisabledErrorState);
1206 addState(mStartTetheringErrorState);
1207 addState(mStopTetheringErrorState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001208 addState(mSetDnsForwardersErrorState);
1209
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001210 mNotifyList = new ArrayList<>();
Erik Kline7747fd42017-05-12 16:52:48 +09001211 mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList, mLog);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001212 setInitialState(mInitialState);
1213 }
1214
Erik Kline1fdc2e22017-05-08 17:56:35 +09001215 class InitialState extends State {
1216 @Override
1217 public boolean processMessage(Message message) {
1218 maybeLogMessage(this, message.what);
1219 switch (message.what) {
1220 case EVENT_IFACE_SERVING_STATE_ACTIVE:
1221 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
1222 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
1223 handleInterfaceServingStateActive(message.arg1, who);
1224 transitionTo(mTetherModeAliveState);
1225 break;
1226 case EVENT_IFACE_SERVING_STATE_INACTIVE:
1227 who = (TetherInterfaceStateMachine)message.obj;
1228 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
1229 handleInterfaceServingStateInactive(who);
1230 break;
Erik Kline6e9a1012017-06-06 19:24:21 +09001231 case EVENT_IFACE_UPDATE_LINKPROPERTIES:
1232 // Silently ignore these for now.
1233 break;
Erik Kline1fdc2e22017-05-08 17:56:35 +09001234 default:
1235 return NOT_HANDLED;
1236 }
1237 return HANDLED;
1238 }
1239 }
1240
Erik Kline3a5278f2017-06-24 19:29:10 +09001241 protected boolean turnOnMasterTetherSettings() {
1242 final TetheringConfiguration cfg = mConfig;
1243 try {
1244 mNMService.setIpForwardingEnabled(true);
1245 } catch (Exception e) {
1246 mLog.e(e);
1247 transitionTo(mSetIpForwardingEnabledErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001248 return false;
1249 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001250 // TODO: Randomize DHCPv4 ranges, especially in hotspot mode.
1251 try {
1252 // TODO: Find a more accurate method name (startDHCPv4()?).
1253 mNMService.startTethering(cfg.dhcpRanges);
1254 } catch (Exception e) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001255 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001256 mNMService.stopTethering();
Erik Kline3a5278f2017-06-24 19:29:10 +09001257 mNMService.startTethering(cfg.dhcpRanges);
1258 } catch (Exception ee) {
1259 mLog.e(ee);
1260 transitionTo(mStartTetheringErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001261 return false;
1262 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001263 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001264 mLog.log("SET master tether settings: ON");
1265 return true;
1266 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001267
Erik Kline3a5278f2017-06-24 19:29:10 +09001268 protected boolean turnOffMasterTetherSettings() {
1269 try {
1270 mNMService.stopTethering();
1271 } catch (Exception e) {
1272 mLog.e(e);
1273 transitionTo(mStopTetheringErrorState);
1274 return false;
Erik Kline14f7faf2017-02-14 19:03:09 +09001275 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001276 try {
1277 mNMService.setIpForwardingEnabled(false);
1278 } catch (Exception e) {
1279 mLog.e(e);
1280 transitionTo(mSetIpForwardingDisabledErrorState);
1281 return false;
1282 }
1283 transitionTo(mInitialState);
1284 mLog.log("SET master tether settings: OFF");
1285 return true;
1286 }
Erik Kline14f7faf2017-02-14 19:03:09 +09001287
Erik Kline3a5278f2017-06-24 19:29:10 +09001288 protected void chooseUpstreamType(boolean tryCell) {
1289 updateConfiguration(); // TODO - remove?
Erik Kline1e2897d2017-06-09 17:08:52 +09001290
Erik Kline3a5278f2017-06-24 19:29:10 +09001291 final NetworkState ns = mUpstreamNetworkMonitor.selectPreferredUpstreamType(
1292 mConfig.preferredUpstreamIfaceTypes);
1293 if (ns == null) {
1294 if (tryCell) {
1295 mUpstreamNetworkMonitor.registerMobileNetworkRequest();
1296 // We think mobile should be coming up; don't set a retry.
1297 } else {
1298 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
Erik Kline1e2897d2017-06-09 17:08:52 +09001299 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001300 }
1301 setUpstreamNetwork(ns);
1302 }
1303
1304 protected void setUpstreamNetwork(NetworkState ns) {
1305 String iface = null;
1306 if (ns != null && ns.linkProperties != null) {
1307 // Find the interface with the default IPv4 route. It may be the
1308 // interface described by linkProperties, or one of the interfaces
1309 // stacked on top of it.
1310 Log.i(TAG, "Finding IPv4 upstream interface on: " + ns.linkProperties);
1311 RouteInfo ipv4Default = RouteInfo.selectBestRoute(
1312 ns.linkProperties.getAllRoutes(), Inet4Address.ANY);
1313 if (ipv4Default != null) {
1314 iface = ipv4Default.getInterface();
1315 Log.i(TAG, "Found interface " + ipv4Default.getInterface());
1316 } else {
1317 Log.i(TAG, "No IPv4 upstream interface, giving up.");
Erik Kline00019f42016-06-30 19:31:46 +09001318 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001319 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001320
Erik Kline3a5278f2017-06-24 19:29:10 +09001321 if (iface != null) {
1322 setDnsForwarders(ns.network, ns.linkProperties);
Erik Kline6ff17f72015-12-10 20:42:12 +09001323 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001324 notifyTetheredOfNewUpstreamIface(iface);
1325 if (ns != null && pertainsToCurrentUpstream(ns)) {
1326 // If we already have NetworkState for this network examine
1327 // it immediately, because there likely will be no second
1328 // EVENT_ON_AVAILABLE (it was already received).
1329 handleNewUpstreamNetworkState(ns);
1330 } else if (mCurrentUpstreamIface == null) {
1331 // There are no available upstream networks, or none that
1332 // have an IPv4 default route (current metric for success).
1333 handleNewUpstreamNetworkState(null);
1334 }
1335 }
Erik Kline6ff17f72015-12-10 20:42:12 +09001336
Erik Kline3a5278f2017-06-24 19:29:10 +09001337 protected void setDnsForwarders(final Network network, final LinkProperties lp) {
1338 // TODO: Set v4 and/or v6 DNS per available connectivity.
1339 String[] dnsServers = mConfig.defaultIPv4DNS;
1340 final Collection<InetAddress> dnses = lp.getDnsServers();
1341 // TODO: Properly support the absence of DNS servers.
1342 if (dnses != null && !dnses.isEmpty()) {
1343 // TODO: remove this invocation of NetworkUtils.makeStrings().
1344 dnsServers = NetworkUtils.makeStrings(dnses);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001345 }
Erik Kline3a5278f2017-06-24 19:29:10 +09001346 try {
1347 mNMService.setDnsForwarders(network, dnsServers);
1348 mLog.log(String.format(
1349 "SET DNS forwarders: network=%s dnsServers=%s",
1350 network, Arrays.toString(dnsServers)));
1351 } catch (Exception e) {
1352 // TODO: Investigate how this can fail and what exactly
1353 // happens if/when such failures occur.
1354 mLog.e("setting DNS forwarders failed, " + e);
1355 transitionTo(mSetDnsForwardersErrorState);
1356 }
1357 }
Erik Kline00019f42016-06-30 19:31:46 +09001358
Erik Kline3a5278f2017-06-24 19:29:10 +09001359 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
1360 if (DBG) Log.d(TAG, "Notifying tethered with upstream=" + ifaceName);
1361 mCurrentUpstreamIface = ifaceName;
1362 for (TetherInterfaceStateMachine sm : mNotifyList) {
1363 sm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
1364 ifaceName);
Erik Kline00019f42016-06-30 19:31:46 +09001365 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001366 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001367
Erik Kline3a5278f2017-06-24 19:29:10 +09001368 protected void handleNewUpstreamNetworkState(NetworkState ns) {
1369 mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
1370 mOffloadController.setUpstreamLinkProperties((ns != null) ? ns.linkProperties : null);
1371 }
1372
Erik Klineea9cc482017-03-10 19:35:34 +09001373 private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) {
1374 if (mNotifyList.indexOf(who) < 0) {
1375 mNotifyList.add(who);
1376 mIPv6TetheringCoordinator.addActiveDownstream(who, mode);
1377 }
1378
1379 if (mode == IControlsTethering.STATE_TETHERED) {
1380 mForwardedDownstreams.add(who);
1381 } else {
Erik Kline6e9a1012017-06-06 19:24:21 +09001382 mOffloadController.removeDownstreamInterface(who.interfaceName());
Erik Klineea9cc482017-03-10 19:35:34 +09001383 mForwardedDownstreams.remove(who);
1384 }
Erik Kline216af6d2017-04-27 20:57:23 +09001385
1386 // If this is a Wi-Fi interface, notify WifiManager of the active serving state.
1387 if (who.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
1388 final WifiManager mgr = getWifiManager();
1389 final String iface = who.interfaceName();
1390 switch (mode) {
1391 case IControlsTethering.STATE_TETHERED:
Erik Kline2efb8272017-05-31 15:53:53 +09001392 mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +09001393 break;
1394 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Kline2efb8272017-05-31 15:53:53 +09001395 mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +09001396 break;
1397 default:
1398 Log.wtf(TAG, "Unknown active serving mode: " + mode);
1399 break;
1400 }
1401 }
Erik Klineea9cc482017-03-10 19:35:34 +09001402 }
1403
1404 private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) {
1405 mNotifyList.remove(who);
1406 mIPv6TetheringCoordinator.removeActiveDownstream(who);
Erik Kline6e9a1012017-06-06 19:24:21 +09001407 mOffloadController.removeDownstreamInterface(who.interfaceName());
Erik Klineea9cc482017-03-10 19:35:34 +09001408 mForwardedDownstreams.remove(who);
Erik Kline216af6d2017-04-27 20:57:23 +09001409
1410 // If this is a Wi-Fi interface, tell WifiManager of any errors.
1411 if (who.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
1412 if (who.lastError() != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
1413 getWifiManager().updateInterfaceIpState(
Erik Kline2efb8272017-05-31 15:53:53 +09001414 who.interfaceName(), IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline216af6d2017-04-27 20:57:23 +09001415 }
1416 }
Erik Klineea9cc482017-03-10 19:35:34 +09001417 }
1418
Erik Kline3a5278f2017-06-24 19:29:10 +09001419 private void handleUpstreamNetworkMonitorCallback(int arg1, Object o) {
1420 if (arg1 == UpstreamNetworkMonitor.NOTIFY_EXEMPT_PREFIXES) {
1421 mOffloadController.updateExemptPrefixes((Set<IpPrefix>) o);
1422 return;
1423 }
1424
1425 final NetworkState ns = (NetworkState) o;
1426
1427 if (ns == null || !pertainsToCurrentUpstream(ns)) {
1428 // TODO: In future, this is where upstream evaluation and selection
1429 // could be handled for notifications which include sufficient data.
1430 // For example, after CONNECTIVITY_ACTION listening is removed, here
1431 // is where we could observe a Wi-Fi network becoming available and
1432 // passing validation.
1433 if (mCurrentUpstreamIface == null) {
1434 // If we have no upstream interface, try to run through upstream
1435 // selection again. If, for example, IPv4 connectivity has shown up
1436 // after IPv6 (e.g., 464xlat became available) we want the chance to
1437 // notice and act accordingly.
1438 chooseUpstreamType(false);
1439 }
1440 return;
1441 }
1442
1443 switch (arg1) {
1444 case UpstreamNetworkMonitor.EVENT_ON_AVAILABLE:
1445 // The default network changed, or DUN connected
1446 // before this callback was processed. Updates
1447 // for the current NetworkCapabilities and
1448 // LinkProperties have been requested (default
1449 // request) or are being sent shortly (DUN). Do
1450 // nothing until they arrive; if no updates
1451 // arrive there's nothing to do.
1452 break;
1453 case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES:
1454 handleNewUpstreamNetworkState(ns);
1455 break;
1456 case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
1457 setDnsForwarders(ns.network, ns.linkProperties);
1458 handleNewUpstreamNetworkState(ns);
1459 break;
1460 case UpstreamNetworkMonitor.EVENT_ON_LOST:
1461 // TODO: Re-evaluate possible upstreams. Currently upstream
1462 // reevaluation is triggered via received CONNECTIVITY_ACTION
1463 // broadcasts that result in being passed a
1464 // TetherMasterSM.CMD_UPSTREAM_CHANGED.
1465 handleNewUpstreamNetworkState(null);
1466 break;
1467 default:
1468 mLog.e("Unknown arg1 value: " + arg1);
1469 break;
1470 }
1471 }
1472
1473 class TetherModeAliveState extends State {
Erik Klineea9cc482017-03-10 19:35:34 +09001474 boolean mUpstreamWanted = false;
Erik Kline6ff17f72015-12-10 20:42:12 +09001475 boolean mTryCell = true;
Erik Klinee0cce212017-03-06 14:05:23 +09001476
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001477 @Override
1478 public void enter() {
Erik Kline1fdc2e22017-05-08 17:56:35 +09001479 // If turning on master tether settings fails, we have already
1480 // transitioned to an error state; exit early.
1481 if (!turnOnMasterTetherSettings()) {
1482 return;
1483 }
1484
Erik Kline227648f2017-01-20 20:26:10 +09001485 mSimChange.startListening();
Erik Kline6ff17f72015-12-10 20:42:12 +09001486 mUpstreamNetworkMonitor.start();
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001487
Erik Klinef4b6e342017-04-25 19:19:59 +09001488 // TODO: De-duplicate with updateUpstreamWanted() below.
Erik Klineea9cc482017-03-10 19:35:34 +09001489 if (upstreamWanted()) {
1490 mUpstreamWanted = true;
Erik Kline3a5278f2017-06-24 19:29:10 +09001491 startOffloadController();
Erik Klineea9cc482017-03-10 19:35:34 +09001492 chooseUpstreamType(true);
1493 mTryCell = false;
1494 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001495 }
Erik Klinefa37b2f2016-08-02 18:27:03 +09001496
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001497 @Override
1498 public void exit() {
Erik Klinee0cce212017-03-06 14:05:23 +09001499 mOffloadController.stop();
Erik Kline6ff17f72015-12-10 20:42:12 +09001500 mUpstreamNetworkMonitor.stop();
Erik Kline227648f2017-01-20 20:26:10 +09001501 mSimChange.stopListening();
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001502 notifyTetheredOfNewUpstreamIface(null);
Erik Klinefa37b2f2016-08-02 18:27:03 +09001503 handleNewUpstreamNetworkState(null);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001504 }
Erik Klinefa37b2f2016-08-02 18:27:03 +09001505
Erik Klineea9cc482017-03-10 19:35:34 +09001506 private boolean updateUpstreamWanted() {
1507 final boolean previousUpstreamWanted = mUpstreamWanted;
1508 mUpstreamWanted = upstreamWanted();
Erik Klinef4b6e342017-04-25 19:19:59 +09001509 if (mUpstreamWanted != previousUpstreamWanted) {
1510 if (mUpstreamWanted) {
Erik Kline3a5278f2017-06-24 19:29:10 +09001511 startOffloadController();
Erik Klinef4b6e342017-04-25 19:19:59 +09001512 } else {
1513 mOffloadController.stop();
1514 }
1515 }
Erik Klineea9cc482017-03-10 19:35:34 +09001516 return previousUpstreamWanted;
1517 }
1518
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001519 @Override
1520 public boolean processMessage(Message message) {
Lorenzo Colitticd63d242016-04-10 15:39:53 +09001521 maybeLogMessage(this, message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001522 boolean retValue = true;
1523 switch (message.what) {
Erik Klineea9cc482017-03-10 19:35:34 +09001524 case EVENT_IFACE_SERVING_STATE_ACTIVE: {
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001525 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001526 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
Erik Klineea9cc482017-03-10 19:35:34 +09001527 handleInterfaceServingStateActive(message.arg1, who);
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001528 who.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
Erik Kline6ff17f72015-12-10 20:42:12 +09001529 mCurrentUpstreamIface);
Erik Klineea9cc482017-03-10 19:35:34 +09001530 // If there has been a change and an upstream is now
1531 // desired, kick off the selection process.
1532 final boolean previousUpstreamWanted = updateUpstreamWanted();
1533 if (!previousUpstreamWanted && mUpstreamWanted) {
1534 chooseUpstreamType(true);
1535 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001536 break;
Erik Kline6e29bf02016-08-15 16:16:18 +09001537 }
Erik Klineea9cc482017-03-10 19:35:34 +09001538 case EVENT_IFACE_SERVING_STATE_INACTIVE: {
Erik Kline6e29bf02016-08-15 16:16:18 +09001539 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001540 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
Erik Klineea9cc482017-03-10 19:35:34 +09001541 handleInterfaceServingStateInactive(who);
1542
1543 if (mNotifyList.isEmpty()) {
Erik Kline47222fc2017-04-30 19:36:15 +09001544 // This transitions us out of TetherModeAliveState,
1545 // either to InitialState or an error state.
Erik Kline1fdc2e22017-05-08 17:56:35 +09001546 turnOffMasterTetherSettings();
1547 break;
1548 }
1549
1550 if (DBG) {
1551 Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
1552 " live requests:");
1553 for (TetherInterfaceStateMachine o : mNotifyList) {
1554 Log.d(TAG, " " + o);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001555 }
1556 }
Erik Klineea9cc482017-03-10 19:35:34 +09001557 // If there has been a change and an upstream is no
1558 // longer desired, release any mobile requests.
1559 final boolean previousUpstreamWanted = updateUpstreamWanted();
1560 if (previousUpstreamWanted && !mUpstreamWanted) {
1561 mUpstreamNetworkMonitor.releaseMobileNetworkRequest();
1562 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001563 break;
Erik Kline6e29bf02016-08-15 16:16:18 +09001564 }
Erik Kline6e9a1012017-06-06 19:24:21 +09001565 case EVENT_IFACE_UPDATE_LINKPROPERTIES: {
1566 final LinkProperties newLp = (LinkProperties) message.obj;
1567 if (message.arg1 == IControlsTethering.STATE_TETHERED) {
1568 mOffloadController.notifyDownstreamLinkProperties(newLp);
1569 } else {
1570 mOffloadController.removeDownstreamInterface(newLp.getInterfaceName());
1571 }
1572 break;
1573 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001574 case CMD_UPSTREAM_CHANGED:
Erik Klineea9cc482017-03-10 19:35:34 +09001575 updateUpstreamWanted();
1576 if (!mUpstreamWanted) break;
1577
Erik Klinefb413432017-02-14 18:26:04 +09001578 // Need to try DUN immediately if Wi-Fi goes down.
1579 chooseUpstreamType(true);
1580 mTryCell = false;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001581 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001582 case CMD_RETRY_UPSTREAM:
Erik Klineea9cc482017-03-10 19:35:34 +09001583 updateUpstreamWanted();
1584 if (!mUpstreamWanted) break;
1585
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001586 chooseUpstreamType(mTryCell);
1587 mTryCell = !mTryCell;
1588 break;
Erik Kline00019f42016-06-30 19:31:46 +09001589 case EVENT_UPSTREAM_CALLBACK: {
Erik Klineea9cc482017-03-10 19:35:34 +09001590 updateUpstreamWanted();
Erik Kline3a5278f2017-06-24 19:29:10 +09001591 if (mUpstreamWanted) {
1592 handleUpstreamNetworkMonitorCallback(message.arg1, message.obj);
Erik Kline6ff17f72015-12-10 20:42:12 +09001593 }
1594 break;
Erik Kline00019f42016-06-30 19:31:46 +09001595 }
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001596 default:
1597 retValue = false;
1598 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001599 }
1600 return retValue;
1601 }
1602 }
1603
Wink Saville64c42ca2011-04-18 14:55:10 -07001604 class ErrorState extends State {
Erik Kline8351faa2017-04-17 16:47:23 +09001605 private int mErrorNotification;
1606
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001607 @Override
1608 public boolean processMessage(Message message) {
1609 boolean retValue = true;
1610 switch (message.what) {
Erik Klineea9cc482017-03-10 19:35:34 +09001611 case EVENT_IFACE_SERVING_STATE_ACTIVE:
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001612 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001613 who.sendMessage(mErrorNotification);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001614 break;
Yohei, Oshima977aad52016-12-08 13:39:20 +09001615 case CMD_CLEAR_ERROR:
1616 mErrorNotification = ConnectivityManager.TETHER_ERROR_NO_ERROR;
1617 transitionTo(mInitialState);
1618 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001619 default:
1620 retValue = false;
1621 }
1622 return retValue;
1623 }
Erik Kline8351faa2017-04-17 16:47:23 +09001624
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001625 void notify(int msgType) {
1626 mErrorNotification = msgType;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001627 for (TetherInterfaceStateMachine sm : mNotifyList) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001628 sm.sendMessage(msgType);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001629 }
1630 }
1631
1632 }
Erik Kline8351faa2017-04-17 16:47:23 +09001633
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001634 class SetIpForwardingEnabledErrorState extends ErrorState {
1635 @Override
1636 public void enter() {
1637 Log.e(TAG, "Error in setIpForwardingEnabled");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001638 notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001639 }
1640 }
1641
1642 class SetIpForwardingDisabledErrorState extends ErrorState {
1643 @Override
1644 public void enter() {
1645 Log.e(TAG, "Error in setIpForwardingDisabled");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001646 notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001647 }
1648 }
1649
1650 class StartTetheringErrorState extends ErrorState {
1651 @Override
1652 public void enter() {
1653 Log.e(TAG, "Error in startTethering");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001654 notify(TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001655 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001656 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001657 } catch (Exception e) {}
1658 }
1659 }
1660
1661 class StopTetheringErrorState extends ErrorState {
1662 @Override
1663 public void enter() {
1664 Log.e(TAG, "Error in stopTethering");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001665 notify(TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001666 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001667 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001668 } catch (Exception e) {}
1669 }
1670 }
1671
1672 class SetDnsForwardersErrorState extends ErrorState {
1673 @Override
1674 public void enter() {
1675 Log.e(TAG, "Error in setDnsForwarders");
Mitchell Wills7040b4e2016-05-23 16:40:10 -07001676 notify(TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001677 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001678 mNMService.stopTethering();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001679 } catch (Exception e) {}
1680 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001681 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001682 } catch (Exception e) {}
1683 }
1684 }
1685 }
1686
Christopher Wiley499a57a2016-05-16 16:19:07 -07001687 @Override
Lorenzo Colittie3805462015-06-03 11:18:24 +09001688 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Christopher Wiley499a57a2016-05-16 16:19:07 -07001689 // Binder.java closes the resource for us.
1690 @SuppressWarnings("resource")
Lorenzo Colittie3805462015-06-03 11:18:24 +09001691 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06001692 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001693
Lorenzo Colittie3805462015-06-03 11:18:24 +09001694 pw.println("Tethering:");
1695 pw.increaseIndent();
Lorenzo Colittie3805462015-06-03 11:18:24 +09001696
Erik Kline9db1b542017-03-16 14:10:27 +09001697 pw.println("Configuration:");
1698 pw.increaseIndent();
1699 final TetheringConfiguration cfg = mConfig;
1700 cfg.dump(pw);
1701 pw.decreaseIndent();
1702
1703 synchronized (mPublicSync) {
Robert Greenwaltb4453622011-11-03 16:01:40 -07001704 pw.println("Tether state:");
Lorenzo Colittie3805462015-06-03 11:18:24 +09001705 pw.increaseIndent();
Christopher Wileyd985dde2016-05-31 10:44:35 -07001706 for (int i = 0; i < mTetherStates.size(); i++) {
1707 final String iface = mTetherStates.keyAt(i);
1708 final TetherState tetherState = mTetherStates.valueAt(i);
1709 pw.print(iface + " - ");
1710
Hugo Benichib55fb222017-03-10 14:20:57 +09001711 switch (tetherState.lastState) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001712 case IControlsTethering.STATE_UNAVAILABLE:
1713 pw.print("UnavailableState");
1714 break;
1715 case IControlsTethering.STATE_AVAILABLE:
1716 pw.print("AvailableState");
1717 break;
1718 case IControlsTethering.STATE_TETHERED:
1719 pw.print("TetheredState");
1720 break;
Erik Klineca41be72017-04-20 22:59:16 +09001721 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Klineea9cc482017-03-10 19:35:34 +09001722 pw.print("LocalHotspotState");
1723 break;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001724 default:
1725 pw.print("UnknownState");
1726 break;
1727 }
Hugo Benichib55fb222017-03-10 14:20:57 +09001728 pw.println(" - lastError = " + tetherState.lastError);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001729 }
Erik Klineea9cc482017-03-10 19:35:34 +09001730 pw.println("Upstream wanted: " + upstreamWanted());
Erik Klineee363c42017-05-29 09:11:03 +09001731 pw.println("Current upstream interface: " + mCurrentUpstreamIface);
Lorenzo Colittie3805462015-06-03 11:18:24 +09001732 pw.decreaseIndent();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001733 }
Erik Kline1fdc2e22017-05-08 17:56:35 +09001734
1735 pw.println("Log:");
1736 pw.increaseIndent();
Erik Kline7747fd42017-05-12 16:52:48 +09001737 if (argsContain(args, SHORT_ARG)) {
1738 pw.println("<log removed for brevity>");
1739 } else {
1740 mLog.dump(fd, pw, args);
1741 }
Erik Kline1fdc2e22017-05-08 17:56:35 +09001742 pw.decreaseIndent();
1743
Lorenzo Colittie3805462015-06-03 11:18:24 +09001744 pw.decreaseIndent();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001745 }
Christopher Wileye03fb442016-05-18 13:45:20 -07001746
Erik Kline7747fd42017-05-12 16:52:48 +09001747 private static boolean argsContain(String[] args, String target) {
1748 for (String arg : args) {
Erik Klineee363c42017-05-29 09:11:03 +09001749 if (target.equals(arg)) return true;
Erik Kline7747fd42017-05-12 16:52:48 +09001750 }
1751 return false;
1752 }
1753
Erik Kline6e9a1012017-06-06 19:24:21 +09001754 private IControlsTethering makeControlCallback(String ifname) {
1755 return new IControlsTethering() {
1756 @Override
1757 public void updateInterfaceState(
1758 TetherInterfaceStateMachine who, int state, int lastError) {
1759 notifyInterfaceStateChange(ifname, who, state, lastError);
1760 }
1761
1762 @Override
1763 public void updateLinkProperties(
1764 TetherInterfaceStateMachine who, LinkProperties newLp) {
1765 notifyLinkPropertiesChanged(ifname, who, newLp);
1766 }
1767 };
1768 }
1769
1770 // TODO: Move into TetherMasterSM.
1771 private void notifyInterfaceStateChange(
1772 String iface, TetherInterfaceStateMachine who, int state, int error) {
Christopher Wileyd985dde2016-05-31 10:44:35 -07001773 synchronized (mPublicSync) {
Erik Kline216af6d2017-04-27 20:57:23 +09001774 final TetherState tetherState = mTetherStates.get(iface);
Hugo Benichib55fb222017-03-10 14:20:57 +09001775 if (tetherState != null && tetherState.stateMachine.equals(who)) {
1776 tetherState.lastState = state;
1777 tetherState.lastError = error;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001778 } else {
1779 if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
1780 }
1781 }
1782
Erik Kline7747fd42017-05-12 16:52:48 +09001783 mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
Christopher Wileyd985dde2016-05-31 10:44:35 -07001784
Christopher Wileydeebfec2016-09-16 11:14:36 -07001785 try {
1786 // Notify that we're tethering (or not) this interface.
1787 // This is how data saver for instance knows if the user explicitly
1788 // turned on tethering (thus keeping us from being in data saver mode).
1789 mPolicyManager.onTetheringChanged(iface, state == IControlsTethering.STATE_TETHERED);
1790 } catch (RemoteException e) {
1791 // Not really very much we can do here.
1792 }
1793
Yohei, Oshima977aad52016-12-08 13:39:20 +09001794 // If TetherMasterSM is in ErrorState, TetherMasterSM stays there.
1795 // Thus we give a chance for TetherMasterSM to recover to InitialState
1796 // by sending CMD_CLEAR_ERROR
1797 if (error == ConnectivityManager.TETHER_ERROR_MASTER_ERROR) {
1798 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_CLEAR_ERROR, who);
1799 }
Erik Klineea9cc482017-03-10 19:35:34 +09001800 int which;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001801 switch (state) {
1802 case IControlsTethering.STATE_UNAVAILABLE:
1803 case IControlsTethering.STATE_AVAILABLE:
Erik Klineea9cc482017-03-10 19:35:34 +09001804 which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001805 break;
1806 case IControlsTethering.STATE_TETHERED:
Erik Klineca41be72017-04-20 22:59:16 +09001807 case IControlsTethering.STATE_LOCAL_ONLY:
Erik Klineea9cc482017-03-10 19:35:34 +09001808 which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001809 break;
Erik Klineea9cc482017-03-10 19:35:34 +09001810 default:
1811 Log.wtf(TAG, "Unknown interface state: " + state);
1812 return;
Christopher Wileyd985dde2016-05-31 10:44:35 -07001813 }
Erik Klineea9cc482017-03-10 19:35:34 +09001814 mTetherMasterSM.sendMessage(which, state, 0, who);
Christopher Wileyd985dde2016-05-31 10:44:35 -07001815 sendTetherStateChangedBroadcast();
1816 }
1817
Erik Kline6e9a1012017-06-06 19:24:21 +09001818 private void notifyLinkPropertiesChanged(String iface, TetherInterfaceStateMachine who,
1819 LinkProperties newLp) {
1820 final int state;
1821 synchronized (mPublicSync) {
1822 final TetherState tetherState = mTetherStates.get(iface);
1823 if (tetherState != null && tetherState.stateMachine.equals(who)) {
1824 state = tetherState.lastState;
1825 } else {
1826 mLog.log("got notification from stale iface " + iface);
1827 return;
1828 }
1829 }
1830
Erik Kline7fd696c2017-06-12 18:20:08 +09001831 mLog.log(String.format(
1832 "OBSERVED LinkProperties update iface=%s state=%s lp=%s",
1833 iface, IControlsTethering.getStateString(state), newLp));
Erik Kline6e9a1012017-06-06 19:24:21 +09001834 final int which = TetherMasterSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
1835 mTetherMasterSM.sendMessage(which, state, 0, newLp);
1836 }
1837
Erik Kline4dd9bb82017-04-26 11:11:07 +09001838 private void maybeTrackNewInterfaceLocked(final String iface) {
1839 // If we don't care about this type of interface, ignore.
1840 final int interfaceType = ifaceNameToType(iface);
1841 if (interfaceType == ConnectivityManager.TETHERING_INVALID) {
1842 mLog.log(iface + " is not a tetherable iface, ignoring");
1843 return;
1844 }
Erik Klinea9cde8b2017-06-20 21:18:31 +09001845 maybeTrackNewInterfaceLocked(iface, interfaceType);
1846 }
Erik Kline4dd9bb82017-04-26 11:11:07 +09001847
Erik Klinea9cde8b2017-06-20 21:18:31 +09001848 private void maybeTrackNewInterfaceLocked(final String iface, int interfaceType) {
Erik Kline4dd9bb82017-04-26 11:11:07 +09001849 // If we have already started a TISM for this interface, skip.
1850 if (mTetherStates.containsKey(iface)) {
1851 mLog.log("active iface (" + iface + ") reported as added, ignoring");
1852 return;
1853 }
1854
1855 mLog.log("adding TetheringInterfaceStateMachine for: " + iface);
1856 final TetherState tetherState = new TetherState(
1857 new TetherInterfaceStateMachine(
Erik Kline6e9a1012017-06-06 19:24:21 +09001858 iface, mLooper, interfaceType, mLog, mNMService, mStatsService,
Erik Klinea8e2e792017-06-13 21:32:10 +09001859 makeControlCallback(iface)));
Christopher Wileyd985dde2016-05-31 10:44:35 -07001860 mTetherStates.put(iface, tetherState);
Hugo Benichib55fb222017-03-10 14:20:57 +09001861 tetherState.stateMachine.start();
Christopher Wileye03fb442016-05-18 13:45:20 -07001862 }
Erik Kline3e756652017-01-17 13:42:19 +09001863
Erik Kline4dd9bb82017-04-26 11:11:07 +09001864 private void stopTrackingInterfaceLocked(final String iface) {
1865 final TetherState tetherState = mTetherStates.get(iface);
1866 if (tetherState == null) {
1867 mLog.log("attempting to remove unknown iface (" + iface + "), ignoring");
1868 return;
1869 }
Erik Kline6e9a1012017-06-06 19:24:21 +09001870 tetherState.stateMachine.stop();
Erik Kline4dd9bb82017-04-26 11:11:07 +09001871 mLog.log("removing TetheringInterfaceStateMachine for: " + iface);
1872 mTetherStates.remove(iface);
1873 }
1874
Erik Kline3e756652017-01-17 13:42:19 +09001875 private static String[] copy(String[] strarray) {
1876 return Arrays.copyOf(strarray, strarray.length);
1877 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001878}