diff --git a/res/values/strings.xml b/res/values/strings.xml
index eeb9d044b9b..f5b19318e04 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3750,6 +3750,23 @@
"Can\u2019t tether or use portable hotspots while Data Saver is on"
+
+ Hotspot only
+
+ USB only
+
+ Bluetooth only
+
+ Hotspot, USB
+
+ Hotspot, Bluetooth
+
+ USB, Bluetooth
+
+ Hotspot, USB, Bluetooth
+
+ Not sharing internet with other devices
+
Only share internet via USB
diff --git a/src/com/android/settings/network/AllInOneTetherPreferenceController.java b/src/com/android/settings/network/AllInOneTetherPreferenceController.java
index b237c777310..85cfb8bc931 100644
--- a/src/com/android/settings/network/AllInOneTetherPreferenceController.java
+++ b/src/com/android/settings/network/AllInOneTetherPreferenceController.java
@@ -17,12 +17,16 @@ package com.android.settings.network;
import static android.os.UserManager.DISALLOW_CONFIG_TETHERING;
+import static com.android.settings.network.TetherEnabler.BLUETOOTH_TETHER_KEY;
+import static com.android.settings.network.TetherEnabler.KEY_ENABLE_WIFI_TETHERING;
+import static com.android.settings.network.TetherEnabler.USB_TETHER_KEY;
import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfRestrictionEnforced;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.content.SharedPreferences;
import android.os.UserHandle;
import android.util.FeatureFlagUtils;
import android.util.Log;
@@ -34,6 +38,7 @@ import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.PreferenceScreen;
+import com.android.settings.R;
import com.android.settings.TetherSettings;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.FeatureFlags;
@@ -48,12 +53,22 @@ import java.util.concurrent.atomic.AtomicReference;
* preference. It updates the preference summary text based on tethering state.
*/
public class AllInOneTetherPreferenceController extends BasePreferenceController implements
- LifecycleObserver {
+ LifecycleObserver, TetherEnabler.OnTetherStateUpdateListener {
private static final String TAG = "AllInOneTetherPreferenceController";
+ private static final byte HOTSPOT_ONLY = 1;
+ private static final byte USB_ONLY = 1 << 1;
+ private static final byte BLUETOOTH_ONLY = 1 << 2;
+ private static final byte HOTSPOT_AND_USB = HOTSPOT_ONLY | USB_ONLY;
+ private static final byte HOTSPOT_AND_BLUETOOTH = HOTSPOT_ONLY | BLUETOOTH_ONLY;
+ private static final byte USB_AND_BLUETOOTH = USB_ONLY | BLUETOOTH_ONLY;
+ private static final byte HOTSPOT_AND_USB_AND_BLUETOOTH =
+ HOTSPOT_ONLY | USB_ONLY | BLUETOOTH_ONLY;
+
private final boolean mAdminDisallowedTetherConfig;
private final AtomicReference mBluetoothPan;
private final BluetoothAdapter mBluetoothAdapter;
+ private final SharedPreferences mTetherEnablerSharedPreferences;
@VisibleForTesting
final BluetoothProfile.ServiceListener mBtProfileServiceListener =
new BluetoothProfile.ServiceListener() {
@@ -69,6 +84,7 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
};
private MasterSwitchPreference mPreference;
+ private TetherEnabler mTetherEnabler;
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
AllInOneTetherPreferenceController() {
@@ -76,6 +92,7 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
mAdminDisallowedTetherConfig = false;
mBluetoothPan = new AtomicReference<>();
mBluetoothAdapter = null;
+ mTetherEnablerSharedPreferences = null;
}
public AllInOneTetherPreferenceController(Context context, String key) {
@@ -84,6 +101,8 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
mAdminDisallowedTetherConfig = checkIfRestrictionEnforced(
context, DISALLOW_CONFIG_TETHERING, UserHandle.myUserId()) != null;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ mTetherEnablerSharedPreferences =
+ context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE);
}
@Override
@@ -109,11 +128,38 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
@Override
public CharSequence getSummary() {
if (mPreference != null && mPreference.isChecked()) {
- // TODO(b/149256198) update summary accordingly.
- return "Tethering";
+ int chosenType = 0;
+ chosenType |= mTetherEnablerSharedPreferences
+ .getBoolean(KEY_ENABLE_WIFI_TETHERING, true) ? HOTSPOT_ONLY : 0;
+ chosenType |= mTetherEnablerSharedPreferences.getBoolean(USB_TETHER_KEY, false)
+ ? USB_ONLY : 0;
+ chosenType |= mTetherEnablerSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)
+ ? BLUETOOTH_ONLY : 0;
+ switch (chosenType) {
+ case HOTSPOT_ONLY:
+ return mContext.getString(R.string.tether_settings_summary_hotspot_only);
+ case USB_ONLY:
+ return mContext.getString(R.string.tether_settings_summary_usb_tethering_only);
+ case BLUETOOTH_ONLY:
+ return mContext.getString(
+ R.string.tether_settings_summary_bluetooth_tethering_only);
+ case HOTSPOT_AND_USB:
+ return mContext.getString(R.string.tether_settings_summary_hotspot_and_usb);
+ case HOTSPOT_AND_BLUETOOTH:
+ return mContext.getString(
+ R.string.tether_settings_summary_hotspot_and_bluetooth);
+ case USB_AND_BLUETOOTH:
+ return mContext.getString(R.string.tether_settings_summary_usb_and_bluetooth);
+ case HOTSPOT_AND_USB_AND_BLUETOOTH:
+ return mContext.getString(
+ R.string.tether_settings_summary_hotspot_and_usb_and_bluetooth);
+ default:
+ Log.e(TAG, "None of the tether interfaces is chosen");
+ return mContext.getString(R.string.summary_placeholder);
+ }
}
- return "Not sharing internet with other devices";
+ return mContext.getString(R.string.tether_settings_summary_off);
}
@OnLifecycleEvent(Event.ON_CREATE)
@@ -125,6 +171,20 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
}
}
+ @OnLifecycleEvent(Event.ON_RESUME)
+ public void onResume() {
+ if (mTetherEnabler != null) {
+ mTetherEnabler.setListener(this);
+ }
+ }
+
+ @OnLifecycleEvent(Event.ON_PAUSE)
+ public void onPause() {
+ if (mTetherEnabler != null) {
+ mTetherEnabler.setListener(null);
+ }
+ }
+
@OnLifecycleEvent(Event.ON_DESTROY)
public void onDestroy() {
final BluetoothProfile profile = mBluetoothPan.getAndSet(null);
@@ -133,19 +193,20 @@ public class AllInOneTetherPreferenceController extends BasePreferenceController
}
}
- void init(Lifecycle lifecycle) {
- lifecycle.addObserver(this);
- }
-
void initEnabler(Lifecycle lifecycle) {
if (mPreference != null) {
- TetherEnabler tetherEnabler = new TetherEnabler(
+ mTetherEnabler = new TetherEnabler(
mContext, new MasterSwitchController(mPreference), mBluetoothPan);
if (lifecycle != null) {
- lifecycle.addObserver(tetherEnabler);
+ lifecycle.addObserver(mTetherEnabler);
}
} else {
Log.e(TAG, "TetherEnabler is not initialized");
}
}
+
+ @Override
+ public void onTetherStateUpdated(boolean isTethering) {
+ updateState(mPreference);
+ }
}
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index b1685fd3fcb..ad3df333bfa 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -66,7 +66,7 @@ public class NetworkDashboardFragment extends DashboardFragment implements
use(MultiNetworkHeaderController.class).init(getSettingsLifecycle());
use(AirplaneModePreferenceController.class).setFragment(this);
- use(AllInOneTetherPreferenceController.class).init(getSettingsLifecycle());
+ getSettingsLifecycle().addObserver(use(AllInOneTetherPreferenceController.class));
}
@Override
diff --git a/src/com/android/settings/network/TetherEnabler.java b/src/com/android/settings/network/TetherEnabler.java
index ffb0ef25d97..e17dcd11cbb 100644
--- a/src/com/android/settings/network/TetherEnabler.java
+++ b/src/com/android/settings/network/TetherEnabler.java
@@ -61,6 +61,20 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
DataSaverBackend.Listener, LifecycleObserver,
SharedPreferences.OnSharedPreferenceChangeListener {
+ private OnTetherStateUpdateListener mListener;
+
+ /**
+ * Interface definition for a callback to be invoked when the tethering has been updated.
+ */
+ public interface OnTetherStateUpdateListener {
+ /**
+ * Called when the tethering state has changed.
+ *
+ * @param isTethering The new tethering state.
+ */
+ void onTetherStateUpdated(boolean isTethering);
+ }
+
private static final String TAG = "TetherEnabler";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -135,6 +149,10 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
mContext.unregisterReceiver(mTetherChangeReceiver);
}
+ public void setListener(@Nullable OnTetherStateUpdateListener listener) {
+ mListener = listener;
+ }
+
@VisibleForTesting
void updateState(@Nullable String[] tethered) {
boolean isTethering = tethered == null ? isTethering() : isTethering(tethered);
@@ -143,6 +161,9 @@ public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListe
}
setSwitchCheckedInternal(isTethering);
mSwitchWidgetController.setEnabled(!mDataSaverEnabled);
+ if (mListener != null) {
+ mListener.onTetherStateUpdated(isTethering);
+ }
}
private void setSwitchCheckedInternal(boolean checked) {
diff --git a/tests/robotests/src/com/android/settings/network/AllInOneTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/AllInOneTetherPreferenceControllerTest.java
index 4fbc4736adc..c74e669f009 100644
--- a/tests/robotests/src/com/android/settings/network/AllInOneTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/AllInOneTetherPreferenceControllerTest.java
@@ -26,6 +26,7 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.content.SharedPreferences;
import com.android.settings.widget.MasterSwitchPreference;
@@ -48,6 +49,8 @@ public class AllInOneTetherPreferenceControllerTest {
private BluetoothAdapter mBluetoothAdapter;
@Mock
private MasterSwitchPreference mPreference;
+ @Mock
+ private SharedPreferences mSharedPreferences;
private AllInOneTetherPreferenceController mController;
@@ -58,10 +61,12 @@ public class AllInOneTetherPreferenceControllerTest {
ReflectionHelpers.setField(mController, "mContext", mContext);
ReflectionHelpers.setField(mController, "mBluetoothAdapter", mBluetoothAdapter);
ReflectionHelpers.setField(mController, "mPreference", mPreference);
+ ReflectionHelpers
+ .setField(mController, "mTetherEnablerSharedPreferences", mSharedPreferences);
}
@Test
- public void lifeCycle_onCreate_shouldInitBluetoothPan() {
+ public void onCreate_shouldInitBluetoothPan() {
when(mBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_ON);
mController.onCreate();
@@ -71,7 +76,7 @@ public class AllInOneTetherPreferenceControllerTest {
}
@Test
- public void lifeCycle_onCreate_shouldNotInitBluetoothPanWhenBluetoothOff() {
+ public void onCreate_shouldNotInitBluetoothPanWhenBluetoothOff() {
when(mBluetoothAdapter.getState()).thenReturn(BluetoothAdapter.STATE_OFF);
mController.onCreate();