Update bluetooth preference to take user to new screen

This CL removes the toggle from the bluetooth preference and instead
takes users to a new dedicated screen for toggling bluetooth status.
On this screen we show a different summary text depending on whether
bluetooth and bluetooth scanning are on/off. Also, we were able to
delegate most of the UI/bluetooth handling to already existing
classes.

Test: robotests
Bug: 77543471
Merged-In: I036a3992bbd78896da8364b55ecc51afc4464b6e
Change-Id: I036a3992bbd78896da8364b55ecc51afc4464b6e
This commit is contained in:
Salvador Martinez
2018-04-04 14:23:57 -07:00
parent d57d27acab
commit 9eac182805
13 changed files with 312 additions and 170 deletions

View File

@@ -1613,6 +1613,8 @@
<string name="bluetooth_advanced_titlebar">Advanced Bluetooth</string>
<!-- Bluetooth settings. Text displayed when Bluetooth is off and device list is empty [CHAR LIMIT=50]-->
<string name="bluetooth_empty_list_bluetooth_off">When Bluetooth is turned on, your device can communicate with other nearby Bluetooth devices.</string>
<!-- Bluetooth settings. Text displayed when Bluetooth is off and bluetooth scanning is turned on [CHAR LIMIT=NONE] -->
<string name="bluetooth_scanning_on_info_message">When Bluetooth is turned on, your device can communicate with other nearby Bluetooth devices.\n\nTo improve device experience, apps and services can still scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services. you can change this in <annotation id="link">scanning settings</annotation>.</string>
<!-- Message to describe "BLE scan always available feature" when Bluetooth is off. The
place-holders "LINK_BEGIN" and "LINK_END" must NOT be translated. They mark a link to bring
the user to "scanning settings" screen. -->
@@ -6692,6 +6694,8 @@
<string name="help_uri_wifi_calling" translatable="false"></string>
<!-- url for the wifi scanning required dialog help page -->
<string name="help_uri_wifi_scanning_required" translatable="false"></string>
<!-- url for the bluetooth toggle required dialog help page -->
<string name="help_uri_bluetooth_screen" translatable="false"></string>
<!-- User account title [CHAR LIMIT=30] -->
<string name="user_account_title">Account for content</string>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:key="bluetooth_switchbar_screen"
android:title="@string/bluetooth_settings_title" />

View File

@@ -42,14 +42,12 @@
android:fragment="com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment"
settings:allowDividerAbove="true"/>
<com.android.settingslib.RestrictedSwitchPreference
android:key="toggle_bluetooth_switch"
<Preference
android:fragment="com.android.settings.connecteddevice.BluetoothDashboardFragment"
android:key="bluetooth_settings"
android:title="@string/bluetooth_settings_title"
android:icon="@drawable/ic_settings_bluetooth"
android:summary="@string/bluetooth_pref_summary"
settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"
settings:userRestriction="no_bluetooth"
settings:platform_slice="true"/>
settings:allowDividerAbove="true"/>
<SwitchPreference
android:key="toggle_nfc"

View File

