1 /* 2 * Copyright (C) 2022 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 17 package com.android.settings.network.tether; 18 19 import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; 20 import static android.net.ConnectivityManager.TETHERING_USB; 21 import static android.net.TetheringManager.TETHERING_ETHERNET; 22 23 import static com.android.settings.wifi.WifiUtils.canShowWifiHotspot; 24 import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfUsbDataSignalingIsDisabled; 25 26 import android.app.Activity; 27 import android.app.settings.SettingsEnums; 28 import android.bluetooth.BluetoothAdapter; 29 import android.bluetooth.BluetoothPan; 30 import android.bluetooth.BluetoothProfile; 31 import android.content.BroadcastReceiver; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.IntentFilter; 35 import android.hardware.usb.UsbManager; 36 import android.net.ConnectivityManager; 37 import android.net.EthernetManager; 38 import android.net.IpConfiguration; 39 import android.net.TetheringManager; 40 import android.net.wifi.WifiManager; 41 import android.os.Bundle; 42 import android.os.Environment; 43 import android.os.Handler; 44 import android.os.UserHandle; 45 import android.os.UserManager; 46 import android.provider.SearchIndexableResource; 47 import android.text.TextUtils; 48 import android.util.Log; 49 50 import androidx.annotation.NonNull; 51 import androidx.annotation.VisibleForTesting; 52 import androidx.lifecycle.ViewModelProvider; 53 import androidx.preference.Preference; 54 import androidx.preference.TwoStatePreference; 55 56 import com.android.settings.R; 57 import com.android.settings.RestrictedSettingsFragment; 58 import com.android.settings.Utils; 59 import com.android.settings.datausage.DataSaverBackend; 60 import com.android.settings.search.BaseSearchIndexProvider; 61 import com.android.settings.wifi.tether.WifiTetherPreferenceController; 62 import com.android.settingslib.RestrictedLockUtils; 63 import com.android.settingslib.RestrictedSwitchPreference; 64 import com.android.settingslib.TetherUtil; 65 import com.android.settingslib.search.SearchIndexable; 66 67 import java.lang.ref.WeakReference; 68 import java.util.ArrayList; 69 import java.util.Arrays; 70 import java.util.HashSet; 71 import java.util.List; 72 import java.util.concurrent.atomic.AtomicReference; 73 74 /** 75 * Displays preferences for Tethering. 76 */ 77 @SearchIndexable 78 public class TetherSettings extends RestrictedSettingsFragment 79 implements DataSaverBackend.Listener { 80 81 @VisibleForTesting 82 static final String KEY_TETHER_PREFS_SCREEN = "tether_prefs_screen"; 83 @VisibleForTesting 84 static final String KEY_WIFI_TETHER = "wifi_tether"; 85 @VisibleForTesting 86 static final String KEY_USB_TETHER_SETTINGS = "usb_tether_settings"; 87 @VisibleForTesting 88 static final String KEY_ENABLE_BLUETOOTH_TETHERING = "enable_bluetooth_tethering"; 89 private static final String KEY_ENABLE_ETHERNET_TETHERING = "enable_ethernet_tethering"; 90 private static final String KEY_DATA_SAVER_FOOTER = "disabled_on_data_saver"; 91 @VisibleForTesting 92 static final String KEY_TETHER_PREFS_TOP_INTRO = "tether_prefs_top_intro"; 93 94 private static final String TAG = "TetheringSettings"; 95 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 96 97 @VisibleForTesting 98 RestrictedSwitchPreference mUsbTether; 99 @VisibleForTesting 100 TwoStatePreference mBluetoothTether; 101 @VisibleForTesting 102 TwoStatePreference mEthernetTether; 103 104 private BroadcastReceiver mTetherChangeReceiver; 105 private BroadcastReceiver mBluetoothStateReceiver; 106 107 private String[] mBluetoothRegexs; 108 private AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<>(); 109 110 private Handler mHandler = new Handler(); 111 private OnStartTetheringCallback mStartTetheringCallback; 112 private ConnectivityManager mCm; 113 private EthernetManager mEm; 114 private EthernetListener mEthernetListener; 115 private final HashSet<String> mAvailableInterfaces = new HashSet<>(); 116 117 @VisibleForTesting 118 WifiTetherPreferenceController mWifiTetherPreferenceController; 119 120 private boolean mUsbConnected; 121 private boolean mMassStorageActive; 122 123 private boolean mBluetoothEnableForTether; 124 125 private DataSaverBackend mDataSaverBackend; 126 private boolean mDataSaverEnabled; 127 @VisibleForTesting 128 Preference mDataSaverFooter; 129 130 @VisibleForTesting 131 String[] mUsbRegexs; 132 @VisibleForTesting 133 Context mContext; 134 @VisibleForTesting 135 TetheringManager mTm; 136 137 @Override getMetricsCategory()138 public int getMetricsCategory() { 139 return SettingsEnums.TETHER; 140 } 141 TetherSettings()142 public TetherSettings() { 143 super(UserManager.DISALLOW_CONFIG_TETHERING); 144 } 145 146 @Override onCreate(Bundle icicle)147 public void onCreate(Bundle icicle) { 148 super.onCreate(icicle); 149 // Even when the UI is restricted, addPreferencesFromResource cannot be omitted. 150 addPreferencesFromResource(R.xml.tether_prefs); 151 setIfOnlyAvailableForAdmins(true); 152 if (isUiRestricted()) { 153 return; 154 } 155 156 mContext = getContext(); 157 mDataSaverBackend = new DataSaverBackend(mContext); 158 mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled(); 159 mDataSaverFooter = findPreference(KEY_DATA_SAVER_FOOTER); 160 161 setupTetherPreference(); 162 setupViewModel(); 163 164 final Activity activity = getActivity(); 165 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 166 if (adapter != null) { 167 adapter.getProfileProxy(activity.getApplicationContext(), mProfileServiceListener, 168 BluetoothProfile.PAN); 169 } 170 if (mBluetoothStateReceiver == null) { 171 mBluetoothStateReceiver = new BluetoothStateReceiver(); 172 mContext.registerReceiver( 173 mBluetoothStateReceiver, 174 new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)); 175 } 176 177 setTopIntroPreferenceTitle(); 178 179 mDataSaverBackend.addListener(this); 180 181 mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 182 // Some devices do not have available EthernetManager. In that case getSystemService will 183 // return null. 184 mEm = mContext.getSystemService(EthernetManager.class); 185 186 mUsbRegexs = mTm.getTetherableUsbRegexs(); 187 mBluetoothRegexs = mTm.getTetherableBluetoothRegexs(); 188 189 final boolean usbAvailable = mUsbRegexs.length != 0; 190 final boolean bluetoothAvailable = adapter != null && mBluetoothRegexs.length != 0; 191 final boolean ethernetAvailable = (mEm != null); 192 193 if (!usbAvailable || Utils.isMonkeyRunning()) { 194 getPreferenceScreen().removePreference(mUsbTether); 195 } 196 197 mWifiTetherPreferenceController.displayPreference(getPreferenceScreen()); 198 199 if (!bluetoothAvailable) { 200 getPreferenceScreen().removePreference(mBluetoothTether); 201 } else { 202 BluetoothPan pan = mBluetoothPan.get(); 203 if (pan != null && pan.isTetheringOn()) { 204 mBluetoothTether.setChecked(true); 205 } else { 206 mBluetoothTether.setChecked(false); 207 } 208 } 209 if (!ethernetAvailable) getPreferenceScreen().removePreference(mEthernetTether); 210 // Set initial state based on Data Saver mode. 211 onDataSaverChanged(mDataSaverBackend.isDataSaverEnabled()); 212 } 213 214 @VisibleForTesting setupViewModel()215 void setupViewModel() { 216 TetheringManagerModel model = new ViewModelProvider(this).get(TetheringManagerModel.class); 217 mWifiTetherPreferenceController = 218 new WifiTetherPreferenceController(getContext(), getSettingsLifecycle(), model); 219 mTm = model.getTetheringManager(); 220 model.getTetheredInterfaces().observe(this, this::onTetheredInterfacesChanged); 221 } 222 223 @Override onDestroy()224 public void onDestroy() { 225 if (isUiRestricted()) { 226 super.onDestroy(); 227 return; 228 } 229 230 mDataSaverBackend.remListener(this); 231 232 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 233 BluetoothProfile profile = mBluetoothPan.getAndSet(null); 234 if (profile != null && adapter != null) { 235 adapter.closeProfileProxy(BluetoothProfile.PAN, profile); 236 } 237 if (mBluetoothStateReceiver != null) { 238 mContext.unregisterReceiver(mBluetoothStateReceiver); 239 mBluetoothStateReceiver = null; 240 } 241 242 super.onDestroy(); 243 } 244 245 @VisibleForTesting setupTetherPreference()246 void setupTetherPreference() { 247 mUsbTether = (RestrictedSwitchPreference) findPreference(KEY_USB_TETHER_SETTINGS); 248 mBluetoothTether = (TwoStatePreference) findPreference(KEY_ENABLE_BLUETOOTH_TETHERING); 249 mEthernetTether = (TwoStatePreference) findPreference(KEY_ENABLE_ETHERNET_TETHERING); 250 } 251 252 @Override onDataSaverChanged(boolean isDataSaving)253 public void onDataSaverChanged(boolean isDataSaving) { 254 mDataSaverEnabled = isDataSaving; 255 mWifiTetherPreferenceController.setDataSaverEnabled(mDataSaverEnabled); 256 mUsbTether.setEnabled(!mDataSaverEnabled); 257 mBluetoothTether.setEnabled(!mDataSaverEnabled); 258 mEthernetTether.setEnabled(!mDataSaverEnabled); 259 mDataSaverFooter.setVisible(mDataSaverEnabled); 260 } 261 262 @Override onAllowlistStatusChanged(int uid, boolean isAllowlisted)263 public void onAllowlistStatusChanged(int uid, boolean isAllowlisted) { 264 } 265 266 @Override onDenylistStatusChanged(int uid, boolean isDenylisted)267 public void onDenylistStatusChanged(int uid, boolean isDenylisted) { 268 } 269 270 @VisibleForTesting setTopIntroPreferenceTitle()271 void setTopIntroPreferenceTitle() { 272 final Preference topIntroPreference = findPreference(KEY_TETHER_PREFS_TOP_INTRO); 273 final WifiManager wifiManager = mContext.getSystemService(WifiManager.class); 274 if (wifiManager.isStaApConcurrencySupported()) { 275 topIntroPreference.setTitle(R.string.tethering_footer_info_sta_ap_concurrency); 276 } else { 277 topIntroPreference.setTitle(R.string.tethering_footer_info); 278 } 279 } 280 281 private class BluetoothStateReceiver extends BroadcastReceiver { 282 @Override onReceive(Context context, Intent intent)283 public void onReceive(Context context, Intent intent) { 284 final String action = intent.getAction(); 285 Log.i(TAG, "onReceive: action: " + action); 286 287 if (TextUtils.equals(action, BluetoothAdapter.ACTION_STATE_CHANGED)) { 288 final int state = 289 intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); 290 Log.i(TAG, "onReceive: state: " + BluetoothAdapter.nameForState(state)); 291 final BluetoothProfile profile = mBluetoothPan.get(); 292 switch(state) { 293 case BluetoothAdapter.STATE_ON: 294 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 295 if (profile == null && adapter != null) { 296 adapter.getProfileProxy(mContext, mProfileServiceListener, 297 BluetoothProfile.PAN); 298 } 299 break; 300 } 301 } 302 } 303 } 304 305 private class TetherChangeReceiver extends BroadcastReceiver { 306 @Override onReceive(Context content, Intent intent)307 public void onReceive(Context content, Intent intent) { 308 String action = intent.getAction(); 309 if (DEBUG) { 310 Log.d(TAG, "onReceive() action : " + action); 311 } 312 // TODO(b/194961339): Stop using ACTION_TETHER_STATE_CHANGED and use 313 // mTetheringEventCallback instead. 314 if (action.equals(TetheringManager.ACTION_TETHER_STATE_CHANGED)) { 315 // TODO - this should understand the interface types 316 ArrayList<String> available = intent.getStringArrayListExtra( 317 TetheringManager.EXTRA_AVAILABLE_TETHER); 318 ArrayList<String> active = intent.getStringArrayListExtra( 319 TetheringManager.EXTRA_ACTIVE_TETHER); 320 updateBluetoothState(); 321 updateEthernetState(available.toArray(new String[available.size()]), 322 active.toArray(new String[active.size()])); 323 } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) { 324 mMassStorageActive = true; 325 updateBluetoothAndEthernetState(); 326 updateUsbPreference(); 327 } else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) { 328 mMassStorageActive = false; 329 updateBluetoothAndEthernetState(); 330 updateUsbPreference(); 331 } else if (action.equals(UsbManager.ACTION_USB_STATE)) { 332 mUsbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); 333 updateBluetoothAndEthernetState(); 334 updateUsbPreference(); 335 } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { 336 if (mBluetoothEnableForTether) { 337 switch (intent 338 .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) { 339 case BluetoothAdapter.STATE_ON: 340 startTethering(TETHERING_BLUETOOTH); 341 mBluetoothEnableForTether = false; 342 break; 343 344 case BluetoothAdapter.STATE_OFF: 345 case BluetoothAdapter.ERROR: 346 mBluetoothEnableForTether = false; 347 break; 348 349 default: 350 // ignore transition states 351 } 352 } 353 updateBluetoothAndEthernetState(); 354 } else if (action.equals(BluetoothPan.ACTION_TETHERING_STATE_CHANGED)) { 355 updateBluetoothAndEthernetState(); 356 } 357 } 358 } 359 360 @Override onStart()361 public void onStart() { 362 super.onStart(); 363 364 if (isUiRestricted()) { 365 if (!isUiRestrictedByOnlyAdmin()) { 366 getEmptyTextView().setText( 367 com.android.settingslib.R.string.tethering_settings_not_available); 368 } 369 getPreferenceScreen().removeAll(); 370 return; 371 } 372 373 374 mStartTetheringCallback = new OnStartTetheringCallback(this); 375 376 mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState()); 377 registerReceiver(); 378 379 mEthernetListener = new EthernetListener(this); 380 if (mEm != null) { 381 mEm.addInterfaceStateListener(mContext.getApplicationContext().getMainExecutor(), 382 mEthernetListener); 383 } 384 385 updateUsbState(); 386 updateBluetoothAndEthernetState(); 387 } 388 389 @Override onStop()390 public void onStop() { 391 super.onStop(); 392 393 if (isUiRestricted()) { 394 return; 395 } 396 getActivity().unregisterReceiver(mTetherChangeReceiver); 397 if (mEm != null) { 398 mEm.removeInterfaceStateListener(mEthernetListener); 399 } 400 mTetherChangeReceiver = null; 401 mStartTetheringCallback = null; 402 } 403 404 @VisibleForTesting registerReceiver()405 void registerReceiver() { 406 final Activity activity = getActivity(); 407 408 mTetherChangeReceiver = new TetherChangeReceiver(); 409 IntentFilter filter = new IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED); 410 final Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter); 411 412 filter = new IntentFilter(); 413 filter.addAction(UsbManager.ACTION_USB_STATE); 414 activity.registerReceiver(mTetherChangeReceiver, filter); 415 416 filter = new IntentFilter(); 417 filter.addAction(Intent.ACTION_MEDIA_SHARED); 418 filter.addAction(Intent.ACTION_MEDIA_UNSHARED); 419 filter.addDataScheme("file"); 420 activity.registerReceiver(mTetherChangeReceiver, filter); 421 422 filter = new IntentFilter(); 423 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 424 filter.addAction(BluetoothPan.ACTION_TETHERING_STATE_CHANGED); 425 activity.registerReceiver(mTetherChangeReceiver, filter); 426 427 if (intent != null) mTetherChangeReceiver.onReceive(activity, intent); 428 } 429 430 // TODO(b/194961339): Separate the updateBluetoothAndEthernetState() to two methods, 431 // updateBluetoothAndEthernetState() and updateBluetoothAndEthernetPreference(). 432 // Because we should update the state when only receiving tethering 433 // state changes and update preference when usb or media share changed. updateBluetoothAndEthernetState()434 private void updateBluetoothAndEthernetState() { 435 String[] tethered = mTm.getTetheredIfaces(); 436 updateBluetoothAndEthernetState(tethered); 437 } 438 updateBluetoothAndEthernetState(String[] tethered)439 private void updateBluetoothAndEthernetState(String[] tethered) { 440 String[] available = mTm.getTetherableIfaces(); 441 updateBluetoothState(); 442 updateEthernetState(available, tethered); 443 } 444 updateUsbState()445 private void updateUsbState() { 446 String[] tethered = mTm.getTetheredIfaces(); 447 updateUsbState(tethered); 448 } 449 450 @VisibleForTesting updateUsbState(String[] tethered)451 void updateUsbState(String[] tethered) { 452 boolean usbTethered = false; 453 for (String s : tethered) { 454 for (String regex : mUsbRegexs) { 455 if (s.matches(regex)) usbTethered = true; 456 } 457 } 458 if (DEBUG) { 459 Log.d(TAG, "updateUsbState() mUsbConnected : " + mUsbConnected 460 + ", mMassStorageActive : " + mMassStorageActive 461 + ", usbTethered : " + usbTethered); 462 } 463 if (usbTethered) { 464 mUsbTether.setEnabled(!mDataSaverEnabled); 465 mUsbTether.setChecked(true); 466 final RestrictedLockUtils.EnforcedAdmin enforcedAdmin = 467 checkIfUsbDataSignalingIsDisabled(mContext, UserHandle.myUserId()); 468 if (enforcedAdmin != null) { 469 mUsbTether.setDisabledByAdmin(enforcedAdmin); 470 } 471 } else { 472 mUsbTether.setChecked(false); 473 updateUsbPreference(); 474 } 475 } 476 updateUsbPreference()477 private void updateUsbPreference() { 478 boolean usbAvailable = mUsbConnected && !mMassStorageActive; 479 final RestrictedLockUtils.EnforcedAdmin enforcedAdmin = 480 checkIfUsbDataSignalingIsDisabled(mContext, UserHandle.myUserId()); 481 482 if (enforcedAdmin != null) { 483 mUsbTether.setDisabledByAdmin(enforcedAdmin); 484 } else if (usbAvailable) { 485 mUsbTether.setEnabled(!mDataSaverEnabled); 486 } else { 487 mUsbTether.setEnabled(false); 488 } 489 } 490 491 @VisibleForTesting getBluetoothState()492 int getBluetoothState() { 493 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 494 if (adapter == null) { 495 return BluetoothAdapter.ERROR; 496 } 497 return adapter.getState(); 498 } 499 500 @VisibleForTesting isBluetoothTetheringOn()501 boolean isBluetoothTetheringOn() { 502 final BluetoothPan bluetoothPan = mBluetoothPan.get(); 503 return bluetoothPan != null && bluetoothPan.isTetheringOn(); 504 } 505 updateBluetoothState()506 private void updateBluetoothState() { 507 final int btState = getBluetoothState(); 508 if (DEBUG) { 509 Log.d(TAG, "updateBluetoothState() btState : " + btState); 510 } 511 if (btState == BluetoothAdapter.ERROR) { 512 Log.w(TAG, "updateBluetoothState() Bluetooth state is error!"); 513 return; 514 } 515 516 if (btState == BluetoothAdapter.STATE_TURNING_OFF) { 517 mBluetoothTether.setEnabled(false); 518 } else if (btState == BluetoothAdapter.STATE_TURNING_ON) { 519 mBluetoothTether.setEnabled(false); 520 } else { 521 if (btState == BluetoothAdapter.STATE_ON && isBluetoothTetheringOn()) { 522 mBluetoothTether.setChecked(true); 523 mBluetoothTether.setEnabled(!mDataSaverEnabled); 524 } else { 525 mBluetoothTether.setEnabled(!mDataSaverEnabled); 526 mBluetoothTether.setChecked(false); 527 } 528 } 529 } 530 531 @VisibleForTesting updateEthernetState(String[] available, String[] tethered)532 void updateEthernetState(String[] available, String[] tethered) { 533 boolean isAvailable = false; 534 boolean isTethered = false; 535 536 for (String s : available) { 537 if (mAvailableInterfaces.contains(s)) isAvailable = true; 538 } 539 540 for (String s : tethered) { 541 if (mAvailableInterfaces.contains(s)) isTethered = true; 542 } 543 544 if (DEBUG) { 545 Log.d(TAG, "updateEthernetState() isAvailable : " + isAvailable 546 + ", isTethered : " + isTethered); 547 } 548 549 if (isTethered) { 550 mEthernetTether.setEnabled(!mDataSaverEnabled); 551 mEthernetTether.setChecked(true); 552 } else if (mAvailableInterfaces.size() > 0) { 553 mEthernetTether.setEnabled(!mDataSaverEnabled); 554 mEthernetTether.setChecked(false); 555 } else { 556 mEthernetTether.setEnabled(false); 557 mEthernetTether.setChecked(false); 558 } 559 } 560 startTethering(int choice)561 private void startTethering(int choice) { 562 if (choice == TETHERING_BLUETOOTH) { 563 // Turn on Bluetooth first. 564 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 565 if (adapter.getState() == BluetoothAdapter.STATE_OFF) { 566 mBluetoothEnableForTether = true; 567 adapter.enable(); 568 mBluetoothTether.setEnabled(false); 569 return; 570 } 571 } 572 573 mCm.startTethering(choice, true, mStartTetheringCallback, mHandler); 574 } 575 576 @Override onPreferenceTreeClick(Preference preference)577 public boolean onPreferenceTreeClick(Preference preference) { 578 if (preference == mUsbTether) { 579 if (mUsbTether.isChecked()) { 580 startTethering(TETHERING_USB); 581 } else { 582 mCm.stopTethering(TETHERING_USB); 583 } 584 } else if (preference == mBluetoothTether) { 585 if (mBluetoothTether.isChecked()) { 586 startTethering(TETHERING_BLUETOOTH); 587 } else { 588 mCm.stopTethering(TETHERING_BLUETOOTH); 589 } 590 } else if (preference == mEthernetTether) { 591 if (mEthernetTether.isChecked()) { 592 startTethering(TETHERING_ETHERNET); 593 } else { 594 mCm.stopTethering(TETHERING_ETHERNET); 595 } 596 } 597 598 return super.onPreferenceTreeClick(preference); 599 } 600 601 @Override getHelpResource()602 public int getHelpResource() { 603 return R.string.help_url_tether; 604 } 605 606 private BluetoothProfile.ServiceListener mProfileServiceListener = 607 new BluetoothProfile.ServiceListener() { 608 @Override 609 public void onServiceConnected(int profile, BluetoothProfile proxy) { 610 if (mBluetoothPan.get() == null) { 611 mBluetoothPan.set((BluetoothPan) proxy); 612 updateBluetoothState(); 613 } 614 } 615 616 @Override 617 public void onServiceDisconnected(int profile) { /* Do nothing */ } 618 }; 619 620 public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 621 new BaseSearchIndexProvider() { 622 @Override 623 public List<SearchIndexableResource> getXmlResourcesToIndex( 624 Context context, boolean enabled) { 625 final SearchIndexableResource sir = new SearchIndexableResource(context); 626 sir.xmlResId = R.xml.tether_prefs; 627 return Arrays.asList(sir); 628 } 629 630 @Override 631 public List<String> getNonIndexableKeys(Context context) { 632 final List<String> keys = super.getNonIndexableKeys(context); 633 final TetheringManager tm = 634 context.getSystemService(TetheringManager.class); 635 636 if (!TetherUtil.isTetherAvailable(context)) { 637 keys.add(KEY_TETHER_PREFS_SCREEN); 638 } 639 640 if (!canShowWifiHotspot(context) || !TetherUtil.isTetherAvailable(context)) { 641 keys.add(KEY_WIFI_TETHER); 642 } 643 644 final boolean usbAvailable = 645 tm.getTetherableUsbRegexs().length != 0; 646 if (!usbAvailable || Utils.isMonkeyRunning()) { 647 keys.add(KEY_USB_TETHER_SETTINGS); 648 } 649 650 final boolean bluetoothAvailable = 651 tm.getTetherableBluetoothRegexs().length != 0; 652 if (!bluetoothAvailable) { 653 keys.add(KEY_ENABLE_BLUETOOTH_TETHERING); 654 } 655 656 final EthernetManager em = 657 context.getSystemService(EthernetManager.class); 658 final boolean ethernetAvailable = (em != null); 659 if (!ethernetAvailable) { 660 keys.add(KEY_ENABLE_ETHERNET_TETHERING); 661 } 662 return keys; 663 } 664 }; 665 666 private static final class OnStartTetheringCallback extends 667 ConnectivityManager.OnStartTetheringCallback { 668 final WeakReference<TetherSettings> mTetherSettings; 669 OnStartTetheringCallback(TetherSettings settings)670 OnStartTetheringCallback(TetherSettings settings) { 671 mTetherSettings = new WeakReference<>(settings); 672 } 673 674 @Override onTetheringStarted()675 public void onTetheringStarted() { 676 update(); 677 } 678 679 @Override onTetheringFailed()680 public void onTetheringFailed() { 681 update(); 682 } 683 update()684 private void update() { 685 TetherSettings settings = mTetherSettings.get(); 686 if (settings != null) { 687 settings.updateBluetoothAndEthernetState(); 688 } 689 } 690 } 691 onTetheredInterfacesChanged(List<String> interfaces)692 protected void onTetheredInterfacesChanged(List<String> interfaces) { 693 Log.d(TAG, "onTetheredInterfacesChanged() interfaces : " + interfaces.toString()); 694 final String[] tethered = interfaces.toArray(new String[interfaces.size()]); 695 updateUsbState(tethered); 696 updateBluetoothAndEthernetState(tethered); 697 } 698 699 private static final class EthernetListener implements EthernetManager.InterfaceStateListener { 700 final WeakReference<TetherSettings> mTetherSettings; 701 EthernetListener(TetherSettings settings)702 EthernetListener(TetherSettings settings) { 703 mTetherSettings = new WeakReference<>(settings); 704 } 705 706 @Override onInterfaceStateChanged(@onNull String iface, int state, int role, @NonNull IpConfiguration configuration)707 public void onInterfaceStateChanged(@NonNull String iface, int state, int role, 708 @NonNull IpConfiguration configuration) { 709 final TetherSettings tetherSettings = mTetherSettings.get(); 710 if (tetherSettings == null) { 711 return; 712 } 713 tetherSettings.onInterfaceStateChanged(iface, state, role, configuration); 714 } 715 } 716 onInterfaceStateChanged(@onNull String iface, int state, int role, @NonNull IpConfiguration configuration)717 void onInterfaceStateChanged(@NonNull String iface, int state, int role, 718 @NonNull IpConfiguration configuration) { 719 if (state == EthernetManager.STATE_LINK_UP) { 720 mAvailableInterfaces.add(iface); 721 } else { 722 mAvailableInterfaces.remove(iface); 723 } 724 updateBluetoothAndEthernetState(); 725 } 726 } 727