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