@@ -47,6 +47,7 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
private final LocalBluetoothAdapter mLocalAdapter;
private final IntentFilter mIntentFilter;
private final RestrictionUtils mRestrictionUtils;
private SwitchWidgetController.OnSwitchChangeListener mCallback;
private static final String EVENT_DATA_IS_BT_ON = "is_bluetooth_on";
private static final int EVENT_UPDATE_INDEX = 0;
@@ -170,6 +171,7 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
@Override
public boolean onSwitchToggled(boolean isChecked) {
if (maybeEnforceRestrictions()) {
triggerParentPreferenceCallback(isChecked);
return true;
}
@@ -179,6 +181,7 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
// Reset switch to off
mSwitchController.setChecked(false);
triggerParentPreferenceCallback(false);
return false;
}
@@ -193,13 +196,24 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
mSwitchController.setChecked(false);
mSwitchController.setEnabled(true);
mSwitchController.updateTitle(false);
triggerParentPreferenceCallback(false);
return false;
}
}
mSwitchController.setEnabled(false);
triggerParentPreferenceCallback(isChecked);
return true;
}
/**
* Sets a callback back that this enabler will trigger in case the preference using the enabler
* still needed the callback on the SwitchController (which we now use).
* @param listener The listener with a callback to trigger.
*/
public void setToggleCallback(SwitchWidgetController.OnSwitchChangeListener listener) {
mCallback = listener;
}
/**
* Enforces user restrictions disallowing Bluetooth (or its configuration) if there are any.
*
@@ -227,4 +241,11 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
return admin;
}
// This triggers the callback which was manually set for this enabler since the enabler will
// take over the switch controller callback
private void triggerParentPreferenceCallback(boolean isChecked) {
if (mCallback != null) {
mCallback.onSwitchToggled(isChecked);
}
}
}

View File

@@ -16,75 +16,79 @@
package com.android.settings.bluetooth;
import android.content.Context;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.view.View;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.location.ScanningSettings;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.utils.AnnotationSpan;
import com.android.settings.widget.SwitchWidgetController;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.widget.FooterPreference;
/**
* PreferenceController to update of bluetooth {@link SwitchPreference}. It will
*
* 1. Invoke the user toggle
* 2. Listen to the update from {@link LocalBluetoothManager}
* PreferenceController to update of bluetooth state. All behavior except managing the footer text
* is delegated to the SwitchWidgetController it uses.
*/
public class BluetoothSwitchPreferenceController extends TogglePreferenceController
implements LifecycleObserver, OnStart, OnStop {
public class BluetoothSwitchPreferenceController
implements LifecycleObserver, OnStart, OnStop,
SwitchWidgetController.OnSwitchChangeListener, View.OnClickListener {
public static final String KEY_TOGGLE_BLUETOOTH = "toggle_bluetooth_switch";
private LocalBluetoothManager mBluetoothManager;
private SwitchPreference mBtPreference;
private BluetoothEnabler mBluetoothEnabler;
private RestrictionUtils mRestrictionUtils;
@VisibleForTesting
LocalBluetoothAdapter mBluetoothAdapter;
public BluetoothSwitchPreferenceController(Context context) {
this(context, Utils.getLocalBtManager(context), new RestrictionUtils());
private LocalBluetoothManager mBluetoothManager;
private BluetoothEnabler mBluetoothEnabler;
private RestrictionUtils mRestrictionUtils;
private SwitchWidgetController mSwitch;
private Context mContext;
private FooterPreference mFooterPreference;
public BluetoothSwitchPreferenceController(Context context,
SwitchWidgetController switchController,
FooterPreference footerPreference) {
this(context, Utils.getLocalBtManager(context), new RestrictionUtils(), switchController,
footerPreference);
}
@VisibleForTesting
public BluetoothSwitchPreferenceController(Context context,
LocalBluetoothManager bluetoothManager, RestrictionUtils restrictionUtils) {
super(context, KEY_TOGGLE_BLUETOOTH);
LocalBluetoothManager bluetoothManager, RestrictionUtils restrictionUtils,
SwitchWidgetController switchController, FooterPreference footerPreference) {
mBluetoothManager = bluetoothManager;
mRestrictionUtils = restrictionUtils;
mSwitch = switchController;
mContext = context;
mFooterPreference = footerPreference;
mSwitch.setupView();
updateText(mSwitch.isChecked());
if (mBluetoothManager != null) {
mBluetoothAdapter = mBluetoothManager.getBluetoothAdapter();
}
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mBtPreference = (SwitchPreference) screen.findPreference(KEY_TOGGLE_BLUETOOTH);
mBluetoothEnabler = new BluetoothEnabler(mContext,
new SwitchController(mBtPreference),
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(), mBluetoothManager,
mBluetoothEnabler = new BluetoothEnabler(context,
switchController,
FeatureFactory.getFactory(context).getMetricsFeatureProvider(), mBluetoothManager,
MetricsEvent.ACTION_SETTINGS_MASTER_SWITCH_BLUETOOTH_TOGGLE,
mRestrictionUtils);
}
@Override
public int getAvailabilityStatus() {
return mBluetoothAdapter != null ? AVAILABLE : DISABLED_UNSUPPORTED;
mBluetoothEnabler.setToggleCallback(this);
}
@Override
public void onStart() {
mBluetoothEnabler.resume(mContext);
if (mSwitch != null) {
updateText(mSwitch.isChecked());
}
}
@Override
@@ -93,70 +97,30 @@ public class BluetoothSwitchPreferenceController extends TogglePreferenceControl
}
@Override
public boolean isChecked() {
return mBluetoothAdapter != null ? mBluetoothAdapter.isEnabled() : false;
}
@Override
public boolean setChecked(boolean isChecked) {
if (mBluetoothAdapter != null) {
mBluetoothAdapter.setBluetoothEnabled(isChecked);
}
public boolean onSwitchToggled(boolean isChecked) {
updateText(isChecked);
return true;
}
/**
* Control the switch inside {@link SwitchPreference}
*/
@VisibleForTesting
static class SwitchController extends SwitchWidgetController implements
Preference.OnPreferenceChangeListener {
private SwitchPreference mSwitchPreference;
public SwitchController(SwitchPreference switchPreference) {
mSwitchPreference = switchPreference;
}
@Override
public void updateTitle(boolean isChecked) {
public void onClick(View v) {
// send users to scanning settings if they click on the link in the summary text
new SubSettingLauncher(mContext)
.setDestination(ScanningSettings.class.getName())
.setSourceMetricsCategory(MetricsProto.MetricsEvent.BLUETOOTH_FRAGMENT)
.launch();
}
@Override
public void startListening() {
mSwitchPreference.setOnPreferenceChangeListener(this);
}
@Override
public void stopListening() {
mSwitchPreference.setOnPreferenceChangeListener(null);
}
@Override
public void setChecked(boolean checked) {
mSwitchPreference.setChecked(checked);
}
@Override
public boolean isChecked() {
return mSwitchPreference.isChecked();
}
@Override
public void setEnabled(boolean enabled) {
mSwitchPreference.setEnabled(enabled);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (mListener != null) {
return mListener.onSwitchToggled((Boolean) newValue);
}
return false;
}
@Override
public void setDisabledByAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
mSwitchPreference.setEnabled(admin == null);
@VisibleForTesting void updateText(boolean isChecked) {
if (!isChecked
&& Utils.isBluetoothScanningEnabled(mContext)) {
AnnotationSpan.LinkInfo info = new AnnotationSpan.LinkInfo(
AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION, this);
CharSequence text = AnnotationSpan.linkify(
mContext.getText(R.string.bluetooth_scanning_on_info_message), info);
mFooterPreference.setTitle(text);
} else {
mFooterPreference.setTitle(R.string.bluetooth_empty_list_bluetooth_off);
}
}
}

View File

@@ -21,6 +21,7 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.DialogInterface;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.widget.Toast;
@@ -142,4 +143,8 @@ public final class Utils {
}
};
public static boolean isBluetoothScanningEnabled(Context context) {
return Settings.Global.getInt(context.getContentResolver(),
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1;
}
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright (C) 2018 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.connecteddevice;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.bluetooth.BluetoothSwitchPreferenceController;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.location.ScanningSettings;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.SwitchBarController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.FooterPreference;
import java.util.ArrayList;
import java.util.List;
/**
* Dedicated screen for allowing the user to toggle bluetooth which displays relevant information to
* the user based on related settings such as bluetooth scanning.
*/
public class BluetoothDashboardFragment extends DashboardFragment {
private static final String TAG = "BluetoothDashboardFrag";
public static final String KEY_BLUETOOTH_SCREEN = "bluetooth_switchbar_screen";
private FooterPreference mFooterPreference;
private SwitchBar mSwitchBar;
private BluetoothSwitchPreferenceController mController;
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.BLUETOOTH_FRAGMENT;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
public int getHelpResource() {
return R.string.help_uri_bluetooth_screen;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.bluetooth_screen;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mFooterPreference = mFooterPreferenceMixin.createFooterPreference();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
SettingsActivity activity = (SettingsActivity) getActivity();
mSwitchBar = activity.getSwitchBar();
mController = new BluetoothSwitchPreferenceController(activity,
new SwitchBarController(mSwitchBar), mFooterPreference);
Lifecycle lifecycle = getLifecycle();
if (lifecycle != null) {
lifecycle.addObserver(mController);
}
}
/**
* For Search.
*/
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableRaw> getRawDataToIndex(Context context,
boolean enabled) {
final List<SearchIndexableRaw> result = new ArrayList<>();
// Add the activity title
SearchIndexableRaw data = new SearchIndexableRaw(context);
data.title = context.getString(R.string.bluetooth_settings_title);
data.screenTitle = context.getString(R.string.settings_label);
data.keywords = context.getString(R.string.keywords_bluetooth_settings);
data.intentTargetPackage = context.getPackageName();
data.intentTargetClass = BluetoothDashboardFragment.class.getName();
data.intentAction = new SubSettingLauncher(context)
.setDestination(ScanningSettings.class.getName())
.setSourceMetricsCategory(MetricsProto.MetricsEvent.BLUETOOTH_FRAGMENT)
.toIntent()
.getAction();
data.key = KEY_BLUETOOTH_SCREEN;
result.add(data);
return result;
}
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context);
BluetoothManager manager =
(BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
if (manager != null) {
BluetoothAdapter adapter = manager.getAdapter();
final int status = adapter != null
? TogglePreferenceController.AVAILABLE
: TogglePreferenceController.DISABLED_UNSUPPORTED;
if (status != TogglePreferenceController.AVAILABLE) {
keys.add(KEY_BLUETOOTH_SCREEN);
}
}
return keys;
}
};
}

View File

@@ -22,7 +22,6 @@ import android.support.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.bluetooth.BluetoothSwitchPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.nfc.NfcPreferenceController;
@@ -77,13 +76,8 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
new NfcPreferenceController(context);
controllers.add(nfcPreferenceController);
final BluetoothSwitchPreferenceController bluetoothPreferenceController =
new BluetoothSwitchPreferenceController(context);
controllers.add(bluetoothPreferenceController);
if (lifecycle != null) {
lifecycle.addObserver(nfcPreferenceController);
lifecycle.addObserver(bluetoothPreferenceController);
}
return controllers;

View File

@@ -23,6 +23,7 @@ import com.android.settings.DisplaySettings;
import com.android.settings.LegalSettings;
import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment;
import com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment;
import com.android.settings.connecteddevice.BluetoothDashboardFragment;
import com.android.settings.datausage.DataUsageSummaryLegacy;
import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
import com.android.settings.accessibility.AccessibilitySettings;
@@ -185,6 +186,7 @@ public class SearchIndexableResourcesImpl implements SearchIndexableResources {
addIndex(VibrationSettings.class);
addIndex(RecentLocationRequestSeeAllFragment.class);
addIndex(PreviouslyConnectedDeviceDashboardFragment.class);
addIndex(BluetoothDashboardFragment.class);
}
@Override

View File

@@ -80,6 +80,7 @@ public class AnnotationSpan extends URLSpan {
*/
public static class LinkInfo {
private static final String TAG = "AnnotationSpan.LinkInfo";
public static final String DEFAULT_ANNOTATION = "link";
private final String mAnnotation;
private final Boolean mActionable;
private final View.OnClickListener mListener;

View File

@@ -5,7 +5,6 @@ com.android.settings.applications.appinfo.AppMemoryPreferenceController
com.android.settings.applications.appinfo.InstantAppButtonsPreferenceController
com.android.settings.bluetooth.BluetoothDeviceNamePreferenceController
com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController
com.android.settings.bluetooth.BluetoothSwitchPreferenceController
com.android.settings.connecteddevice.ConnectedDeviceGroupController
com.android.settings.connecteddevice.SavedDeviceGroupController
com.android.settings.datausage.DataUsageSummaryPreferenceController

View File

@@ -37,9 +37,11 @@ import android.view.View;
import android.widget.Switch;
import com.android.settings.R;
import com.android.settings.bluetooth.BluetoothSwitchPreferenceController.SwitchController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.SwitchBarController;
import com.android.settings.widget.SwitchWidgetController;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
@@ -77,9 +79,11 @@ public class BluetoothEnablerTest {
private LocalBluetoothManager mBluetoothManager;
@Mock
private LocalBluetoothAdapter mBluetoothAdapter;
@Mock
private SwitchWidgetController.OnSwitchChangeListener mCallback;
private Context mContext;
private SwitchController mSwitchController;
private SwitchWidgetController mSwitchController;
private BluetoothEnabler mBluetoothEnabler;
@Before
@@ -89,7 +93,7 @@ public class BluetoothEnablerTest {
when(mBluetoothManager.getBluetoothAdapter()).thenReturn(mBluetoothAdapter);
mRestrictedSwitchPreference = new RestrictedSwitchPreference(mContext);
mSwitchController = spy(new SwitchController(mRestrictedSwitchPreference));
mSwitchController = spy(new SwitchBarController(new SwitchBar(mContext)));
mBluetoothEnabler = new BluetoothEnabler(
mContext,
mSwitchController,
@@ -99,6 +103,7 @@ public class BluetoothEnablerTest {
mRestrictionUtils);
mHolder = PreferenceViewHolder.createInstanceForTests(mock(View.class));
mRestrictedSwitchPreference.onBindViewHolder(mHolder);
mBluetoothEnabler.setToggleCallback(mCallback);
}
@Test
@@ -110,6 +115,15 @@ public class BluetoothEnablerTest {
verify(mMetricsFeatureProvider).action(mContext, 123, false);
}
@Test
public void onSwitchToggled_shouldTriggerCallback() {
// WHEN the switch is toggled...
mBluetoothEnabler.onSwitchToggled(false);
// THEN the callback is triggered
verify(mCallback).onSwitchToggled(false);
}
@Test
public void maybeEnforceRestrictions_noRestrictions() {
// GIVEN there are no restrictions set...

View File

@@ -17,21 +17,21 @@
package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.PreferenceScreen;
import android.provider.Settings;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settings.utils.AnnotationSpan;
import com.android.settings.widget.SwitchWidgetController;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.widget.FooterPreference;
import org.junit.Before;
import org.junit.Test;
@@ -44,17 +44,16 @@ import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class BluetoothSwitchPreferenceControllerTest {
public static final String BLUETOOTH_INFO_STRING = "When Bluetooth is turned on, your device"
+ " can communicate with other nearby Bluetooth devices.";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private LocalBluetoothManager mBluetoothManager;
@Mock
private PreferenceScreen mScreen;
@Mock
private SwitchPreference mPreference;
@Mock
private RestrictionUtils mRestrictionUtils;
@Mock
private LocalBluetoothAdapter mLocalBluetoothAdapter;
private SwitchWidgetController mSwitchController;
private FooterPreference mFooterPreference;
private Context mContext;
private BluetoothSwitchPreferenceController mController;
@@ -62,70 +61,52 @@ public class BluetoothSwitchPreferenceControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application.getApplicationContext());
mFooterPreference = new FooterPreference(mContext);
FakeFeatureFactory.setupForTest();
mController =
new BluetoothSwitchPreferenceController(mContext, mBluetoothManager, mRestrictionUtils);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
new BluetoothSwitchPreferenceController(mContext, mBluetoothManager, mRestrictionUtils,
mSwitchController, mFooterPreference);
}
@Test
public void testGetAvailabilityStatus_adapterNull_returnDisabled() {
mController.mBluetoothAdapter = null;
public void updateText_bluetoothOffScanningOn() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 1);
mController.updateText(false);
AnnotationSpan.LinkInfo info = new AnnotationSpan.LinkInfo(
AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION, mController);
CharSequence text = AnnotationSpan.linkify(
mContext.getText(R.string.bluetooth_scanning_on_info_message), info);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
assertThat(mFooterPreference.getTitle()).isEqualTo(text);
}
@Test
public void testGetAvailabilityStatus_adapterExisted_returnAvailable() {
mController.mBluetoothAdapter = mLocalBluetoothAdapter;
public void updateText_bluetoothOffScanningOff() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
mController.updateText(false);
assertThat(mFooterPreference.getTitle()).isEqualTo(BLUETOOTH_INFO_STRING);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
}
@Test
public void testOnStart_shouldRegisterPreferenceChangeListener() {
mController.displayPreference(mScreen);
mController.onStart();
public void updateText_bluetoothOnScanningOff() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0);
mController.updateText(true);
verify(mPreference).setOnPreferenceChangeListener(
any(BluetoothSwitchPreferenceController.SwitchController.class));
assertThat(mFooterPreference.getTitle()).isEqualTo(BLUETOOTH_INFO_STRING);
}
@Test
public void testOnStop_shouldRegisterPreferenceChangeListener() {
mController.displayPreference(mScreen);
mController.onStart();
public void updateText_bluetoothOnScanningOn() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 1);
mController.updateText(true);
mController.onStop();
verify(mPreference).setOnPreferenceChangeListener(null);
}
@Test
public void testIsChecked_adapterNull_returnFalse() {
mController.mBluetoothAdapter = null;
assertThat(mController.isChecked()).isFalse();
}
@Test
public void testIsChecked_adapterExisted_returnFromAdapter() {
mController.mBluetoothAdapter = mLocalBluetoothAdapter;
doReturn(true).when(mLocalBluetoothAdapter).isEnabled();
assertThat(mController.isChecked()).isTrue();
}
@Test
public void testSetChecked_adapterExisted() {
mController.mBluetoothAdapter = mLocalBluetoothAdapter;
mController.setChecked(true);
verify(mLocalBluetoothAdapter).setBluetoothEnabled(true);
assertThat(mFooterPreference.getTitle()).isEqualTo(BLUETOOTH_INFO_STRING);
}
}