From c689d136c1890b307e3535ce25cf76820f5c5895 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Thu, 9 Feb 2017 18:04:00 -0800 Subject: [PATCH] Add hotspot summary text Bug: 34974598 Test: RunSettingsLibRoboTests Change-Id: If5d17bf458f980b4f3a8fdeb4718bbf5d2993a21 --- res/values/strings.xml | 6 + .../network/TetherPreferenceController.java | 107 +++++++++++++++- .../TetherPreferenceControllerTest.java | 117 ++++++++++++++++++ 3 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 9c3a8106e7b..2494e3a0171 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2941,6 +2941,12 @@ Tethering Hotspot & Tethering + + Hotspot on, tethering + + Hotspot on + + Tethering "Can\u2019t tether or use portable hotspots while Data Saver is on" diff --git a/src/com/android/settings/network/TetherPreferenceController.java b/src/com/android/settings/network/TetherPreferenceController.java index e24c873b10b..236fa96a282 100644 --- a/src/com/android/settings/network/TetherPreferenceController.java +++ b/src/com/android/settings/network/TetherPreferenceController.java @@ -15,17 +15,23 @@ */ package com.android.settings.network; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothPan; +import android.bluetooth.BluetoothProfile; import android.content.Context; import android.net.ConnectivityManager; import android.os.UserHandle; import android.os.UserManager; +import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; +import com.android.settings.R; import com.android.settings.TetherSettings; import com.android.settings.core.PreferenceController; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import static android.os.UserManager.DISALLOW_CONFIG_TETHERING; import static com.android.settingslib.RestrictedLockUtils.checkIfRestrictionEnforced; @@ -36,28 +42,60 @@ public class TetherPreferenceController extends PreferenceController { private static final String KEY_TETHER_SETTINGS = "tether_settings"; private final boolean mAdminDisallowedTetherConfig; + private final AtomicReference mBluetoothPan; private final ConnectivityManager mConnectivityManager; + private final BluetoothAdapter mBluetoothAdapter; private final UserManager mUserManager; + private final BluetoothProfile.ServiceListener mBtProfileServiceListener = + new android.bluetooth.BluetoothProfile.ServiceListener() { + public void onServiceConnected(int profile, BluetoothProfile proxy) { + mBluetoothPan.set((BluetoothPan) proxy); + updateSummary(); + } + + public void onServiceDisconnected(int profile) { + mBluetoothPan.set(null); + } + }; + + private Preference mPreference; + + @VisibleForTesting(otherwise = VisibleForTesting.NONE) + TetherPreferenceController() { + super(null); + mAdminDisallowedTetherConfig = false; + mBluetoothPan = null; + mConnectivityManager = null; + mBluetoothAdapter = null; + mUserManager = null; + } + public TetherPreferenceController(Context context) { super(context); + mBluetoothPan = new AtomicReference<>(); mAdminDisallowedTetherConfig = checkIfRestrictionEnforced( context, DISALLOW_CONFIG_TETHERING, UserHandle.myUserId()) != null; mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (mBluetoothAdapter != null) { + mBluetoothAdapter.getProfileProxy(context, mBtProfileServiceListener, + BluetoothProfile.PAN); + } } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); - final Preference preference = screen.findPreference(KEY_TETHER_SETTINGS); - if (preference != null && !mAdminDisallowedTetherConfig) { - preference.setTitle( + mPreference = screen.findPreference(KEY_TETHER_SETTINGS); + if (mPreference != null && !mAdminDisallowedTetherConfig) { + mPreference.setTitle( com.android.settingslib.Utils.getTetheringLabel(mConnectivityManager)); // Grey out if provisioning is not available. - preference.setEnabled(!TetherSettings.isProvisioningNeededButUnavailable(mContext)); + mPreference.setEnabled(!TetherSettings.isProvisioningNeededButUnavailable(mContext)); } } @@ -70,6 +108,11 @@ public class TetherPreferenceController extends PreferenceController { return !isBlocked; } + @Override + public void updateState(Preference preference) { + updateSummary(); + } + @Override public void updateNonIndexableKeys(List keys) { if (!mUserManager.isAdminUser() || !mConnectivityManager.isTetheringSupported()) { @@ -81,4 +124,60 @@ public class TetherPreferenceController extends PreferenceController { public String getPreferenceKey() { return KEY_TETHER_SETTINGS; } + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + void updateSummary() { + if (mPreference == null) { + // Preference is not ready yet. + return; + } + String[] allTethered = mConnectivityManager.getTetheredIfaces(); + String[] wifiTetherRegex = mConnectivityManager.getTetherableWifiRegexs(); + String[] bluetoothRegex = mConnectivityManager.getTetherableBluetoothRegexs(); + + boolean hotSpotOn = false; + boolean tetherOn = false; + if (allTethered != null) { + if (wifiTetherRegex != null) { + for (String tethered : allTethered) { + for (String regex : wifiTetherRegex) { + if (tethered.matches(regex)) { + hotSpotOn = true; + break; + } + } + } + } + if (allTethered.length > 1) { + // We have more than 1 tethered connection + tetherOn = true; + } else if (allTethered.length == 1) { + // We have more than 1 tethered, it's either wifiTether (hotspot), or other type of + // tether. + tetherOn = !hotSpotOn; + } else { + // No tethered connection. + tetherOn = false; + } + } + if (!tetherOn + && bluetoothRegex != null && bluetoothRegex.length > 0 + && mBluetoothAdapter != null + && mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) { + // Check bluetooth state. It's not included in mConnectivityManager.getTetheredIfaces. + final BluetoothPan pan = mBluetoothPan.get(); + tetherOn = pan != null && pan.isTetheringOn(); + } + if (!hotSpotOn && !tetherOn) { + // Both off + mPreference.setSummary(R.string.switch_off_text); + } else if (hotSpotOn && tetherOn) { + // Both on + mPreference.setSummary(R.string.tether_settings_summary_hotspot_on_tether_on); + } else if (hotSpotOn) { + mPreference.setSummary(R.string.tether_settings_summary_hotspot_on_tether_off); + } else { + mPreference.setSummary(R.string.tether_settings_summary_hotspot_off_tether_on); + } + } } diff --git a/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java new file mode 100644 index 00000000000..3d6a2335172 --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/TetherPreferenceControllerTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.network; + + +import android.bluetooth.BluetoothAdapter; +import android.content.Context; +import android.net.ConnectivityManager; +import android.os.UserManager; +import android.support.v7.preference.Preference; + +import com.android.settings.R; +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.util.ReflectionHelpers; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class TetherPreferenceControllerTest { + + @Mock + private Context mContext; + @Mock + private ConnectivityManager mConnectivityManager; + @Mock + private BluetoothAdapter mBluetoothAdapter; + @Mock + private UserManager mUserManager; + @Mock + private Preference mPreference; + + private TetherPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mController = spy(TetherPreferenceController.class); + ReflectionHelpers.setField(mController, "mContext", mContext); + ReflectionHelpers.setField(mController, "mConnectivityManager", mConnectivityManager); + ReflectionHelpers.setField(mController, "mBluetoothAdapter", mBluetoothAdapter); + ReflectionHelpers.setField(mController, "mUserManager", mUserManager); + } + + @Test + public void updateSummary_noPreference_noInteractionWithConnectivityManager() { + mController.updateSummary(); + verifyNoMoreInteractions(mConnectivityManager); + } + + @Test + public void updateSummary_wifiTethered_shouldShowHotspotMessage() { + ReflectionHelpers.setField(mController, "mPreference", mPreference); + when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123"}); + when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"123"}); + + mController.updateSummary(); + verify(mPreference).setSummary(R.string.tether_settings_summary_hotspot_on_tether_off); + } + + @Test + public void updateSummary_btThetherOn_shouldShowTetherMessage() { + ReflectionHelpers.setField(mController, "mPreference", mPreference); + when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123"}); + when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"123"}); + + mController.updateSummary(); + verify(mPreference).setSummary(R.string.tether_settings_summary_hotspot_off_tether_on); + } + + @Test + public void updateSummary_tetherOff_shouldShowTetherOffMessage() { + ReflectionHelpers.setField(mController, "mPreference", mPreference); + when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"123"}); + when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"456"}); + + mController.updateSummary(); + verify(mPreference).setSummary(R.string.switch_off_text); + } + + @Test + public void updateSummary_wifiBtTetherOn_shouldShowHotspotAndTetherMessage() { + ReflectionHelpers.setField(mController, "mPreference", mPreference); + when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[]{"123", "456"}); + when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"456"}); + when(mConnectivityManager.getTetherableBluetoothRegexs()).thenReturn(new String[]{"23"}); + + mController.updateSummary(); + verify(mPreference).setSummary(R.string.tether_settings_summary_hotspot_on_tether_on); + } + +}