diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b14856c85ec..a9497159b05 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3324,17 +3324,6 @@
android:value="com.android.settings.applications.ProcessStatsSummary" />
-
-
-
-
-
-
-
-
diff --git a/res/layout/preference_widget_master_switch.xml b/res/layout/preference_widget_master_switch.xml
new file mode 100644
index 00000000000..51d938b8a46
--- /dev/null
+++ b/res/layout/preference_widget_master_switch.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/xml/connected_devices.xml b/res/xml/connected_devices.xml
index abf493fed34..d70cc335ce8 100644
--- a/res/xml/connected_devices.xml
+++ b/res/xml/connected_devices.xml
@@ -18,6 +18,13 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/connected_devices_dashboard_title">
+
+
devices = getDevices();
- if (devices == null) {
- mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
- return;
- }
- if (mConnectionState == BluetoothAdapter.STATE_CONNECTED) {
- CachedBluetoothDevice connectedDevice = null;
- for (CachedBluetoothDevice device : devices) {
- if (device.isConnected()) {
- connectedDevice = device;
- }
- }
- if (connectedDevice == null) {
- // If somehow we think we are connected, but have no connected devices, we
- // aren't connected.
- mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
- }
- }
- }
-
- private Collection getDevices() {
- return mBluetoothManager != null
- ? mBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()
- : null;
- }
}
public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
diff --git a/src/com/android/settings/bluetooth/BluetoothSummaryHelper.java b/src/com/android/settings/bluetooth/BluetoothSummaryHelper.java
new file mode 100644
index 00000000000..2bd6f704b54
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothSummaryHelper.java
@@ -0,0 +1,172 @@
+/*
+ * 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+import android.text.TextUtils;
+import com.android.settings.R;
+import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import java.util.Collection;
+
+/**
+ * Helper class that listeners to bluetooth callback and notify client when there is update in
+ * bluetooth summary info.
+ */
+public final class BluetoothSummaryHelper implements BluetoothCallback {
+
+ private OnSummaryChangeListener mListener;
+
+ private final LocalBluetoothManager mBluetoothManager;
+ private final LocalBluetoothAdapter mBluetoothAdapter;
+ private final Context mContext;
+
+ private boolean mEnabled;
+ private int mConnectionState;
+ private String mSummary;
+
+ public interface OnSummaryChangeListener {
+ /**
+ * Called when bluetooth summary has changed.
+ *
+ * @param summary The new bluetooth summary .
+ */
+ void onSummaryChanged(String summary);
+ }
+
+ public BluetoothSummaryHelper(Context context, LocalBluetoothManager bluetoothManager) {
+ mContext = context;
+ mBluetoothManager = bluetoothManager;
+ mBluetoothAdapter = mBluetoothManager != null
+ ? mBluetoothManager.getBluetoothAdapter() : null;
+ }
+
+ @Override
+ public void onBluetoothStateChanged(int bluetoothState) {
+ mEnabled = bluetoothState == BluetoothAdapter.STATE_ON
+ || bluetoothState == BluetoothAdapter.STATE_TURNING_ON;
+ notifyChangeIfNeeded();
+ }
+
+ @Override
+ public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
+ mConnectionState = state;
+ updateConnected();
+ notifyChangeIfNeeded();
+ }
+
+ @Override
+ public void onScanningStateChanged(boolean started) {
+ }
+
+ @Override
+ public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
+ }
+
+ @Override
+ public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
+ }
+
+ @Override
+ public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
+ }
+
+ public void setOnSummaryChangeListener(OnSummaryChangeListener listener) {
+ mListener = listener;
+ }
+
+ public void setListening(boolean listening) {
+ if (mBluetoothAdapter == null) {
+ return;
+ }
+ if (listening) {
+ mEnabled = mBluetoothAdapter.isEnabled();
+ mConnectionState = mBluetoothAdapter.getConnectionState();
+ notifyChangeIfNeeded();
+ mBluetoothManager.getEventManager().registerCallback(this);
+ } else {
+ mBluetoothManager.getEventManager().unregisterCallback(this);
+ }
+ }
+
+ private void notifyChangeIfNeeded() {
+ String summary = getSummary();
+ if (!TextUtils.equals(mSummary, summary)) {
+ mSummary = summary;
+ if (mListener != null) {
+ mListener.onSummaryChanged(summary);
+ }
+ }
+ }
+
+ private String getSummary() {
+ if (!mEnabled) {
+ return mContext.getString(R.string.bluetooth_disabled);
+ }
+ switch (mConnectionState) {
+ case BluetoothAdapter.STATE_CONNECTED:
+ return mContext.getString(R.string.bluetooth_connected);
+ case BluetoothAdapter.STATE_CONNECTING:
+ return mContext.getString(R.string.bluetooth_connecting);
+ case BluetoothAdapter.STATE_DISCONNECTING:
+ return mContext.getString(R.string.bluetooth_disconnecting);
+ default:
+ return mContext.getString(R.string.bluetooth_disconnected);
+ }
+ }
+
+ private void updateConnected() {
+ if (mBluetoothAdapter == null) {
+ return;
+ }
+ // Make sure our connection state is up to date.
+ int state = mBluetoothAdapter.getConnectionState();
+ if (state != mConnectionState) {
+ mConnectionState = state;
+ return;
+ }
+ final Collection devices = getDevices();
+ if (devices == null) {
+ mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
+ return;
+ }
+ if (mConnectionState == BluetoothAdapter.STATE_CONNECTED) {
+ CachedBluetoothDevice connectedDevice = null;
+ for (CachedBluetoothDevice device : devices) {
+ if (device.isConnected()) {
+ connectedDevice = device;
+ break;
+ }
+ }
+ if (connectedDevice == null) {
+ // If somehow we think we are connected, but have no connected devices, we
+ // aren't connected.
+ mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
+ }
+ }
+ }
+
+ private Collection getDevices() {
+ return mBluetoothManager != null
+ ? mBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()
+ : null;
+ }
+
+}
diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
index b8ee1ff408b..fe0e1d2e88c 100644
--- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
@@ -20,7 +20,10 @@ import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settings.bluetooth.BluetoothMasterSwitchPreferenceController;
+import com.android.settings.bluetooth.Utils;
import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.deviceinfo.UsbBackend;
import com.android.settings.nfc.NfcPreferenceController;
@@ -37,6 +40,7 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
private static final String TAG = "ConnectedDeviceFrag";
private UsbModePreferenceController mUsbPrefController;
+ private BluetoothMasterSwitchPreferenceController mBluetoothPreferenceController;
@Override
public int getMetricsCategory() {
@@ -61,13 +65,19 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
@Override
protected List getPreferenceControllers(Context context) {
final List controllers = new ArrayList<>();
+ final Lifecycle lifecycle = getLifecycle();
final NfcPreferenceController nfcPreferenceController =
new NfcPreferenceController(context);
- getLifecycle().addObserver(nfcPreferenceController);
+ lifecycle.addObserver(nfcPreferenceController);
controllers.add(nfcPreferenceController);
mUsbPrefController = new UsbModePreferenceController(context, new UsbBackend(context));
- getLifecycle().addObserver(mUsbPrefController);
+ lifecycle.addObserver(mUsbPrefController);
controllers.add(mUsbPrefController);
+ mBluetoothPreferenceController =
+ new BluetoothMasterSwitchPreferenceController(
+ context, Utils.getLocalBtManager(context));
+ lifecycle.addObserver(mBluetoothPreferenceController);
+ controllers.add(mBluetoothPreferenceController);
return controllers;
}
diff --git a/src/com/android/settings/widget/MasterSwitchController.java b/src/com/android/settings/widget/MasterSwitchController.java
new file mode 100644
index 00000000000..53e5fe7817c
--- /dev/null
+++ b/src/com/android/settings/widget/MasterSwitchController.java
@@ -0,0 +1,70 @@
+/*
+ * 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.widget;
+
+import android.support.v7.preference.Preference;
+
+/*
+ * The switch controller that is used to update the switch widget in the MasterSwitchPreference
+ * layout.
+ */
+public class MasterSwitchController extends SwitchWidgetController implements
+ Preference.OnPreferenceChangeListener {
+
+ private final MasterSwitchPreference mPreference;
+
+ public MasterSwitchController(MasterSwitchPreference preference) {
+ mPreference = preference;
+ }
+
+ @Override
+ public void updateTitle(boolean isChecked) {
+ }
+
+ @Override
+ public void startListening() {
+ mPreference.setOnPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void stopListening() {
+ mPreference.setOnPreferenceChangeListener(null);
+ }
+
+ @Override
+ public void setChecked(boolean checked) {
+ mPreference.setChecked(checked);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mPreference.isChecked();
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ mPreference.setSwitchEnabled(enabled);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (mListener != null) {
+ return mListener.onSwitchToggled((Boolean) newValue);
+ }
+ return false;
+ }
+}
diff --git a/src/com/android/settings/widget/MasterSwitchPreference.java b/src/com/android/settings/widget/MasterSwitchPreference.java
new file mode 100644
index 00000000000..8130ca5ad64
--- /dev/null
+++ b/src/com/android/settings/widget/MasterSwitchPreference.java
@@ -0,0 +1,102 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.widget.CompoundButton;
+import android.widget.Switch;
+
+import com.android.settings.R;
+
+/**
+ * A custom preference that provides inline switch toggle. It has a mandatory field for title, and
+ * optional fields for icon and sub-text.
+ */
+public class MasterSwitchPreference extends Preference {
+
+ private Switch mSwitch;
+ private boolean mChecked;
+
+ public MasterSwitchPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init();
+ }
+
+ public MasterSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ public MasterSwitchPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public MasterSwitchPreference(Context context) {
+ super(context);
+ init();
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ mSwitch = (Switch) holder.itemView.findViewById(R.id.switchWidget);
+ if (mSwitch != null) {
+ mSwitch.setChecked(mChecked);
+ mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton button, boolean isChecked) {
+ if (!callChangeListener(isChecked)) {
+ button.setChecked(!isChecked);
+ } else {
+ persistBoolean(isChecked);
+ mChecked = isChecked;
+ }
+ }
+ });
+ }
+ }
+
+ public boolean isChecked() {
+ return isEnabled() && mChecked;
+ }
+
+ public void setChecked(boolean checked) {
+ mChecked = checked;
+ if (mSwitch != null) {
+ mSwitch.setChecked(checked);
+ }
+ }
+
+ public boolean isSwitchEnabled() {
+ return isEnabled() && mSwitch != null && mSwitch.isEnabled();
+ }
+
+ public void setSwitchEnabled(boolean enabled) {
+ if (mSwitch != null) {
+ mSwitch.setEnabled(enabled);
+ }
+ }
+
+ private void init() {
+ setWidgetLayoutResource(R.layout.preference_widget_master_switch);
+ }
+}
diff --git a/src/com/android/settings/widget/SwitchBarController.java b/src/com/android/settings/widget/SwitchBarController.java
new file mode 100644
index 00000000000..70fd7ba75b6
--- /dev/null
+++ b/src/com/android/settings/widget/SwitchBarController.java
@@ -0,0 +1,81 @@
+/*
+ * 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.widget;
+
+import android.widget.Switch;
+
+/*
+ * The switch controller that is used to update the switch widget in the SwitchBar layout.
+ */
+public class SwitchBarController extends SwitchWidgetController implements
+ SwitchBar.OnSwitchChangeListener {
+
+ private final SwitchBar mSwitchBar;
+ private final Switch mSwitch;
+
+ public SwitchBarController(SwitchBar switchBar) {
+ mSwitchBar = switchBar;
+ mSwitch = switchBar.getSwitch();
+ }
+
+ @Override
+ public void setupView() {
+ mSwitchBar.show();
+ }
+
+ @Override
+ public void teardownView() {
+ mSwitchBar.hide();
+ }
+
+ @Override
+ public void updateTitle(boolean isChecked) {
+ mSwitchBar.setTextViewLabel(isChecked);
+ }
+
+ @Override
+ public void startListening() {
+ mSwitchBar.addOnSwitchChangeListener(this);
+ }
+
+ @Override
+ public void stopListening() {
+ mSwitchBar.removeOnSwitchChangeListener(this);
+ }
+
+ @Override
+ public void setChecked(boolean checked) {
+ mSwitch.setChecked(checked);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mSwitch.isChecked();
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ mSwitch.setEnabled(enabled);
+ }
+
+ @Override
+ public void onSwitchChanged(Switch switchView, boolean isChecked) {
+ if (mListener != null) {
+ mListener.onSwitchToggled(isChecked);
+ }
+ }
+}
diff --git a/src/com/android/settings/widget/SwitchWidgetController.java b/src/com/android/settings/widget/SwitchWidgetController.java
new file mode 100644
index 00000000000..c5a8c87c09f
--- /dev/null
+++ b/src/com/android/settings/widget/SwitchWidgetController.java
@@ -0,0 +1,58 @@
+/*
+ * 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.widget;
+
+/*
+ * A controller class for general switch widget handling. We have different containers that provide
+ * different forms of switch layout. Provide a centralized control for updating the switch widget.
+ */
+public abstract class SwitchWidgetController {
+
+ protected OnSwitchChangeListener mListener;
+
+ public interface OnSwitchChangeListener {
+ /**
+ * Called when the checked state of the Switch has changed.
+ *
+ * @param isChecked The new checked state of switchView.
+ */
+ boolean onSwitchToggled(boolean isChecked);
+ }
+
+ public void setupView() {
+ }
+
+ public void teardownView() {
+ }
+
+ public void setListener(OnSwitchChangeListener listener) {
+ mListener = listener;
+ }
+
+ public abstract void updateTitle(boolean isChecked);
+
+ public abstract void startListening();
+
+ public abstract void stopListening();
+
+ public abstract void setChecked(boolean checked);
+
+ public abstract boolean isChecked();
+
+ public abstract void setEnabled(boolean enabled);
+
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothMasterSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothMasterSwitchPreferenceControllerTest.java
new file mode 100644
index 00000000000..0e39c5df6e6
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothMasterSwitchPreferenceControllerTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.bluetooth;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.widget.MasterSwitchPreference;
+import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BluetoothMasterSwitchPreferenceControllerTest {
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private LocalBluetoothManager mBluetoothManager;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private MasterSwitchPreference mPreference;
+
+ private Context mContext;
+ private BluetoothMasterSwitchPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application.getApplicationContext();
+ mController = new BluetoothMasterSwitchPreferenceController(mContext, mBluetoothManager);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ }
+
+ @Test
+ public void isAvailable_shouldAlwaysReturnTrue() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void onResume_shouldRegisterCallback() {
+ mController.onResume();
+
+ verify(mBluetoothManager.getEventManager()).registerCallback(any(BluetoothCallback.class));
+ }
+
+ @Test
+ public void onPause_shouldUnregisterCallback() {
+ mController.onPause();
+
+ verify(mBluetoothManager.getEventManager()).unregisterCallback(
+ any(BluetoothCallback.class));
+ }
+
+ @Test
+ public void onStart_shouldRegisterPreferenceChangeListener() {
+ mController.displayPreference(mScreen);
+ mController.onStart();
+
+ verify(mPreference).setOnPreferenceChangeListener(any(OnPreferenceChangeListener.class));
+ }
+
+ @Test
+ public void onStop_shouldRegisterPreferenceChangeListener() {
+ mController.displayPreference(mScreen);
+ mController.onStart();
+
+ mController.onStop();
+
+ verify(mPreference).setOnPreferenceChangeListener(null);
+ }
+
+ @Test
+ public void onSummaryUpdated_shouldUpdatePreferenceSummary() {
+ mController.displayPreference(mScreen);
+
+ mController.onSummaryChanged("test summary");
+
+ verify(mPreference).setSummary("test summary");
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothSettingsSummaryProviderTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothSettingsSummaryProviderTest.java
index 7ac7cb189e4..2822b1efee6 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothSettingsSummaryProviderTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothSettingsSummaryProviderTest.java
@@ -16,14 +16,11 @@
package com.android.settings.bluetooth;
-import android.bluetooth.BluetoothAdapter;
import android.content.Context;
-import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.dashboard.SummaryLoader;
-import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import org.junit.Before;
@@ -34,15 +31,10 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowBluetoothAdapter;
import java.util.ArrayList;
import java.util.List;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -67,102 +59,27 @@ public class BluetoothSettingsSummaryProviderTest {
}
@Test
- public void setListening_shouldUpdateSummary() {
+ public void setListening_shouldRegister() {
mSummaryProvider.setListening(true);
- verify(mBluetoothManager.getEventManager()).registerCallback(mSummaryProvider);
- verify(mSummaryLoader).setSummary(eq(mSummaryProvider), anyString());
+ verify(mBluetoothManager.getEventManager()).registerCallback(
+ mSummaryProvider.mSummaryHelper);
}
@Test
public void setNotListening_shouldUnregister() {
mSummaryProvider.setListening(false);
- verify(mBluetoothManager.getEventManager()).unregisterCallback(mSummaryProvider);
+ verify(mBluetoothManager.getEventManager()).unregisterCallback(
+ mSummaryProvider.mSummaryHelper);
}
@Test
- public void updateSummary_btDisabled_shouldShowDisabledMessage() {
- ShadowBluetoothAdapter.getDefaultAdapter().disable();
- mSummaryProvider.setListening(true);
+ public void onSummaryChanged_shouldSetSummary() {
+ final String summary = "Bluetooth summary";
+ mSummaryProvider.onSummaryChanged(summary);
- verify(mSummaryLoader).setSummary(mSummaryProvider,
- mContext.getString(R.string.bluetooth_disabled));
- }
-
- @Test
- public void updateSummary_btEnabled_noDevice_shouldShowDisconnectedMessage() {
- ShadowBluetoothAdapter.getDefaultAdapter().enable();
- mSummaryProvider.setListening(true);
-
- verify(mSummaryLoader).setSummary(mSummaryProvider,
- mContext.getString(R.string.bluetooth_disconnected));
- }
-
- @Test
- public void updateState_btEnabled_noDevice_shouldShowDisconnectedMessage() {
- ShadowBluetoothAdapter.getDefaultAdapter().enable();
- mSummaryProvider.onBluetoothStateChanged(BluetoothAdapter.STATE_TURNING_ON);
-
- verify(mSummaryLoader).setSummary(mSummaryProvider,
- mContext.getString(R.string.bluetooth_disconnected));
- }
-
- @Test
- public void updateState_btDisabled_shouldShowDisabledMessage() {
- ShadowBluetoothAdapter.getDefaultAdapter().enable();
- mSummaryProvider.onBluetoothStateChanged(BluetoothAdapter.STATE_TURNING_OFF);
-
- verify(mSummaryLoader).setSummary(mSummaryProvider,
- mContext.getString(R.string.bluetooth_disabled));
- }
-
- @Test
- public void updateConnectionState_disconnected_shouldShowDisconnectedMessage() {
- ShadowBluetoothAdapter.getDefaultAdapter().enable();
- when(mBluetoothManager.getBluetoothAdapter().getConnectionState())
- .thenReturn(BluetoothAdapter.STATE_DISCONNECTED);
-
- mSummaryProvider.setListening(true);
- mSummaryProvider.onConnectionStateChanged(null /* device */,
- BluetoothAdapter.STATE_DISCONNECTED);
-
- verify(mSummaryLoader, times(2)).setSummary(mSummaryProvider,
- mContext.getString(R.string.bluetooth_disconnected));
- }
-
-
- @Test
- public void updateConnectionState_connected_shouldShowConnectedMessage() {
- ShadowBluetoothAdapter.getDefaultAdapter().enable();
- when(mBluetoothManager.getBluetoothAdapter().getConnectionState())
- .thenReturn(BluetoothAdapter.STATE_CONNECTED);
- final List devices = new ArrayList<>();
- devices.add(mock(CachedBluetoothDevice.class));
- when(devices.get(0).isConnected()).thenReturn(true);
- when(mBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy())
- .thenReturn(devices);
-
- mSummaryProvider.setListening(true);
- mSummaryProvider.onConnectionStateChanged(null /* device */,
- BluetoothAdapter.STATE_CONNECTED);
-
- verify(mSummaryLoader).setSummary(mSummaryProvider,
- mContext.getString(R.string.bluetooth_connected));
- }
-
- @Test
- public void updateConnectionState_inconsistentState_shouldShowDisconnectedMessage() {
- ShadowBluetoothAdapter.getDefaultAdapter().enable();
- when(mBluetoothManager.getBluetoothAdapter().getConnectionState())
- .thenReturn(BluetoothAdapter.STATE_CONNECTED);
-
- mSummaryProvider.setListening(true);
- mSummaryProvider.onConnectionStateChanged(null /* device */,
- BluetoothAdapter.STATE_CONNECTED);
-
- verify(mSummaryLoader, times(2)).setSummary(mSummaryProvider,
- mContext.getString(R.string.bluetooth_disconnected));
+ verify(mSummaryLoader).setSummary(mSummaryProvider, summary);
}
}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothSummaryHelperTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothSummaryHelperTest.java
new file mode 100644
index 00000000000..f25e6d98f08
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothSummaryHelperTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowBluetoothAdapter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BluetoothSummaryHelperTest {
+
+ private Context mContext;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private LocalBluetoothManager mBluetoothManager;
+ @Mock
+ private LocalBluetoothAdapter mBtAdapter;
+
+ private BluetoothSummaryHelper mHelper;
+ @Mock
+ private SummaryListener mListener;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mBluetoothManager.getBluetoothAdapter()).thenReturn(mBtAdapter);
+ when(mBtAdapter.isEnabled()).thenReturn(true);
+ when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_CONNECTED);
+ mContext = RuntimeEnvironment.application.getApplicationContext();
+ mHelper = new BluetoothSummaryHelper(mContext, mBluetoothManager);
+ mHelper.setOnSummaryChangeListener(mListener);
+ }
+
+ @Test
+ public void setListening_shouldRegisterListener() {
+ mHelper.setListening(true);
+
+ verify(mBluetoothManager.getEventManager()).registerCallback(mHelper);
+ }
+
+ @Test
+ public void setNotListening_shouldUnregisterListener() {
+ mHelper.setListening(false);
+
+ verify(mBluetoothManager.getEventManager()).unregisterCallback(mHelper);
+ }
+
+ @Test
+ public void setListening_shouldSendSummaryChange() {
+ mHelper.setListening(true);
+
+ verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_connected));
+ }
+
+ @Test
+ public void onBluetoothStateChanged_btDisabled_shouldSendDisabledSummary() {
+ mHelper.setListening(true);
+ mHelper.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
+
+ verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disabled));
+ }
+
+ @Test
+ public void onBluetoothStateChanged_btEnabled_connected_shouldSendConnectedSummary() {
+ mHelper.setListening(true);
+ mHelper.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
+
+ verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_connected));
+ }
+
+ @Test
+ public void onBluetoothStateChanged_btEnabled_notConnected_shouldSendDisconnectedMessage() {
+ when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_DISCONNECTED);
+ mHelper.setListening(true);
+ mHelper.onBluetoothStateChanged(BluetoothAdapter.STATE_TURNING_ON);
+
+ verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disconnected));
+ }
+
+ @Test
+ public void onConnectionStateChanged_connected_shouldSendConnectedMessage() {
+ final List devices = new ArrayList<>();
+ devices.add(mock(CachedBluetoothDevice.class));
+ when(devices.get(0).isConnected()).thenReturn(true);
+ when(mBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy())
+ .thenReturn(devices);
+ when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_DISCONNECTED);
+ mHelper.setListening(true);
+
+ when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_CONNECTED);
+ mHelper.onConnectionStateChanged(null /* device */, BluetoothAdapter.STATE_CONNECTED);
+
+ verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_connected));
+ }
+
+ @Test
+ public void onConnectionStateChanged_inconsistentState_shouldSendDisconnectedMessage() {
+ mHelper.setListening(true);
+ mHelper.onConnectionStateChanged(null /* device */, BluetoothAdapter.STATE_CONNECTED);
+
+ verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disconnected));
+ }
+
+ @Test
+ public void onConnectionStateChanged_connecting_shouldSendConnectingMessage() {
+ mHelper.setListening(true);
+ when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_CONNECTING);
+ mHelper.onConnectionStateChanged(null /* device */, BluetoothAdapter.STATE_CONNECTING);
+
+ verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_connecting));
+ }
+
+ @Test
+ public void onConnectionStateChanged_disconnecting_shouldSendDisconnectingMessage() {
+ mHelper.setListening(true);
+ when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_DISCONNECTING);
+ mHelper.onConnectionStateChanged(null /* device */, BluetoothAdapter.STATE_DISCONNECTING);
+
+ verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disconnecting));
+ }
+
+ private class SummaryListener implements BluetoothSummaryHelper.OnSummaryChangeListener {
+ String summary;
+
+ @Override
+ public void onSummaryChanged(String summary) {
+ this.summary = summary;
+ }
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/widget/MasterSwitchPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/MasterSwitchPreferenceTest.java
new file mode 100644
index 00000000000..1dce599d311
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/MasterSwitchPreferenceTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.view.LayoutInflater;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.Switch;
+
+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.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class MasterSwitchPreferenceTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = ShadowApplication.getInstance().getApplicationContext();
+ }
+
+ @Test
+ public void createNewPreference_shouldSetLayout() {
+ final MasterSwitchPreference preference = new MasterSwitchPreference(mContext);
+
+ assertThat(preference.getWidgetLayoutResource()).isEqualTo(
+ R.layout.preference_widget_master_switch);
+ }
+
+ @Test
+ public void setChecked_shouldUpdateButtonCheckedState() {
+ final MasterSwitchPreference preference = new MasterSwitchPreference(mContext);
+ final PreferenceViewHolder holder = new PreferenceViewHolder(LayoutInflater.from(mContext)
+ .inflate(R.layout.preference_widget_master_switch, null));
+ final Switch toggle = (Switch) holder.itemView.findViewById(R.id.switchWidget);
+ preference.onBindViewHolder(holder);
+
+ preference.setChecked(true);
+ assertThat(toggle.isChecked()).isTrue();
+
+ preference.setChecked(false);
+ assertThat(toggle.isChecked()).isFalse();
+ }
+
+ @Test
+ public void setSwitchEnabled_shouldUpdateButtonEnabledState() {
+ final MasterSwitchPreference preference = new MasterSwitchPreference(mContext);
+ final PreferenceViewHolder holder = new PreferenceViewHolder(
+ LayoutInflater.from(mContext).inflate(R.layout.preference_widget_master_switch, null));
+ final Switch toggle = (Switch) holder.itemView.findViewById(R.id.switchWidget);
+ preference.onBindViewHolder(holder);
+
+ preference.setSwitchEnabled(true);
+ assertThat(toggle.isEnabled()).isTrue();
+
+ preference.setSwitchEnabled(false);
+ assertThat(toggle.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void toggleButtonOn_shouldNotifyChecked() {
+ final MasterSwitchPreference preference = new MasterSwitchPreference(mContext);
+ final PreferenceViewHolder holder = new PreferenceViewHolder(
+ LayoutInflater.from(mContext).inflate(R.layout.preference_widget_master_switch, null));
+ final Switch toggle = (Switch) holder.itemView.findViewById(R.id.switchWidget);
+ final OnPreferenceChangeListener listener = mock(OnPreferenceChangeListener.class);
+ preference.setOnPreferenceChangeListener(listener);
+ preference.onBindViewHolder(holder);
+
+ toggle.setChecked(true);
+ verify(listener).onPreferenceChange(preference, true);
+ }
+
+ @Test
+ public void toggleButtonOff_shouldNotifyUnchecked() {
+ final MasterSwitchPreference preference = new MasterSwitchPreference(mContext);
+ final PreferenceViewHolder holder = new PreferenceViewHolder(
+ LayoutInflater.from(mContext).inflate(R.layout.preference_widget_master_switch, null));
+ final Switch toggle = (Switch) holder.itemView.findViewById(R.id.switchWidget);
+ final OnPreferenceChangeListener listener = mock(OnPreferenceChangeListener.class);
+ preference.setChecked(true);
+ preference.setOnPreferenceChangeListener(listener);
+ preference.onBindViewHolder(holder);
+
+ toggle.setChecked(false);
+ verify(listener).onPreferenceChange(preference, false);
+ }
+}