From 988199e2023107795570105679725d12c993fe48 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Fri, 1 Dec 2017 10:36:22 -0800 Subject: [PATCH 1/2] Add ConnectedUsbDeviceUpdater The usb updater listens to usb update and notify ConnectedDeviceGroupController to add/remove preference. This cl: 1. Add ConntectedusbDeviceUpdater 2. Extract the UsbConnectionBroadcastReceiver since it would be used both in controller and updater. 3. Add tests Bug: 69333961 Test: RunSettingsRoboTests Change-Id: Ic3b045a6faa4eba57d9b0c089ea1656141cc0220 --- .../ConnectedDeviceGroupController.java | 18 ++- .../ConnectedUsbDeviceUpdater.java | 92 +++++++++++++ .../UsbConnectionBroadcastReceiver.java | 76 +++++++++++ .../UsbModePreferenceController.java | 60 ++------- .../ConnectedDeviceGroupControllerTest.java | 18 ++- .../ConnectedUsbDeviceUpdaterTest.java | 89 +++++++++++++ .../UsbConnectionBroadcastReceiverTest.java | 126 ++++++++++++++++++ 7 files changed, 421 insertions(+), 58 deletions(-) create mode 100644 src/com/android/settings/connecteddevice/ConnectedUsbDeviceUpdater.java create mode 100644 src/com/android/settings/connecteddevice/UsbConnectionBroadcastReceiver.java create mode 100644 tests/robotests/src/com/android/settings/connecteddevice/ConnectedUsbDeviceUpdaterTest.java create mode 100644 tests/robotests/src/com/android/settings/connecteddevice/UsbConnectionBroadcastReceiverTest.java diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java b/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java index a0b5cb85697..3cccc15782f 100644 --- a/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java +++ b/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java @@ -19,6 +19,7 @@ import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceGroup; import android.support.v7.preference.PreferenceScreen; + import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.bluetooth.BluetoothDeviceUpdater; import com.android.settings.bluetooth.ConnectedBluetoothDeviceUpdater; @@ -42,26 +43,31 @@ public class ConnectedDeviceGroupController extends AbstractPreferenceController @VisibleForTesting PreferenceGroup mPreferenceGroup; private BluetoothDeviceUpdater mBluetoothDeviceUpdater; + private ConnectedUsbDeviceUpdater mConnectedUsbDeviceUpdater; public ConnectedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle) { super(fragment.getContext()); - init(lifecycle, new ConnectedBluetoothDeviceUpdater(fragment, this)); + init(lifecycle, new ConnectedBluetoothDeviceUpdater(fragment, this), + new ConnectedUsbDeviceUpdater(fragment.getContext(), this)); } @VisibleForTesting ConnectedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle, - BluetoothDeviceUpdater bluetoothDeviceUpdater) { + BluetoothDeviceUpdater bluetoothDeviceUpdater, + ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater) { super(fragment.getContext()); - init(lifecycle, bluetoothDeviceUpdater); + init(lifecycle, bluetoothDeviceUpdater, connectedUsbDeviceUpdater); } @Override public void onStart() { mBluetoothDeviceUpdater.registerCallback(); + mConnectedUsbDeviceUpdater.registerCallback(); } @Override public void onStop() { + mConnectedUsbDeviceUpdater.unregisterCallback(); mBluetoothDeviceUpdater.unregisterCallback(); } @@ -70,8 +76,10 @@ public class ConnectedDeviceGroupController extends AbstractPreferenceController super.displayPreference(screen); mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY); mPreferenceGroup.setVisible(false); + mBluetoothDeviceUpdater.setPrefContext(screen.getContext()); mBluetoothDeviceUpdater.forceUpdate(); + mConnectedUsbDeviceUpdater.initUsbPreference(screen.getContext()); } @Override @@ -100,10 +108,12 @@ public class ConnectedDeviceGroupController extends AbstractPreferenceController } } - private void init(Lifecycle lifecycle, BluetoothDeviceUpdater bluetoothDeviceUpdater) { + private void init(Lifecycle lifecycle, BluetoothDeviceUpdater bluetoothDeviceUpdater, + ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater) { if (lifecycle != null) { lifecycle.addObserver(this); } mBluetoothDeviceUpdater = bluetoothDeviceUpdater; + mConnectedUsbDeviceUpdater = connectedUsbDeviceUpdater; } } diff --git a/src/com/android/settings/connecteddevice/ConnectedUsbDeviceUpdater.java b/src/com/android/settings/connecteddevice/ConnectedUsbDeviceUpdater.java new file mode 100644 index 00000000000..0468b0f5a35 --- /dev/null +++ b/src/com/android/settings/connecteddevice/ConnectedUsbDeviceUpdater.java @@ -0,0 +1,92 @@ +/* + * 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.connecteddevice; + +import android.content.Context; +import android.content.Intent; +import android.support.annotation.VisibleForTesting; + +import com.android.settings.R; +import com.android.settings.deviceinfo.UsbBackend; +import com.android.settings.deviceinfo.UsbModeChooserActivity; +import com.android.settings.widget.GearPreference; + +/** + * Controller to maintain connected usb device + */ +public class ConnectedUsbDeviceUpdater { + private Context mContext; + private UsbBackend mUsbBackend; + private DevicePreferenceCallback mDevicePreferenceCallback; + @VisibleForTesting + GearPreference mUsbPreference; + @VisibleForTesting + UsbConnectionBroadcastReceiver mUsbReceiver; + + private UsbConnectionBroadcastReceiver.UsbConnectionListener mUsbConnectionListener = + (connected) -> { + if (connected) { + mUsbPreference.setSummary( + UsbModePreferenceController.getSummary(mUsbBackend.getCurrentMode())); + mDevicePreferenceCallback.onDeviceAdded(mUsbPreference); + } else { + mDevicePreferenceCallback.onDeviceRemoved(mUsbPreference); + } + }; + + public ConnectedUsbDeviceUpdater(Context context, + DevicePreferenceCallback devicePreferenceCallback) { + this(context, devicePreferenceCallback, new UsbBackend(context)); + } + + @VisibleForTesting + ConnectedUsbDeviceUpdater(Context context, DevicePreferenceCallback devicePreferenceCallback, + UsbBackend usbBackend) { + mContext = context; + mDevicePreferenceCallback = devicePreferenceCallback; + mUsbBackend = usbBackend; + mUsbReceiver = new UsbConnectionBroadcastReceiver(context, mUsbConnectionListener); + } + + public void registerCallback() { + // This method could handle multiple register + mUsbReceiver.register(); + } + + public void unregisterCallback() { + mUsbReceiver.unregister(); + } + + public void initUsbPreference(Context context) { + mUsbPreference = new GearPreference(context, null /* AttributeSet */); + mUsbPreference.setTitle(R.string.usb_pref); + mUsbPreference.setIcon(R.drawable.ic_usb); + mUsbPreference.setSelectable(false); + mUsbPreference.setOnGearClickListener((GearPreference p) -> { + final Intent intent = new Intent(mContext, UsbModeChooserActivity.class); + mContext.startActivity(intent); + }); + + forceUpdate(); + } + + private void forceUpdate() { + // Register so we can get the connection state from sticky intent. + //TODO(b/70336520): Use an API to get data instead of sticky intent + mUsbReceiver.register(); + mUsbConnectionListener.onUsbConnectionChanged(mUsbReceiver.isConnected()); + } +} diff --git a/src/com/android/settings/connecteddevice/UsbConnectionBroadcastReceiver.java b/src/com/android/settings/connecteddevice/UsbConnectionBroadcastReceiver.java new file mode 100644 index 00000000000..07a76915af4 --- /dev/null +++ b/src/com/android/settings/connecteddevice/UsbConnectionBroadcastReceiver.java @@ -0,0 +1,76 @@ +/* + * 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.connecteddevice; + + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.usb.UsbManager; + +/** + * Receiver to receive usb update and use {@link UsbConnectionListener} to invoke callback + */ +public class UsbConnectionBroadcastReceiver extends BroadcastReceiver { + private Context mContext; + private UsbConnectionListener mUsbConnectionListener; + private boolean mListeningToUsbEvents; + private boolean mConnected; + + public UsbConnectionBroadcastReceiver(Context context, + UsbConnectionListener usbConnectionListener) { + mContext = context; + mUsbConnectionListener = usbConnectionListener; + } + + @Override + public void onReceive(Context context, Intent intent) { + mConnected = intent != null + && intent.getExtras().getBoolean(UsbManager.USB_CONNECTED); + if (mUsbConnectionListener != null) { + mUsbConnectionListener.onUsbConnectionChanged(mConnected); + } + } + + public void register() { + if (!mListeningToUsbEvents) { + final IntentFilter intentFilter = new IntentFilter(UsbManager.ACTION_USB_STATE); + final Intent intent = mContext.registerReceiver(this, intentFilter); + mConnected = intent != null + && intent.getExtras().getBoolean(UsbManager.USB_CONNECTED); + mListeningToUsbEvents = true; + } + } + + public void unregister() { + if (mListeningToUsbEvents) { + mContext.unregisterReceiver(this); + mListeningToUsbEvents = false; + } + } + + public boolean isConnected() { + return mConnected; + } + + /** + * Interface definition for a callback to be invoked when usb connection is changed. + */ + interface UsbConnectionListener { + void onUsbConnectionChanged(boolean connected); + } +} diff --git a/src/com/android/settings/connecteddevice/UsbModePreferenceController.java b/src/com/android/settings/connecteddevice/UsbModePreferenceController.java index a6cb9be1e7f..869352006c5 100644 --- a/src/com/android/settings/connecteddevice/UsbModePreferenceController.java +++ b/src/com/android/settings/connecteddevice/UsbModePreferenceController.java @@ -15,17 +15,12 @@ */ package com.android.settings.connecteddevice; -import android.content.BroadcastReceiver; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.hardware.usb.UsbManager; -import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; -import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.R; +import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.deviceinfo.UsbBackend; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; @@ -44,19 +39,21 @@ public class UsbModePreferenceController extends AbstractPreferenceController public UsbModePreferenceController(Context context, UsbBackend usbBackend) { super(context); mUsbBackend = usbBackend; - mUsbReceiver = new UsbConnectionBroadcastReceiver(); + mUsbReceiver = new UsbConnectionBroadcastReceiver(mContext, (connected) -> { + updateSummary(mUsbPreference); + }); } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mUsbPreference = screen.findPreference(KEY_USB_MODE); - updataSummary(mUsbPreference); + updateSummary(mUsbPreference); } @Override public void updateState(Preference preference) { - updataSummary(preference); + updateSummary(preference); } @Override @@ -79,8 +76,7 @@ public class UsbModePreferenceController extends AbstractPreferenceController mUsbReceiver.register(); } - @VisibleForTesting - int getSummary(int mode) { + public static int getSummary(int mode) { switch (mode) { case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE: return R.string.usb_summary_charging_only; @@ -96,11 +92,11 @@ public class UsbModePreferenceController extends AbstractPreferenceController return 0; } - private void updataSummary(Preference preference) { - updataSummary(preference, mUsbBackend.getCurrentMode()); + private void updateSummary(Preference preference) { + updateSummary(preference, mUsbBackend.getCurrentMode()); } - private void updataSummary(Preference preference, int mode) { + private void updateSummary(Preference preference, int mode) { if (preference != null) { if (mUsbReceiver.isConnected()) { preference.setEnabled(true); @@ -112,40 +108,4 @@ public class UsbModePreferenceController extends AbstractPreferenceController } } - private class UsbConnectionBroadcastReceiver extends BroadcastReceiver { - private boolean mListeningToUsbEvents; - private boolean mConnected; - - @Override - public void onReceive(Context context, Intent intent) { - boolean connected = intent != null - && intent.getExtras().getBoolean(UsbManager.USB_CONNECTED); - if (connected != mConnected) { - mConnected = connected; - updataSummary(mUsbPreference); - } - } - - public void register() { - if (!mListeningToUsbEvents) { - IntentFilter intentFilter = new IntentFilter(UsbManager.ACTION_USB_STATE); - Intent intent = mContext.registerReceiver(this, intentFilter); - mConnected = intent != null - && intent.getExtras().getBoolean(UsbManager.USB_CONNECTED); - mListeningToUsbEvents = true; - } - } - - public void unregister() { - if (mListeningToUsbEvents) { - mContext.unregisterReceiver(this); - mListeningToUsbEvents = false; - } - } - - public boolean isConnected() { - return mConnected; - } - } - } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java index f9efc0bf64d..aa5eb67342f 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java @@ -37,6 +37,7 @@ import com.android.settingslib.core.lifecycle.Lifecycle; 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; @@ -45,13 +46,17 @@ import org.robolectric.annotation.Config; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class ConnectedDeviceGroupControllerTest { + private static final String PREFERENCE_KEY_1 = "pref_key_1"; + @Mock private DashboardFragment mDashboardFragment; @Mock private ConnectedBluetoothDeviceUpdater mConnectedBluetoothDeviceUpdater; @Mock - private PreferenceScreen mPreferenceScreen; + private ConnectedUsbDeviceUpdater mConnectedUsbDeviceUpdater; @Mock + private PreferenceScreen mPreferenceScreen; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) private PreferenceManager mPreferenceManager; private PreferenceGroup mPreferenceGroup; @@ -66,30 +71,33 @@ public class ConnectedDeviceGroupControllerTest { mContext = RuntimeEnvironment.application; mPreference = new Preference(mContext); + mPreference.setKey(PREFERENCE_KEY_1); mLifecycle = new Lifecycle(() -> mLifecycle); mPreferenceGroup = spy(new PreferenceScreen(mContext, null)); doReturn(mPreferenceManager).when(mPreferenceGroup).getPreferenceManager(); doReturn(mContext).when(mDashboardFragment).getContext(); mConnectedDeviceGroupController = new ConnectedDeviceGroupController(mDashboardFragment, - mLifecycle, mConnectedBluetoothDeviceUpdater); + mLifecycle, mConnectedBluetoothDeviceUpdater, mConnectedUsbDeviceUpdater); mConnectedDeviceGroupController.mPreferenceGroup = mPreferenceGroup; } @Test - public void testOnDeviceAdded_firstAdd_becomeVisible() { + public void testOnDeviceAdded_firstAdd_becomeVisibleAndPreferenceAdded() { mConnectedDeviceGroupController.onDeviceAdded(mPreference); assertThat(mPreferenceGroup.isVisible()).isTrue(); + assertThat(mPreferenceGroup.findPreference(PREFERENCE_KEY_1)).isEqualTo(mPreference); } @Test - public void testOnDeviceRemoved_lastRemove_becomeInvisible() { + public void testOnDeviceRemoved_lastRemove_becomeInvisibleAndPreferenceRemoved() { mPreferenceGroup.addPreference(mPreference); mConnectedDeviceGroupController.onDeviceRemoved(mPreference); assertThat(mPreferenceGroup.isVisible()).isFalse(); + assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0); } @Test @@ -117,9 +125,11 @@ public class ConnectedDeviceGroupControllerTest { // register the callback in onStart() mLifecycle.handleLifecycleEvent(android.arch.lifecycle.Lifecycle.Event.ON_START); verify(mConnectedBluetoothDeviceUpdater).registerCallback(); + verify(mConnectedUsbDeviceUpdater).registerCallback(); // unregister the callback in onStop() mLifecycle.handleLifecycleEvent(android.arch.lifecycle.Lifecycle.Event.ON_STOP); verify(mConnectedBluetoothDeviceUpdater).unregisterCallback(); + verify(mConnectedUsbDeviceUpdater).unregisterCallback(); } } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedUsbDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedUsbDeviceUpdaterTest.java new file mode 100644 index 00000000000..16cd3a7a94f --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedUsbDeviceUpdaterTest.java @@ -0,0 +1,89 @@ +/* + * 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.connecteddevice; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; + +import android.content.Context; + +import com.android.settings.R; +import com.android.settings.TestConfig; +import com.android.settings.deviceinfo.UsbBackend; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class ConnectedUsbDeviceUpdaterTest { + private Context mContext; + private ConnectedUsbDeviceUpdater mDeviceUpdater; + + @Mock + private UsbConnectionBroadcastReceiver mUsbReceiver; + @Mock + private DevicePreferenceCallback mDevicePreferenceCallback; + @Mock + private UsbBackend mUsbBackend; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = RuntimeEnvironment.application; + mDeviceUpdater = new ConnectedUsbDeviceUpdater(mContext, mDevicePreferenceCallback, + mUsbBackend); + mDeviceUpdater.mUsbReceiver = mUsbReceiver; + } + + @Test + public void testInitUsbPreference_preferenceInit() { + mDeviceUpdater.initUsbPreference(mContext); + + assertThat(mDeviceUpdater.mUsbPreference.getTitle()).isEqualTo("USB"); + assertThat(mDeviceUpdater.mUsbPreference.getIcon()).isEqualTo(mContext.getDrawable( + R.drawable.ic_usb)); + assertThat(mDeviceUpdater.mUsbPreference.isSelectable()).isFalse(); + } + + @Test + public void testInitUsbPreference_usbConnected_preferenceAdded() { + doReturn(true).when(mUsbReceiver).isConnected(); + + mDeviceUpdater.initUsbPreference(mContext); + + verify(mDevicePreferenceCallback).onDeviceAdded(mDeviceUpdater.mUsbPreference); + } + + @Test + public void testInitUsbPreference_usbDisconnected_preferenceRemoved() { + doReturn(false).when(mUsbReceiver).isConnected(); + + mDeviceUpdater.initUsbPreference(mContext); + + verify(mDevicePreferenceCallback).onDeviceRemoved(mDeviceUpdater.mUsbPreference); + } + +} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/connecteddevice/UsbConnectionBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/connecteddevice/UsbConnectionBroadcastReceiverTest.java new file mode 100644 index 00000000000..06bd5b7834d --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/UsbConnectionBroadcastReceiverTest.java @@ -0,0 +1,126 @@ +/* + * 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.connecteddevice; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.hardware.usb.UsbManager; + +import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import java.util.List; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class UsbConnectionBroadcastReceiverTest { + private Context mContext; + private UsbConnectionBroadcastReceiver mReceiver; + private ShadowApplication mShadowApplication; + + @Mock + private UsbConnectionBroadcastReceiver.UsbConnectionListener mListener; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mShadowApplication = ShadowApplication.getInstance(); + mContext = RuntimeEnvironment.application; + mReceiver = new UsbConnectionBroadcastReceiver(mContext, mListener); + } + + @Test + public void testOnReceive_usbConnected_invokeCallback() { + final Intent intent = new Intent(); + intent.putExtra(UsbManager.USB_CONNECTED, true); + + mReceiver.onReceive(mContext, intent); + + verify(mListener).onUsbConnectionChanged(true); + } + + @Test + public void testOnReceive_usbDisconnected_invokeCallback() { + final Intent intent = new Intent(); + intent.putExtra(UsbManager.USB_CONNECTED, false); + + mReceiver.onReceive(mContext, intent); + + verify(mListener).onUsbConnectionChanged(false); + } + + @Test + public void testRegister_invokeMethodTwice_registerOnce() { + mReceiver.register(); + mReceiver.register(); + + final List receivers = mShadowApplication.getReceiversForIntent( + new Intent(UsbManager.ACTION_USB_STATE)); + assertHasOneUsbConnectionBroadcastReceiver(receivers); + } + + @Test + public void testUnregister_invokeMethodTwice_unregisterOnce() { + mReceiver.register(); + mReceiver.unregister(); + mReceiver.unregister(); + + final List receivers = mShadowApplication.getReceiversForIntent( + new Intent(UsbManager.ACTION_USB_STATE)); + assertHasNoUsbConnectionBroadcastReceiver(receivers); + } + + private void assertHasOneUsbConnectionBroadcastReceiver(List receivers) { + boolean hasReceiver = false; + for (final BroadcastReceiver receiver : receivers) { + if (receiver instanceof UsbConnectionBroadcastReceiver) { + // If hasReceiver is true, then we're at the second copy of it so fail. + assertWithMessage( + "Only one instance of UsbConnectionBroadcastReceiver should be " + + "registered").that( + hasReceiver).isFalse(); + hasReceiver = true; + } + } + assertThat(hasReceiver).isTrue(); + } + + private void assertHasNoUsbConnectionBroadcastReceiver(List receivers) { + for (final BroadcastReceiver receiver : receivers) { + assertThat(receiver instanceof UsbConnectionBroadcastReceiver).isFalse(); + } + } +} \ No newline at end of file From d055937664bb023f509fd9c31f9b6ff43fd916b2 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Mon, 4 Dec 2017 13:57:31 -0800 Subject: [PATCH 2/2] Create BluetoothSwitchPreference In the new design, bluetooth preference is not MasterSwitchPreference any more. This cl creates BluetoothSwitchPreference while reuse the BluetoothEnabler. Future cl will remove the BluetoothMasterSwitchPreference when P feature is finalized. Bug: 69333961 Test: RunSettingsRoboTests Change-Id: Ie1f934b4e93a6758a1b0cf83bb5098585a635c2a --- res/values/strings.xml | 2 + res/xml/connected_devices_advanced.xml | 5 +- ...toothMasterSwitchPreferenceController.java | 1 + .../BluetoothSwitchPreferenceController.java | 161 ++++++++++++++++++ ...ancedConnectedDeviceDashboardFragment.java | 7 +- ...uetoothSwitchPreferenceControllerTest.java | 135 +++++++++++++++ 6 files changed, 305 insertions(+), 6 deletions(-) create mode 100644 src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 7331d7265f7..45aadf38d12 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -393,6 +393,8 @@ Your devices Pair new device + + Allow device to pair and connect to bluetooth devices Currently connected diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml index 946151f297e..57a2580c20e 100644 --- a/res/xml/connected_devices_advanced.xml +++ b/res/xml/connected_devices_advanced.xml @@ -19,10 +19,11 @@ android:key="connected_devices_screen" android:title="@string/connected_devices_dashboard_title"> -