blob: ae2416824bd5db9c0c855b7fc442655cd00021e3 [file] [log] [blame]
Robert Greenwalt3901edb2010-01-26 10:22:37 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
Fan Zhangdefb1182017-07-25 14:18:47 -070019import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
20import static android.net.ConnectivityManager.TETHERING_USB;
Yuuki Habu557e4572020-02-05 16:24:52 +090021import static android.net.TetheringManager.TETHERING_ETHERNET;
Fan Zhangdefb1182017-07-25 14:18:47 -070022
Alex Johnston7d4db752021-01-15 20:46:05 +000023import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfUsbDataSignalingIsDisabled;
24
Daisuke Miyakawa9c602c42010-09-10 12:04:37 -070025import android.app.Activity;
Fan Zhang31b21002019-01-16 13:49:47 -080026import android.app.settings.SettingsEnums;
Danica Chang32711b62010-08-10 18:41:29 -070027import android.bluetooth.BluetoothAdapter;
28import android.bluetooth.BluetoothPan;
Jaikumar Ganesh9ad703c2011-02-23 13:08:09 -080029import android.bluetooth.BluetoothProfile;
Robert Greenwalt3901edb2010-01-26 10:22:37 -080030import android.content.BroadcastReceiver;
31import android.content.Context;
32import android.content.Intent;
33import android.content.IntentFilter;
Mike Lockwood69a09572011-07-19 13:30:03 -070034import android.hardware.usb.UsbManager;
Robert Greenwalt3901edb2010-01-26 10:22:37 -080035import android.net.ConnectivityManager;
Yuuki Habu557e4572020-02-05 16:24:52 +090036import android.net.EthernetManager;
Xiao Madb7d7de2022-01-30 11:18:29 +000037import android.net.EthernetManager.InterfaceState;
38import android.net.EthernetManager.Role;
39import android.net.IpConfiguration;
Yuuki Habu557e4572020-02-05 16:24:52 +090040import android.net.TetheringManager;
Arc Wang005fe692020-03-04 21:03:54 +080041import android.net.wifi.WifiManager;
Daisuke Miyakawa9c602c42010-09-10 12:04:37 -070042import android.os.Bundle;
Mike Lockwood26dad3e2010-03-03 06:19:55 -050043import android.os.Environment;
Jeremy Kleine3e7b952016-01-25 14:43:49 -080044import android.os.Handler;
Alex Johnston7d4db752021-01-15 20:46:05 +000045import android.os.UserHandle;
Amith Yamasani394eaa22013-06-11 11:04:44 -070046import android.os.UserManager;
Chilund3358d82018-03-26 18:28:56 +080047import android.provider.SearchIndexableResource;
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080048import android.util.FeatureFlagUtils;
Hugh Chena3a06612021-07-13 10:42:00 +080049import android.util.Log;
Felipe Leme5c091842016-04-21 17:17:28 -070050
Xiao Madb7d7de2022-01-30 11:18:29 +000051import androidx.annotation.NonNull;
Fan Zhang23f8d592018-08-28 15:11:40 -070052import androidx.annotation.VisibleForTesting;
53import androidx.preference.Preference;
54import androidx.preference.SwitchPreference;
55
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -080056import com.android.settings.core.FeatureFlags;
Felipe Leme5c091842016-04-21 17:17:28 -070057import com.android.settings.datausage.DataSaverBackend;
Chilund3358d82018-03-26 18:28:56 +080058import com.android.settings.search.BaseSearchIndexProvider;
Fan Zhang78d5efd2017-06-06 16:55:53 -070059import com.android.settings.wifi.tether.WifiTetherPreferenceController;
Alex Johnston685cacb2021-08-02 14:16:49 +010060import com.android.settingslib.RestrictedLockUtils;
Alex Johnston7d4db752021-01-15 20:46:05 +000061import com.android.settingslib.RestrictedSwitchPreference;
Jason Monk4896c012015-02-11 13:30:41 -050062import com.android.settingslib.TetherUtil;
Chilund3358d82018-03-26 18:28:56 +080063import com.android.settingslib.search.SearchIndexable;
Jeff Sharkeye16e44f2014-11-13 18:02:31 -080064
Jeremy Kleine3e7b952016-01-25 14:43:49 -080065import java.lang.ref.WeakReference;
Robert Greenwaltc4764d22010-02-12 14:21:37 -080066import java.util.ArrayList;
Chilund3358d82018-03-26 18:28:56 +080067import java.util.Arrays;
Xiao Madb7d7de2022-01-30 11:18:29 +000068import java.util.HashSet;
Chilund3358d82018-03-26 18:28:56 +080069import java.util.List;
Robert Greenwaltf60b92b2012-09-13 15:02:00 -070070import java.util.concurrent.atomic.AtomicReference;
Matthew Xieb5f144a2012-06-28 18:41:54 -070071
Robert Greenwalt3901edb2010-01-26 10:22:37 -080072/*
73 * Displays preferences for Tethering.
74 */
Chilund3358d82018-03-26 18:28:56 +080075@SearchIndexable
Sudheer Shanka7dbbe132016-02-16 14:19:32 +000076public class TetherSettings extends RestrictedSettingsFragment
Fan Zhangdefb1182017-07-25 14:18:47 -070077 implements DataSaverBackend.Listener {
Danica Chang32711b62010-08-10 18:41:29 -070078
Chilund3358d82018-03-26 18:28:56 +080079 @VisibleForTesting
80 static final String KEY_TETHER_PREFS_SCREEN = "tether_prefs_screen";
81 @VisibleForTesting
82 static final String KEY_WIFI_TETHER = "wifi_tether";
83 @VisibleForTesting
84 static final String KEY_USB_TETHER_SETTINGS = "usb_tether_settings";
85 @VisibleForTesting
86 static final String KEY_ENABLE_BLUETOOTH_TETHERING = "enable_bluetooth_tethering";
Yuuki Habu557e4572020-02-05 16:24:52 +090087 private static final String KEY_ENABLE_ETHERNET_TETHERING = "enable_ethernet_tethering";
Chilund3358d82018-03-26 18:28:56 +080088 private static final String KEY_DATA_SAVER_FOOTER = "disabled_on_data_saver";
Arc Wang005fe692020-03-04 21:03:54 +080089 @VisibleForTesting
Tsung-Mao Fang00956fb2020-11-16 18:13:36 +080090 static final String KEY_TETHER_PREFS_TOP_INTRO = "tether_prefs_top_intro";
Robert Greenwalt3901edb2010-01-26 10:22:37 -080091
Rebecca Silbersteinffb4fbb2016-03-04 15:47:43 -080092 private static final String TAG = "TetheringSettings";
Hugh Chena3a06612021-07-13 10:42:00 +080093 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Rebecca Silbersteinffb4fbb2016-03-04 15:47:43 -080094
Alex Johnston7d4db752021-01-15 20:46:05 +000095 private RestrictedSwitchPreference mUsbTether;
Robert Greenwalt3901edb2010-01-26 10:22:37 -080096
PauloftheWest656c88c2014-08-24 11:59:35 -070097 private SwitchPreference mBluetoothTether;
Danica Chang32711b62010-08-10 18:41:29 -070098
Yuuki Habu557e4572020-02-05 16:24:52 +090099 private SwitchPreference mEthernetTether;
100
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800101 private BroadcastReceiver mTetherChangeReceiver;
102
Danica Chang32711b62010-08-10 18:41:29 -0700103 private String[] mBluetoothRegexs;
Fan Zhangdefb1182017-07-25 14:18:47 -0700104 private AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<>();
Danica Chang32711b62010-08-10 18:41:29 -0700105
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800106 private Handler mHandler = new Handler();
107 private OnStartTetheringCallback mStartTetheringCallback;
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800108 private ConnectivityManager mCm;
Yuuki Habu557e4572020-02-05 16:24:52 +0900109 private EthernetManager mEm;
Yuuki Habu557e4572020-02-05 16:24:52 +0900110 private TetheringEventCallback mTetheringEventCallback;
111 private EthernetListener mEthernetListener;
Xiao Madb7d7de2022-01-30 11:18:29 +0000112 private final HashSet<String> mAvailableInterfaces = new HashSet<>();
Amith Yamasani84a042c2011-03-02 11:25:04 -0800113
Fan Zhang78d5efd2017-06-06 16:55:53 -0700114 private WifiTetherPreferenceController mWifiTetherPreferenceController;
115
Mike Lockwood69a09572011-07-19 13:30:03 -0700116 private boolean mUsbConnected;
117 private boolean mMassStorageActive;
118
Jake Hambyc777ee22011-03-04 15:37:39 -0800119 private boolean mBluetoothEnableForTether;
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400120 private boolean mUnavailable;
121
Felipe Leme5c091842016-04-21 17:17:28 -0700122 private DataSaverBackend mDataSaverBackend;
123 private boolean mDataSaverEnabled;
124 private Preference mDataSaverFooter;
125
Hugh Chena3a06612021-07-13 10:42:00 +0800126 @VisibleForTesting
127 String[] mUsbRegexs;
128 @VisibleForTesting
129 Context mContext;
130 @VisibleForTesting
131 TetheringManager mTm;
132
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800133 @Override
Fan Zhang65076132016-08-08 10:25:13 -0700134 public int getMetricsCategory() {
Fan Zhang31b21002019-01-16 13:49:47 -0800135 return SettingsEnums.TETHER;
Chris Wren8a963ba2015-03-20 10:29:14 -0400136 }
137
Sudheer Shanka7dbbe132016-02-16 14:19:32 +0000138 public TetherSettings() {
139 super(UserManager.DISALLOW_CONFIG_TETHERING);
140 }
141
Chris Wren8a963ba2015-03-20 10:29:14 -0400142 @Override
Fan Zhang78d5efd2017-06-06 16:55:53 -0700143 public void onAttach(Context context) {
144 super.onAttach(context);
145 mWifiTetherPreferenceController =
tmfang27c84de2018-06-28 11:39:05 +0800146 new WifiTetherPreferenceController(context, getSettingsLifecycle());
Fan Zhang78d5efd2017-06-06 16:55:53 -0700147 }
148
149 @Override
Daisuke Miyakawa9c602c42010-09-10 12:04:37 -0700150 public void onCreate(Bundle icicle) {
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800151 super.onCreate(icicle);
Rohit Sisodia37155e92014-09-22 16:34:56 -0500152
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800153 addPreferencesFromResource(R.xml.tether_prefs);
Hugh Chena3a06612021-07-13 10:42:00 +0800154 mContext = getContext();
155 mDataSaverBackend = new DataSaverBackend(mContext);
Felipe Leme5c091842016-04-21 17:17:28 -0700156 mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled();
Chilund3358d82018-03-26 18:28:56 +0800157 mDataSaverFooter = findPreference(KEY_DATA_SAVER_FOOTER);
Felipe Leme5c091842016-04-21 17:17:28 -0700158
Sudheer Shanka7dbbe132016-02-16 14:19:32 +0000159 setIfOnlyAvailableForAdmins(true);
160 if (isUiRestricted()) {
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400161 mUnavailable = true;
Doris Lingdd5693c2017-03-24 13:10:09 -0700162 getPreferenceScreen().removeAll();
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400163 return;
164 }
165
Daisuke Miyakawa9c602c42010-09-10 12:04:37 -0700166 final Activity activity = getActivity();
Jaikumar Ganesh9ad703c2011-02-23 13:08:09 -0800167 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
168 if (adapter != null) {
169 adapter.getProfileProxy(activity.getApplicationContext(), mProfileServiceListener,
170 BluetoothProfile.PAN);
171 }
172
Ted Wang47f2ebb2020-09-01 14:45:46 +0800173 setupTetherPreference();
Tsung-Mao Fang00956fb2020-11-16 18:13:36 +0800174 setTopIntroPreferenceTitle();
Robert Greenwaltc4764d22010-02-12 14:21:37 -0800175
Felipe Leme5c091842016-04-21 17:17:28 -0700176 mDataSaverBackend.addListener(this);
177
Rebecca Silbersteinffb4fbb2016-03-04 15:47:43 -0800178 mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
Yuuki Habu557e4572020-02-05 16:24:52 +0900179 mTm = (TetheringManager) getSystemService(Context.TETHERING_SERVICE);
Xiao Madb7d7de2022-01-30 11:18:29 +0000180 // Some devices do not have available EthernetManager. In that case getSystemService will
181 // return null.
182 mEm = mContext.getSystemService(EthernetManager.class);
Irfan Sheriff47ebb782010-03-10 08:27:15 -0800183
paulhu6151c222021-02-20 11:21:53 +0800184 mUsbRegexs = mTm.getTetherableUsbRegexs();
185 mBluetoothRegexs = mTm.getTetherableBluetoothRegexs();
Danica Chang32711b62010-08-10 18:41:29 -0700186
Amith Yamasanie419bc12011-02-14 14:19:08 -0800187 final boolean usbAvailable = mUsbRegexs.length != 0;
Weilun Duf8757b72020-03-30 13:27:13 -0700188 final boolean bluetoothAvailable = adapter != null && mBluetoothRegexs.length != 0;
Xiao Madb7d7de2022-01-30 11:18:29 +0000189 final boolean ethernetAvailable = (mEm != null);
Danica Chang32711b62010-08-10 18:41:29 -0700190
Danica Chang32711b62010-08-10 18:41:29 -0700191 if (!usbAvailable || Utils.isMonkeyRunning()) {
192 getPreferenceScreen().removePreference(mUsbTether);
193 }
Amith Yamasanie419bc12011-02-14 14:19:08 -0800194
Fan Zhang78d5efd2017-06-06 16:55:53 -0700195 mWifiTetherPreferenceController.displayPreference(getPreferenceScreen());
Amith Yamasanie419bc12011-02-14 14:19:08 -0800196
Danica Chang32711b62010-08-10 18:41:29 -0700197 if (!bluetoothAvailable) {
198 getPreferenceScreen().removePreference(mBluetoothTether);
Danica Chang32711b62010-08-10 18:41:29 -0700199 } else {
Robert Greenwaltf60b92b2012-09-13 15:02:00 -0700200 BluetoothPan pan = mBluetoothPan.get();
201 if (pan != null && pan.isTetheringOn()) {
Danica Chang32711b62010-08-10 18:41:29 -0700202 mBluetoothTether.setChecked(true);
Danica Chang32711b62010-08-10 18:41:29 -0700203 } else {
204 mBluetoothTether.setChecked(false);
Danica Chang32711b62010-08-10 18:41:29 -0700205 }
206 }
Yuuki Habu557e4572020-02-05 16:24:52 +0900207 if (!ethernetAvailable) getPreferenceScreen().removePreference(mEthernetTether);
Felipe Leme5c091842016-04-21 17:17:28 -0700208 // Set initial state based on Data Saver mode.
209 onDataSaverChanged(mDataSaverBackend.isDataSaverEnabled());
210 }
211
212 @Override
213 public void onDestroy() {
214 mDataSaverBackend.remListener(this);
Robert Greenwalt89b8bab2016-06-13 13:01:36 -0700215
宋凯伦0fb2f2b2016-05-25 10:15:03 +0800216 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
217 BluetoothProfile profile = mBluetoothPan.getAndSet(null);
218 if (profile != null && adapter != null) {
219 adapter.closeProfileProxy(BluetoothProfile.PAN, profile);
220 }
Robert Greenwalt89b8bab2016-06-13 13:01:36 -0700221
Felipe Leme5c091842016-04-21 17:17:28 -0700222 super.onDestroy();
223 }
224
Ted Wang47f2ebb2020-09-01 14:45:46 +0800225 @VisibleForTesting
226 void setupTetherPreference() {
Alex Johnston7d4db752021-01-15 20:46:05 +0000227 mUsbTether = (RestrictedSwitchPreference) findPreference(KEY_USB_TETHER_SETTINGS);
Ted Wang47f2ebb2020-09-01 14:45:46 +0800228 mBluetoothTether = (SwitchPreference) findPreference(KEY_ENABLE_BLUETOOTH_TETHERING);
229 mEthernetTether = (SwitchPreference) findPreference(KEY_ENABLE_ETHERNET_TETHERING);
230 }
231
Felipe Leme5c091842016-04-21 17:17:28 -0700232 @Override
233 public void onDataSaverChanged(boolean isDataSaving) {
234 mDataSaverEnabled = isDataSaving;
Felipe Leme5c091842016-04-21 17:17:28 -0700235 mUsbTether.setEnabled(!mDataSaverEnabled);
236 mBluetoothTether.setEnabled(!mDataSaverEnabled);
Yuuki Habu557e4572020-02-05 16:24:52 +0900237 mEthernetTether.setEnabled(!mDataSaverEnabled);
Felipe Leme5c091842016-04-21 17:17:28 -0700238 mDataSaverFooter.setVisible(mDataSaverEnabled);
239 }
240
241 @Override
Bonian Chena5f08852020-07-08 02:47:18 +0800242 public void onAllowlistStatusChanged(int uid, boolean isAllowlisted) {
Felipe Leme5c091842016-04-21 17:17:28 -0700243 }
244
245 @Override
Bonian Chena5f08852020-07-08 02:47:18 +0800246 public void onDenylistStatusChanged(int uid, boolean isDenylisted) {
Rohit Sisodia37155e92014-09-22 16:34:56 -0500247 }
248
Arc Wang005fe692020-03-04 21:03:54 +0800249 @VisibleForTesting
Tsung-Mao Fang00956fb2020-11-16 18:13:36 +0800250 void setTopIntroPreferenceTitle() {
251 final Preference topIntroPreference = findPreference(KEY_TETHER_PREFS_TOP_INTRO);
Hugh Chena3a06612021-07-13 10:42:00 +0800252 final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
Arc Wang005fe692020-03-04 21:03:54 +0800253 if (wifiManager.isStaApConcurrencySupported()) {
Tsung-Mao Fang00956fb2020-11-16 18:13:36 +0800254 topIntroPreference.setTitle(R.string.tethering_footer_info_sta_ap_concurrency);
Arc Wang005fe692020-03-04 21:03:54 +0800255 } else {
Tsung-Mao Fang00956fb2020-11-16 18:13:36 +0800256 topIntroPreference.setTitle(R.string.tethering_footer_info);
Arc Wang005fe692020-03-04 21:03:54 +0800257 }
258 }
259
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800260 private class TetherChangeReceiver extends BroadcastReceiver {
Danica Chang32711b62010-08-10 18:41:29 -0700261 @Override
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800262 public void onReceive(Context content, Intent intent) {
Jake Hambyc777ee22011-03-04 15:37:39 -0800263 String action = intent.getAction();
Hugh Chena3a06612021-07-13 10:42:00 +0800264 if (DEBUG) {
265 Log.d(TAG, "onReceive() action : " + action);
266 }
267 // TODO(b/194961339): Stop using ACTION_TETHER_STATE_CHANGED and use
268 // mTetheringEventCallback instead.
paulhu6151c222021-02-20 11:21:53 +0800269 if (action.equals(TetheringManager.ACTION_TETHER_STATE_CHANGED)) {
Robert Greenwalta2488762010-03-10 16:57:08 -0800270 // TODO - this should understand the interface types
271 ArrayList<String> available = intent.getStringArrayListExtra(
paulhu6151c222021-02-20 11:21:53 +0800272 TetheringManager.EXTRA_AVAILABLE_TETHER);
Robert Greenwalta2488762010-03-10 16:57:08 -0800273 ArrayList<String> active = intent.getStringArrayListExtra(
paulhu6151c222021-02-20 11:21:53 +0800274 TetheringManager.EXTRA_ACTIVE_TETHER);
Hugh Chena3a06612021-07-13 10:42:00 +0800275 updateBluetoothState();
276 updateEthernetState(available.toArray(new String[available.size()]),
277 active.toArray(new String[active.size()]));
Mike Lockwood69a09572011-07-19 13:30:03 -0700278 } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
279 mMassStorageActive = true;
Hugh Chena3a06612021-07-13 10:42:00 +0800280 updateBluetoothAndEthernetState();
281 updateUsbPreference();
Mike Lockwood69a09572011-07-19 13:30:03 -0700282 } else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) {
283 mMassStorageActive = false;
Hugh Chena3a06612021-07-13 10:42:00 +0800284 updateBluetoothAndEthernetState();
285 updateUsbPreference();
Mike Lockwood69a09572011-07-19 13:30:03 -0700286 } else if (action.equals(UsbManager.ACTION_USB_STATE)) {
287 mUsbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
Hugh Chena3a06612021-07-13 10:42:00 +0800288 updateBluetoothAndEthernetState();
289 updateUsbPreference();
Jake Hambyc777ee22011-03-04 15:37:39 -0800290 } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
291 if (mBluetoothEnableForTether) {
292 switch (intent
293 .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
294 case BluetoothAdapter.STATE_ON:
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800295 startTethering(TETHERING_BLUETOOTH);
296 mBluetoothEnableForTether = false;
Jake Hambyc777ee22011-03-04 15:37:39 -0800297 break;
298
299 case BluetoothAdapter.STATE_OFF:
300 case BluetoothAdapter.ERROR:
301 mBluetoothEnableForTether = false;
302 break;
303
304 default:
305 // ignore transition states
306 }
307 }
Hugh Chena3a06612021-07-13 10:42:00 +0800308 updateBluetoothAndEthernetState();
Ted Wang47f2ebb2020-09-01 14:45:46 +0800309 } else if (action.equals(BluetoothPan.ACTION_TETHERING_STATE_CHANGED)) {
Hugh Chena3a06612021-07-13 10:42:00 +0800310 updateBluetoothAndEthernetState();
Robert Greenwalta2488762010-03-10 16:57:08 -0800311 }
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800312 }
313 }
314
315 @Override
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700316 public void onStart() {
317 super.onStart();
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800318
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400319 if (mUnavailable) {
Sudheer Shanka7dbbe132016-02-16 14:19:32 +0000320 if (!isUiRestrictedByOnlyAdmin()) {
321 getEmptyTextView().setText(R.string.tethering_settings_not_available);
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400322 }
Sudheer Shanka7dbbe132016-02-16 14:19:32 +0000323 getPreferenceScreen().removeAll();
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400324 return;
325 }
326
Daisuke Miyakawa9c602c42010-09-10 12:04:37 -0700327
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800328 mStartTetheringCallback = new OnStartTetheringCallback(this);
Yuuki Habu557e4572020-02-05 16:24:52 +0900329 mTetheringEventCallback = new TetheringEventCallback();
Xiao Maf621c4b2022-01-18 06:44:52 +0000330 mTm.registerTetheringEventCallback(r -> mHandler.post(r), mTetheringEventCallback);
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800331
Mike Lockwood69a09572011-07-19 13:30:03 -0700332 mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState());
Ted Wang47f2ebb2020-09-01 14:45:46 +0800333 registerReceiver();
Jake Hambyc777ee22011-03-04 15:37:39 -0800334
Yuuki Habu557e4572020-02-05 16:24:52 +0900335 mEthernetListener = new EthernetListener();
Weilun Duf8757b72020-03-30 13:27:13 -0700336 if (mEm != null)
Xiao Madb7d7de2022-01-30 11:18:29 +0000337 mEm.addInterfaceStateListener(r -> mHandler.post(r), mEthernetListener);
Yuuki Habu557e4572020-02-05 16:24:52 +0900338
Hugh Chena3a06612021-07-13 10:42:00 +0800339 updateUsbState();
340 updateBluetoothAndEthernetState();
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800341 }
342
343 @Override
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700344 public void onStop() {
345 super.onStop();
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400346
347 if (mUnavailable) {
348 return;
349 }
Daisuke Miyakawa9c602c42010-09-10 12:04:37 -0700350 getActivity().unregisterReceiver(mTetherChangeReceiver);
Yuuki Habu557e4572020-02-05 16:24:52 +0900351 mTm.unregisterTetheringEventCallback(mTetheringEventCallback);
Weilun Duf8757b72020-03-30 13:27:13 -0700352 if (mEm != null)
Xiao Madb7d7de2022-01-30 11:18:29 +0000353 mEm.removeInterfaceStateListener(mEthernetListener);
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800354 mTetherChangeReceiver = null;
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800355 mStartTetheringCallback = null;
Yuuki Habu557e4572020-02-05 16:24:52 +0900356 mTetheringEventCallback = null;
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800357 }
358
Ted Wang47f2ebb2020-09-01 14:45:46 +0800359 @VisibleForTesting
360 void registerReceiver() {
361 final Activity activity = getActivity();
362
363 mTetherChangeReceiver = new TetherChangeReceiver();
paulhu6151c222021-02-20 11:21:53 +0800364 IntentFilter filter = new IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED);
Ted Wang47f2ebb2020-09-01 14:45:46 +0800365 final Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter);
366
367 filter = new IntentFilter();
368 filter.addAction(UsbManager.ACTION_USB_STATE);
369 activity.registerReceiver(mTetherChangeReceiver, filter);
370
371 filter = new IntentFilter();
372 filter.addAction(Intent.ACTION_MEDIA_SHARED);
373 filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
374 filter.addDataScheme("file");
375 activity.registerReceiver(mTetherChangeReceiver, filter);
376
377 filter = new IntentFilter();
378 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
379 filter.addAction(BluetoothPan.ACTION_TETHERING_STATE_CHANGED);
380 activity.registerReceiver(mTetherChangeReceiver, filter);
381
382 if (intent != null) mTetherChangeReceiver.onReceive(activity, intent);
383 }
384
Hugh Chena3a06612021-07-13 10:42:00 +0800385 // TODO(b/194961339): Separate the updateBluetoothAndEthernetState() to two methods,
386 // updateBluetoothAndEthernetState() and updateBluetoothAndEthernetPreference().
387 // Because we should update the state when only receiving tethering
388 // state changes and update preference when usb or media share changed.
389 private void updateBluetoothAndEthernetState() {
390 String[] tethered = mTm.getTetheredIfaces();
391 updateBluetoothAndEthernetState(tethered);
Robert Greenwalt209177a2010-03-04 13:29:02 -0800392 }
393
Hugh Chena3a06612021-07-13 10:42:00 +0800394 private void updateBluetoothAndEthernetState(String[] tethered) {
395 String[] available = mTm.getTetherableIfaces();
Doris Ling1e914eb2017-05-30 17:28:06 -0700396 updateBluetoothState();
Yuuki Habu557e4572020-02-05 16:24:52 +0900397 updateEthernetState(available, tethered);
Danica Chang32711b62010-08-10 18:41:29 -0700398 }
399
Hugh Chena3a06612021-07-13 10:42:00 +0800400 private void updateUsbState() {
401 String[] tethered = mTm.getTetheredIfaces();
402 updateUsbState(tethered);
403 }
404
Ted Wang47f2ebb2020-09-01 14:45:46 +0800405 @VisibleForTesting
Hugh Chena3a06612021-07-13 10:42:00 +0800406 void updateUsbState(String[] tethered) {
Jake Hamby436b29e2011-02-07 18:21:25 -0800407 boolean usbTethered = false;
Ben Clark0008d212010-07-27 16:20:59 +0100408 for (String s : tethered) {
Robert Greenwaltc4764d22010-02-12 14:21:37 -0800409 for (String regex : mUsbRegexs) {
410 if (s.matches(regex)) usbTethered = true;
411 }
Robert Greenwaltc4764d22010-02-12 14:21:37 -0800412 }
Hugh Chena3a06612021-07-13 10:42:00 +0800413 if (DEBUG) {
414 Log.d(TAG, "updateUsbState() mUsbConnected : " + mUsbConnected
415 + ", mMassStorageActive : " + mMassStorageActive
416 + ", usbTethered : " + usbTethered);
Robert Greenwaltd5f121c2010-03-02 17:33:11 -0800417 }
Robert Greenwaltc4764d22010-02-12 14:21:37 -0800418 if (usbTethered) {
Felipe Leme5c091842016-04-21 17:17:28 -0700419 mUsbTether.setEnabled(!mDataSaverEnabled);
Robert Greenwalt204e7c12010-03-05 19:00:30 -0800420 mUsbTether.setChecked(true);
Hugh Chena3a06612021-07-13 10:42:00 +0800421 mUsbTether.setDisabledByAdmin(
422 checkIfUsbDataSignalingIsDisabled(mContext, UserHandle.myUserId()));
423 } else {
Robert Greenwalt204e7c12010-03-05 19:00:30 -0800424 mUsbTether.setChecked(false);
Hugh Chena3a06612021-07-13 10:42:00 +0800425 updateUsbPreference();
426 }
427 }
428
429 private void updateUsbPreference() {
430 boolean usbAvailable = mUsbConnected && !mMassStorageActive;
Alex Johnston685cacb2021-08-02 14:16:49 +0100431 final RestrictedLockUtils.EnforcedAdmin enforcedAdmin =
432 checkIfUsbDataSignalingIsDisabled(mContext, UserHandle.myUserId());
Hugh Chena3a06612021-07-13 10:42:00 +0800433
Alex Johnston685cacb2021-08-02 14:16:49 +0100434 if (enforcedAdmin != null) {
435 mUsbTether.setDisabledByAdmin(enforcedAdmin);
436 } else if (usbAvailable) {
Hugh Chena3a06612021-07-13 10:42:00 +0800437 mUsbTether.setEnabled(!mDataSaverEnabled);
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800438 } else {
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800439 mUsbTether.setEnabled(false);
440 }
441 }
Robert Greenwalt209177a2010-03-04 13:29:02 -0800442
Ted Wang47f2ebb2020-09-01 14:45:46 +0800443 @VisibleForTesting
444 int getBluetoothState() {
Danica Chang32711b62010-08-10 18:41:29 -0700445 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
Rebecca Silbersteinffb4fbb2016-03-04 15:47:43 -0800446 if (adapter == null) {
Ted Wang47f2ebb2020-09-01 14:45:46 +0800447 return BluetoothAdapter.ERROR;
448 }
449 return adapter.getState();
450 }
451
452 @VisibleForTesting
453 boolean isBluetoothTetheringOn() {
454 final BluetoothPan bluetoothPan = mBluetoothPan.get();
455 return bluetoothPan != null && bluetoothPan.isTetheringOn();
456 }
457
458 private void updateBluetoothState() {
459 final int btState = getBluetoothState();
Hugh Chena3a06612021-07-13 10:42:00 +0800460 if (DEBUG) {
461 Log.d(TAG, "updateBluetoothState() btState : " + btState);
462 }
Ted Wang47f2ebb2020-09-01 14:45:46 +0800463 if (btState == BluetoothAdapter.ERROR) {
Hugh Chena3a06612021-07-13 10:42:00 +0800464 Log.w(TAG, "updateBluetoothState() Bluetooth state is error!");
Jianzheng Zhou508c7c12013-08-15 14:34:52 +0800465 return;
Rebecca Silbersteinffb4fbb2016-03-04 15:47:43 -0800466 }
Ted Wang47f2ebb2020-09-01 14:45:46 +0800467
Danica Chang32711b62010-08-10 18:41:29 -0700468 if (btState == BluetoothAdapter.STATE_TURNING_OFF) {
469 mBluetoothTether.setEnabled(false);
Danica Chang32711b62010-08-10 18:41:29 -0700470 } else if (btState == BluetoothAdapter.STATE_TURNING_ON) {
471 mBluetoothTether.setEnabled(false);
Danica Chang32711b62010-08-10 18:41:29 -0700472 } else {
Ted Wang47f2ebb2020-09-01 14:45:46 +0800473 if (btState == BluetoothAdapter.STATE_ON && isBluetoothTetheringOn()) {
Robert Greenwaltf60b92b2012-09-13 15:02:00 -0700474 mBluetoothTether.setChecked(true);
Felipe Leme5c091842016-04-21 17:17:28 -0700475 mBluetoothTether.setEnabled(!mDataSaverEnabled);
Robert Greenwaltf60b92b2012-09-13 15:02:00 -0700476 } else {
Felipe Leme5c091842016-04-21 17:17:28 -0700477 mBluetoothTether.setEnabled(!mDataSaverEnabled);
Robert Greenwaltf60b92b2012-09-13 15:02:00 -0700478 mBluetoothTether.setChecked(false);
Robert Greenwaltf60b92b2012-09-13 15:02:00 -0700479 }
Danica Chang32711b62010-08-10 18:41:29 -0700480 }
481 }
482
Ted Wang47f2ebb2020-09-01 14:45:46 +0800483 @VisibleForTesting
484 void updateEthernetState(String[] available, String[] tethered) {
Yuuki Habu557e4572020-02-05 16:24:52 +0900485 boolean isAvailable = false;
486 boolean isTethered = false;
487
488 for (String s : available) {
Xiao Madb7d7de2022-01-30 11:18:29 +0000489 if (mAvailableInterfaces.contains(s)) isAvailable = true;
Yuuki Habu557e4572020-02-05 16:24:52 +0900490 }
491
492 for (String s : tethered) {
Xiao Madb7d7de2022-01-30 11:18:29 +0000493 if (mAvailableInterfaces.contains(s)) isTethered = true;
Yuuki Habu557e4572020-02-05 16:24:52 +0900494 }
495
Hugh Chena3a06612021-07-13 10:42:00 +0800496 if (DEBUG) {
497 Log.d(TAG, "updateEthernetState() isAvailable : " + isAvailable
498 + ", isTethered : " + isTethered);
499 }
500
Yuuki Habu557e4572020-02-05 16:24:52 +0900501 if (isTethered) {
502 mEthernetTether.setEnabled(!mDataSaverEnabled);
503 mEthernetTether.setChecked(true);
Xiao Madb7d7de2022-01-30 11:18:29 +0000504 } else if (mAvailableInterfaces.size() > 0) {
Yuuki Habu557e4572020-02-05 16:24:52 +0900505 mEthernetTether.setEnabled(!mDataSaverEnabled);
506 mEthernetTether.setChecked(false);
507 } else {
508 mEthernetTether.setEnabled(false);
509 mEthernetTether.setChecked(false);
510 }
511 }
512
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800513 private void startTethering(int choice) {
514 if (choice == TETHERING_BLUETOOTH) {
515 // Turn on Bluetooth first.
516 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
517 if (adapter.getState() == BluetoothAdapter.STATE_OFF) {
518 mBluetoothEnableForTether = true;
519 adapter.enable();
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800520 mBluetoothTether.setEnabled(false);
521 return;
Irfan Sheriffaa3d2c42011-10-06 11:45:45 -0700522 }
523 }
Irfan Sheriffaa3d2c42011-10-06 11:45:45 -0700524
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800525 mCm.startTethering(choice, true, mStartTetheringCallback, mHandler);
Irfan Sheriff01b32362011-11-04 12:08:56 -0700526 }
527
528 @Override
Jason Monk39b46742015-09-10 15:52:51 -0400529 public boolean onPreferenceTreeClick(Preference preference) {
Irfan Sheriff01b32362011-11-04 12:08:56 -0700530 if (preference == mUsbTether) {
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800531 if (mUsbTether.isChecked()) {
532 startTethering(TETHERING_USB);
Irfan Sheriff01b32362011-11-04 12:08:56 -0700533 } else {
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800534 mCm.stopTethering(TETHERING_USB);
Irfan Sheriff01b32362011-11-04 12:08:56 -0700535 }
536 } else if (preference == mBluetoothTether) {
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800537 if (mBluetoothTether.isChecked()) {
538 startTethering(TETHERING_BLUETOOTH);
Danica Chang32711b62010-08-10 18:41:29 -0700539 } else {
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800540 mCm.stopTethering(TETHERING_BLUETOOTH);
Danica Chang32711b62010-08-10 18:41:29 -0700541 }
Yuuki Habu557e4572020-02-05 16:24:52 +0900542 } else if (preference == mEthernetTether) {
543 if (mEthernetTether.isChecked()) {
544 startTethering(TETHERING_ETHERNET);
545 } else {
546 mCm.stopTethering(TETHERING_ETHERNET);
547 }
Robert Greenwalt209177a2010-03-04 13:29:02 -0800548 }
Daisuke Miyakawa9c602c42010-09-10 12:04:37 -0700549
Jason Monk39b46742015-09-10 15:52:51 -0400550 return super.onPreferenceTreeClick(preference);
Robert Greenwalt209177a2010-03-04 13:29:02 -0800551 }
552
Amith Yamasanid3fed682012-04-27 17:38:40 -0700553 @Override
554 public int getHelpResource() {
555 return R.string.help_url_tether;
556 }
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800557
558 private BluetoothProfile.ServiceListener mProfileServiceListener =
559 new BluetoothProfile.ServiceListener() {
560 public void onServiceConnected(int profile, BluetoothProfile proxy) {
561 mBluetoothPan.set((BluetoothPan) proxy);
562 }
563 public void onServiceDisconnected(int profile) {
564 mBluetoothPan.set(null);
565 }
566 };
567
Raff Tsaiac3e0d02019-09-19 17:06:45 +0800568 public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
Chilund3358d82018-03-26 18:28:56 +0800569 new BaseSearchIndexProvider() {
570 @Override
571 public List<SearchIndexableResource> getXmlResourcesToIndex(
572 Context context, boolean enabled) {
573 final SearchIndexableResource sir = new SearchIndexableResource(context);
574 sir.xmlResId = R.xml.tether_prefs;
575 return Arrays.asList(sir);
576 }
577
578 @Override
Zhen Zhang0ccc8492020-01-17 15:23:40 -0800579 protected boolean isPageSearchEnabled(Context context) {
Zhen Zhangd2a7f9a2020-01-30 15:12:50 -0800580 return !FeatureFlagUtils.isEnabled(context, FeatureFlags.TETHER_ALL_IN_ONE);
Zhen Zhang0ccc8492020-01-17 15:23:40 -0800581 }
582
583 @Override
Chilund3358d82018-03-26 18:28:56 +0800584 public List<String> getNonIndexableKeys(Context context) {
585 final List<String> keys = super.getNonIndexableKeys(context);
paulhu6151c222021-02-20 11:21:53 +0800586 final TetheringManager tm =
587 context.getSystemService(TetheringManager.class);
Chilund3358d82018-03-26 18:28:56 +0800588
589 if (!TetherUtil.isTetherAvailable(context)) {
590 keys.add(KEY_TETHER_PREFS_SCREEN);
591 keys.add(KEY_WIFI_TETHER);
592 }
593
594 final boolean usbAvailable =
paulhu6151c222021-02-20 11:21:53 +0800595 tm.getTetherableUsbRegexs().length != 0;
Chilund3358d82018-03-26 18:28:56 +0800596 if (!usbAvailable || Utils.isMonkeyRunning()) {
597 keys.add(KEY_USB_TETHER_SETTINGS);
598 }
599
600 final boolean bluetoothAvailable =
paulhu6151c222021-02-20 11:21:53 +0800601 tm.getTetherableBluetoothRegexs().length != 0;
Chilund3358d82018-03-26 18:28:56 +0800602 if (!bluetoothAvailable) {
603 keys.add(KEY_ENABLE_BLUETOOTH_TETHERING);
604 }
Yuuki Habu557e4572020-02-05 16:24:52 +0900605
Xiao Madb7d7de2022-01-30 11:18:29 +0000606 final EthernetManager em =
607 context.getSystemService(EthernetManager.class);
608 final boolean ethernetAvailable = (em != null);
Yuuki Habu557e4572020-02-05 16:24:52 +0900609 if (!ethernetAvailable) {
610 keys.add(KEY_ENABLE_ETHERNET_TETHERING);
611 }
Chilund3358d82018-03-26 18:28:56 +0800612 return keys;
613 }
614 };
615
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800616 private static final class OnStartTetheringCallback extends
617 ConnectivityManager.OnStartTetheringCallback {
618 final WeakReference<TetherSettings> mTetherSettings;
619
620 OnStartTetheringCallback(TetherSettings settings) {
Fan Zhangdefb1182017-07-25 14:18:47 -0700621 mTetherSettings = new WeakReference<>(settings);
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800622 }
623
624 @Override
625 public void onTetheringStarted() {
626 update();
627 }
628
629 @Override
630 public void onTetheringFailed() {
631 update();
632 }
633
634 private void update() {
635 TetherSettings settings = mTetherSettings.get();
636 if (settings != null) {
Hugh Chena3a06612021-07-13 10:42:00 +0800637 settings.updateBluetoothAndEthernetState();
Jeremy Kleine3e7b952016-01-25 14:43:49 -0800638 }
639 }
640 }
Yuuki Habu557e4572020-02-05 16:24:52 +0900641
642 private final class TetheringEventCallback implements TetheringManager.TetheringEventCallback {
643 @Override
644 public void onTetheredInterfacesChanged(List<String> interfaces) {
Hugh Chena3a06612021-07-13 10:42:00 +0800645 Log.d(TAG, "onTetheredInterfacesChanged() interfaces : " + interfaces.toString());
646 String[] tethered = interfaces.toArray(new String[interfaces.size()]);
647 updateUsbState(tethered);
648 updateBluetoothAndEthernetState(tethered);
Yuuki Habu557e4572020-02-05 16:24:52 +0900649 }
650 }
651
Xiao Madb7d7de2022-01-30 11:18:29 +0000652 private final class EthernetListener implements EthernetManager.InterfaceStateListener {
653 public void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
654 @Role int role, @NonNull IpConfiguration configuration) {
655 if (state == EthernetManager.STATE_LINK_UP) {
656 mAvailableInterfaces.add(iface);
657 } else {
658 mAvailableInterfaces.remove(iface);
659 }
660 updateBluetoothAndEthernetState();
Yuuki Habu557e4572020-02-05 16:24:52 +0900661 }
662 }
Robert Greenwalt3901edb2010-01-26 10:22:37 -0800663}