From bd3e5de207b4b3e62e08a1b0ab506e0b686399e5 Mon Sep 17 00:00:00 2001 From: hughchen Date: Fri, 23 Mar 2018 16:14:13 +0800 Subject: [PATCH] Implement audio switch UI * Implement available media devices group * Add AvailableMediaDeviceGroupController to realize UI, the user can see the all device that can be activated in this group. * ConnectedDeviceGroupController change to show the device that cannot be activated but is connected. * Refactoring the below class, implement the controller in connected_devices.xml. ConnectedDeviceGroupController.java SavedDeviceGroupController.java ConnectedDeviceDashboardFragment.java connected_devices.xml * Add AvailableMediaBluetoothDeviceUpdaterTest to verify the add/remove preference behavior when connectedStateChanged or profileAudioStateChanged * Add test that used to verify device is connected or not in BluetoothDeviceUpdaterTest. * Add test that used to verify the add/remove preference behavior when connectedStateChanged or profileAudioStateChanged in ConnectedBluetoothDeviceUpdaterTest. * Add AvailableMediaDeviceGroupControllerTest to verify bluetooth feature is supported or not and test register callback. * Add test that used to verify bluetooth feature is supported or not and test register callback in ConnectedDeviceGroupControllerTest. * Add test that used to verify bluetooth feature is supported or not and test register callback in SavedDeviceGroupControllerTest Bug: 74134939 Test: make -j40 RunSettingsRoboTests Change-Id: I54d03c2ddadc6a4be7519dd74cdbcb5055d44083 --- res/xml/connected_devices.xml | 8 +- src/com/android/settings/Settings.java | 2 +- .../AvailableMediaBluetoothDeviceUpdater.java | 118 ++++++++++ .../bluetooth/BluetoothDeviceUpdater.java | 32 ++- .../ConnectedBluetoothDeviceUpdater.java | 70 +++++- .../AvailableMediaDeviceGroupController.java | 108 +++++++++ .../ConnectedDeviceDashboardFragment.java | 20 +- .../ConnectedDeviceGroupController.java | 24 +- .../SavedDeviceGroupController.java | 12 +- ...lid_base_preference_controller_constructor | 2 - ...ilableMediaBluetoothDeviceUpdaterTest.java | 211 ++++++++++++++++++ .../bluetooth/BluetoothDeviceUpdaterTest.java | 35 ++- .../ConnectedBluetoothDeviceUpdaterTest.java | 128 ++++++++++- ...ailableMediaDeviceGroupControllerTest.java | 154 +++++++++++++ .../ConnectedDeviceDashboardFragmentTest.java | 6 +- .../ConnectedDeviceGroupControllerTest.java | 42 ++-- .../SavedDeviceGroupControllerTest.java | 13 +- .../testutils/shadow/ShadowAudioManager.java | 49 +++- 18 files changed, 949 insertions(+), 85 deletions(-) create mode 100644 src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java create mode 100644 src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupController.java create mode 100644 tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java create mode 100644 tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java diff --git a/res/xml/connected_devices.xml b/res/xml/connected_devices.xml index 4a3c4f286a5..5b371faf8d6 100644 --- a/res/xml/connected_devices.xml +++ b/res/xml/connected_devices.xml @@ -20,9 +20,15 @@ android:key="connected_devices_screen" android:title="@string/connected_devices_dashboard_title"> + + + android:title="@string/connected_device_connected_title" + settings:controller="com.android.settings.connecteddevice.ConnectedDeviceGroupController"/> createPreferenceControllers(Context context) { - return buildPreferenceControllers(context, getLifecycle(), this); + return buildPreferenceControllers(context, getLifecycle()); } private static List buildPreferenceControllers(Context context, - Lifecycle lifecycle, DashboardFragment dashboardFragment) { + Lifecycle lifecycle) { final List controllers = new ArrayList<>(); - controllers.add(new ConnectedDeviceGroupController(context, dashboardFragment, lifecycle)); - final NfcPreferenceController nfcPreferenceController = new NfcPreferenceController(context); controllers.add(nfcPreferenceController); @@ -83,6 +81,13 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment { return controllers; } + @Override + public void onAttach(Context context) { + super.onAttach(context); + use(AvailableMediaDeviceGroupController.class).init(this); + use(ConnectedDeviceGroupController.class).init(this); + } + @VisibleForTesting static class SummaryProvider implements SummaryLoader.SummaryProvider { @@ -136,16 +141,15 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment { @Override public List createPreferenceControllers(Context context) { - return buildPreferenceControllers(context, null /* lifecycle */, - null /* dashboardFragment */); + return buildPreferenceControllers(context, null /* lifecycle */); } @Override public List getNonIndexableKeys(Context context) { List keys = super.getNonIndexableKeys(context); // Disable because they show dynamic data + keys.add(KEY_AVAILABLE_DEVICES); keys.add(KEY_CONNECTED_DEVICES); - keys.add(KEY_SAVED_DEVICES); return keys; } }; diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java b/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java index 731acae663f..3a1aa056ca1 100644 --- a/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java +++ b/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java @@ -48,19 +48,8 @@ public class ConnectedDeviceGroupController extends BasePreferenceController private BluetoothDeviceUpdater mBluetoothDeviceUpdater; private ConnectedUsbDeviceUpdater mConnectedUsbDeviceUpdater; - public ConnectedDeviceGroupController(Context context, DashboardFragment fragment, - Lifecycle lifecycle) { + public ConnectedDeviceGroupController(Context context) { super(context, KEY); - init(lifecycle, new ConnectedBluetoothDeviceUpdater(context, fragment, this), - new ConnectedUsbDeviceUpdater(context, fragment, this)); - } - - @VisibleForTesting - ConnectedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle, - BluetoothDeviceUpdater bluetoothDeviceUpdater, - ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater) { - super(fragment.getContext(), KEY); - init(lifecycle, bluetoothDeviceUpdater, connectedUsbDeviceUpdater); } @Override @@ -116,12 +105,15 @@ public class ConnectedDeviceGroupController extends BasePreferenceController } } - private void init(Lifecycle lifecycle, BluetoothDeviceUpdater bluetoothDeviceUpdater, + @VisibleForTesting + public void init(BluetoothDeviceUpdater bluetoothDeviceUpdater, ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater) { - if (lifecycle != null && isAvailable()) { - lifecycle.addObserver(this); - } mBluetoothDeviceUpdater = bluetoothDeviceUpdater; mConnectedUsbDeviceUpdater = connectedUsbDeviceUpdater; } + + public void init(DashboardFragment fragment) { + init(new ConnectedBluetoothDeviceUpdater(fragment.getContext(), fragment, this), + new ConnectedUsbDeviceUpdater(fragment.getContext(), fragment, this)); + } } diff --git a/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java b/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java index d045c9ec22d..b1f83601013 100644 --- a/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java +++ b/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java @@ -50,13 +50,6 @@ public class SavedDeviceGroupController extends BasePreferenceController super(context, KEY); } - @VisibleForTesting - SavedDeviceGroupController(DashboardFragment fragment, - BluetoothDeviceUpdater bluetoothDeviceUpdater) { - super(fragment.getContext(), KEY); - mBluetoothDeviceUpdater = bluetoothDeviceUpdater; - } - @Override public void onStart() { mBluetoothDeviceUpdater.registerCallback(); @@ -109,4 +102,9 @@ public class SavedDeviceGroupController extends BasePreferenceController mBluetoothDeviceUpdater = new SavedBluetoothDeviceUpdater(fragment.getContext(), fragment, SavedDeviceGroupController.this); } + + @VisibleForTesting + public void setBluetoothDeviceUpdater(BluetoothDeviceUpdater bluetoothDeviceUpdater) { + mBluetoothDeviceUpdater = bluetoothDeviceUpdater; + } } diff --git a/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor b/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor index 7faa14afcdd..c2b3da98a1f 100644 --- a/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor +++ b/tests/robotests/assets/grandfather_invalid_base_preference_controller_constructor @@ -5,8 +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.connecteddevice.ConnectedDeviceGroupController -com.android.settings.connecteddevice.SavedDeviceGroupController com.android.settings.datausage.DataUsageSummaryPreferenceController com.android.settings.fuelgauge.RestrictAppPreferenceController com.android.settings.fuelgauge.batterysaver.AutoBatterySeekBarPreferenceController diff --git a/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java new file mode 100644 index 00000000000..fbc698c548b --- /dev/null +++ b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java @@ -0,0 +1,211 @@ +/* + * Copyright 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.bluetooth; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.content.Context; + +import android.media.AudioManager; +import com.android.settings.connecteddevice.DevicePreferenceCallback; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import com.android.settings.testutils.shadow.ShadowAudioManager; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.HeadsetProfile; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; +import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; + +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 java.util.ArrayList; +import java.util.Collection; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(shadows = {ShadowAudioManager.class}) +public class AvailableMediaBluetoothDeviceUpdaterTest { + @Mock + private DashboardFragment mDashboardFragment; + @Mock + private DevicePreferenceCallback mDevicePreferenceCallback; + @Mock + private CachedBluetoothDevice mCachedBluetoothDevice; + @Mock + private BluetoothDevice mBluetoothDevice; + @Mock + private LocalBluetoothManager mLocalManager; + @Mock + private LocalBluetoothProfileManager mLocalBluetoothProfileManager; + @Mock + private HeadsetProfile mHeadsetProfile; + @Mock + private CachedBluetoothDeviceManager mCachedDeviceManager; + + private Context mContext; + private AvailableMediaBluetoothDeviceUpdater mBluetoothDeviceUpdater; + private Collection cachedDevices; + private ShadowAudioManager mShadowAudioManager; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mShadowAudioManager = ShadowAudioManager.getShadow(); + mContext = RuntimeEnvironment.application; + doReturn(mContext).when(mDashboardFragment).getContext(); + cachedDevices = + new ArrayList(new ArrayList()); + + when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + when(mLocalManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); + when(mLocalBluetoothProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile); + when(mLocalManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); + when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices); + + mBluetoothDeviceUpdater = spy(new AvailableMediaBluetoothDeviceUpdater(mDashboardFragment, + mDevicePreferenceCallback, mLocalManager)); + mBluetoothDeviceUpdater.setPrefContext(mContext); + doNothing().when(mBluetoothDeviceUpdater).addPreference(any()); + doNothing().when(mBluetoothDeviceUpdater).removePreference(any()); + } + + @Test + public void onAudioModeChanged_hfpDeviceConnected_inCall_addPreference() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true); + cachedDevices.add(mCachedBluetoothDevice); + + mBluetoothDeviceUpdater.onAudioModeChanged(); + + verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); + } + + @Test + public void onAudioModeChanged_hfpDeviceConnected_notInCall_removePreference() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true); + cachedDevices.add(mCachedBluetoothDevice); + + mBluetoothDeviceUpdater.onAudioModeChanged(); + + verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); + } + + @Test + public void onAudioModeChanged_a2dpDeviceConnected_inCall_removePreference() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true); + cachedDevices.add(mCachedBluetoothDevice); + + mBluetoothDeviceUpdater.onAudioModeChanged(); + + verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); + } + + @Test + public void onAudioModeChanged_a2dpDeviceConnected_notInCall_addPreference() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true); + cachedDevices.add(mCachedBluetoothDevice); + + mBluetoothDeviceUpdater.onAudioModeChanged(); + + verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); + } + + @Test + public void onConnectionStateChanged_a2dpDeviceConnected_notInCall_addPreference() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true); + + mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice, + BluetoothAdapter.STATE_CONNECTED); + + verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); + } + + @Test + public void onConnectionStateChanged_a2dpDeviceConnected_inCall_removePreference() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true); + + mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice, + BluetoothAdapter.STATE_CONNECTED); + + verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); + } + @Test + public void onConnectionStateChanged_hfpDeviceConnected_notInCall_removePreference() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true); + + mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice, + BluetoothAdapter.STATE_CONNECTED); + + verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); + } + + @Test + public void onConnectionStateChanged_hfpDeviceConnected_inCall_addPreference() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true); + + mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice, + BluetoothAdapter.STATE_CONNECTED); + + verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); + } + + @Test + public void onConnectionStateChanged_deviceDisconnected_removePreference() { + mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice, + BluetoothAdapter.STATE_DISCONNECTED); + + verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); + } +} + diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java index 5334833dc4c..f4c34269286 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.support.v7.preference.Preference; @@ -32,7 +33,11 @@ import com.android.settings.connecteddevice.DevicePreferenceCallback; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.HeadsetProfile; +import com.android.settingslib.bluetooth.A2dpProfile; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -54,6 +59,14 @@ public class BluetoothDeviceUpdaterTest { private BluetoothDevice mBluetoothDevice; @Mock private SettingsActivity mSettingsActivity; + @Mock + private LocalBluetoothManager mLocalManager; + @Mock + private LocalBluetoothProfileManager mLocalBluetoothProfileManager; + @Mock + private HeadsetProfile mHeadsetProfile; + @Mock + private A2dpProfile mA2dpProfile; private Context mContext; private BluetoothDeviceUpdater mBluetoothDeviceUpdater; @@ -66,10 +79,14 @@ public class BluetoothDeviceUpdaterTest { mContext = RuntimeEnvironment.application; doReturn(mContext).when(mDashboardFragment).getContext(); when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + when(mLocalManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); + when(mLocalBluetoothProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile); + when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile); mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, false); mBluetoothDeviceUpdater = - new BluetoothDeviceUpdater(mDashboardFragment, mDevicePreferenceCallback, null) { + new BluetoothDeviceUpdater(mDashboardFragment, mDevicePreferenceCallback, + mLocalManager) { @Override public boolean isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice) { return true; @@ -124,4 +141,20 @@ public class BluetoothDeviceUpdaterTest { assertThat(intentCaptor.getValue().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)) .isEqualTo(BluetoothDeviceDetailsFragment.class.getName()); } + + @Test + public void isDeviceConnected_deviceConnected() { + doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState(); + doReturn(true).when(mBluetoothDevice).isConnected(); + + assertThat(mBluetoothDeviceUpdater.isDeviceConnected(mCachedBluetoothDevice)).isTrue(); + } + + @Test + public void isDeviceConnected_deviceNotConnected() { + doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState(); + doReturn(false).when(mBluetoothDevice).isConnected(); + + assertThat(mBluetoothDeviceUpdater.isDeviceConnected(mCachedBluetoothDevice)).isFalse(); + } } diff --git a/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java index 036f09dcdfe..9d69f59b7d3 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdaterTest.java @@ -26,10 +26,16 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Context; +import android.media.AudioManager; import com.android.settings.connecteddevice.DevicePreferenceCallback; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowAudioManager; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.HeadsetProfile; +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; +import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import org.junit.Before; import org.junit.Test; @@ -37,10 +43,14 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import java.util.ArrayList; +import java.util.Collection; @RunWith(SettingsRobolectricTestRunner.class) +@Config(shadows = {ShadowAudioManager.class}) public class ConnectedBluetoothDeviceUpdaterTest { - @Mock private DashboardFragment mDashboardFragment; @Mock @@ -49,47 +59,103 @@ public class ConnectedBluetoothDeviceUpdaterTest { private CachedBluetoothDevice mCachedBluetoothDevice; @Mock private BluetoothDevice mBluetoothDevice; + @Mock + private LocalBluetoothManager mLocalManager; + @Mock + private LocalBluetoothProfileManager mLocalBluetoothProfileManager; + @Mock + private HeadsetProfile mHeadsetProfile; private Context mContext; private ConnectedBluetoothDeviceUpdater mBluetoothDeviceUpdater; + @Mock + private CachedBluetoothDeviceManager mCachedDeviceManager; + + private Collection cachedDevices; + private ShadowAudioManager mShadowAudioManager; @Before public void setUp() { MockitoAnnotations.initMocks(this); + mShadowAudioManager = ShadowAudioManager.getShadow(); mContext = RuntimeEnvironment.application; doReturn(mContext).when(mDashboardFragment).getContext(); + cachedDevices = + new ArrayList(new ArrayList()); + when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); + when(mLocalManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); + when(mLocalBluetoothProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile); + when(mLocalManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); + when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices); mBluetoothDeviceUpdater = spy(new ConnectedBluetoothDeviceUpdater(mDashboardFragment, - mDevicePreferenceCallback, null)); + mDevicePreferenceCallback, mLocalManager)); mBluetoothDeviceUpdater.setPrefContext(mContext); doNothing().when(mBluetoothDeviceUpdater).addPreference(any()); doNothing().when(mBluetoothDeviceUpdater).removePreference(any()); } @Test - public void testUpdate_filterMatch_addPreference() { - doReturn(BluetoothDevice.BOND_BONDED).when(mBluetoothDevice).getBondState(); - doReturn(true).when(mBluetoothDevice).isConnected(); + public void onAudioModeChanged_hfpDeviceConnected_notInCall_addPreference() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true); + cachedDevices.add(mCachedBluetoothDevice); - mBluetoothDeviceUpdater.update(mCachedBluetoothDevice); + mBluetoothDeviceUpdater.onAudioModeChanged(); verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); } @Test - public void testUpdate_filterNotMatch_removePreference() { - doReturn(BluetoothDevice.BOND_NONE).when(mBluetoothDevice).getBondState(); - doReturn(false).when(mBluetoothDevice).isConnected(); + public void onAudioModeChanged_hfpDeviceConnected_inCall_removePreference() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true); + cachedDevices.add(mCachedBluetoothDevice); - mBluetoothDeviceUpdater.update(mCachedBluetoothDevice); + mBluetoothDeviceUpdater.onAudioModeChanged(); verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); } @Test - public void testOnConnectionStateChanged_deviceConnected_addPreference() { + public void onAudioModeChanged_a2dpDeviceConnected_notInCall_removePreference() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true); + cachedDevices.add(mCachedBluetoothDevice); + + mBluetoothDeviceUpdater.onAudioModeChanged(); + + verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); + } + + @Test + public void onAudioModeChanged_a2dpDeviceConnected_inCall_addPreference() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true); + cachedDevices.add(mCachedBluetoothDevice); + + mBluetoothDeviceUpdater.onAudioModeChanged(); + + verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); + } + + @Test + public void onConnectionStateChanged_a2dpDeviceConnected_inCall_addPreference() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true); + mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice, BluetoothAdapter.STATE_CONNECTED); @@ -97,7 +163,45 @@ public class ConnectedBluetoothDeviceUpdaterTest { } @Test - public void testOnConnectionStateChanged_deviceDisconnected_removePreference() { + public void onConnectionStateChanged_a2dpDeviceConnected_notInCall_removePreference() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true); + + mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice, + BluetoothAdapter.STATE_CONNECTED); + + verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); + } + @Test + public void onConnectionStateChanged_hfpDeviceConnected_inCall_removePreference() { + mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true); + + mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice, + BluetoothAdapter.STATE_CONNECTED); + + verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); + } + + @Test + public void onConnectionStateChanged_hfpDeviceConnected_notInCall_addPreference() { + mShadowAudioManager.setMode(AudioManager.MODE_NORMAL); + when(mBluetoothDeviceUpdater. + isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true); + when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true); + + mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice, + BluetoothAdapter.STATE_CONNECTED); + + verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); + } + + @Test + public void onConnectionStateChanged_deviceDisconnected_removePreference() { mBluetoothDeviceUpdater.onConnectionStateChanged(mCachedBluetoothDevice, BluetoothAdapter.STATE_DISCONNECTED); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java new file mode 100644 index 00000000000..4e6d5e59113 --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java @@ -0,0 +1,154 @@ +/* + * Copyright 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 static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceGroup; +import android.support.v7.preference.PreferenceManager; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.bluetooth.AvailableMediaBluetoothDeviceUpdater; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +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; + +@RunWith(SettingsRobolectricTestRunner.class) +public class AvailableMediaDeviceGroupControllerTest { + + private static final String PREFERENCE_KEY_1 = "pref_key_1"; + + @Mock + private DashboardFragment mDashboardFragment; + @Mock + private AvailableMediaBluetoothDeviceUpdater mAvailableMediaBluetoothDeviceUpdater; + @Mock + private PreferenceScreen mPreferenceScreen; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private PreferenceManager mPreferenceManager; + @Mock + private PackageManager mPackageManager; + + private PreferenceGroup mPreferenceGroup; + private Context mContext; + private Preference mPreference; + private AvailableMediaDeviceGroupController mAvailableMediaDeviceGroupController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + mPreference = new Preference(mContext); + mPreference.setKey(PREFERENCE_KEY_1); + mPreferenceGroup = spy(new PreferenceScreen(mContext, null)); + when(mPreferenceGroup.getPreferenceManager()).thenReturn(mPreferenceManager); + doReturn(mContext).when(mDashboardFragment).getContext(); + doReturn(mPackageManager).when(mContext).getPackageManager(); + doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); + + mAvailableMediaDeviceGroupController = new AvailableMediaDeviceGroupController(mContext); + mAvailableMediaDeviceGroupController. + setBluetoothDeviceUpdater(mAvailableMediaBluetoothDeviceUpdater); + mAvailableMediaDeviceGroupController.mPreferenceGroup = mPreferenceGroup; + } + + @Test + public void onDeviceAdded_firstAdd_becomeVisibleAndPreferenceAdded() { + mAvailableMediaDeviceGroupController.onDeviceAdded(mPreference); + + assertThat(mPreferenceGroup.isVisible()).isTrue(); + assertThat(mPreferenceGroup.findPreference(PREFERENCE_KEY_1)).isEqualTo(mPreference); + } + + @Test + public void onDeviceRemoved_lastRemove_becomeInvisibleAndPreferenceRemoved() { + mPreferenceGroup.addPreference(mPreference); + + mAvailableMediaDeviceGroupController.onDeviceRemoved(mPreference); + + assertThat(mPreferenceGroup.isVisible()).isFalse(); + assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0); + } + + @Test + public void onDeviceRemoved_notLastRemove_stillVisible() { + mPreferenceGroup.setVisible(true); + mPreferenceGroup.addPreference(mPreference); + mPreferenceGroup.addPreference(new Preference(mContext)); + + mAvailableMediaDeviceGroupController.onDeviceRemoved(mPreference); + + assertThat(mPreferenceGroup.isVisible()).isTrue(); + } + + @Test + public void displayPreference_becomeInvisible() { + doReturn(mPreferenceGroup).when(mPreferenceScreen).findPreference(anyString()); + + mAvailableMediaDeviceGroupController.displayPreference(mPreferenceScreen); + + assertThat(mPreferenceGroup.isVisible()).isFalse(); + } + + @Test + public void testRegister() { + // register the callback in onStart() + mAvailableMediaDeviceGroupController.onStart(); + verify(mAvailableMediaBluetoothDeviceUpdater).registerCallback(); + } + + @Test + public void testUnregister() { + // unregister the callback in onStop() + mAvailableMediaDeviceGroupController.onStop(); + verify(mAvailableMediaBluetoothDeviceUpdater).unregisterCallback(); + } + + @Test + public void testGetAvailabilityStatus_noBluetoothFeature_returnUnSupported() { + doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); + + assertThat(mAvailableMediaDeviceGroupController.getAvailabilityStatus()).isEqualTo( + DISABLED_UNSUPPORTED); + } + + @Test + public void testGetAvailabilityStatus_BluetoothFeature_returnSupported() { + doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); + + assertThat(mAvailableMediaDeviceGroupController.getAvailabilityStatus()).isEqualTo( + AVAILABLE); + } +} diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java index 443e885eb4d..0230540a61c 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java @@ -16,9 +16,9 @@ package com.android.settings.connecteddevice; import static com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment - .KEY_CONNECTED_DEVICES; + .KEY_AVAILABLE_DEVICES; import static com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment - .KEY_SAVED_DEVICES; + .KEY_CONNECTED_DEVICES; import static com.google.common.truth.Truth.assertThat; @@ -78,7 +78,7 @@ public class ConnectedDeviceDashboardFragmentTest { final List niks = ConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER .getNonIndexableKeys(mContext); - assertThat(niks).containsExactly(KEY_CONNECTED_DEVICES, KEY_SAVED_DEVICES, + assertThat(niks).containsExactly(KEY_CONNECTED_DEVICES, KEY_AVAILABLE_DEVICES, NfcPreferenceController.KEY_TOGGLE_NFC); } } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java index 373c255236c..e3e11bcf8f5 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java @@ -15,6 +15,7 @@ */ package com.android.settings.connecteddevice; +import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED; import static com.google.common.truth.Truth.assertThat; @@ -45,8 +46,12 @@ import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; +import org.robolectric.Shadows; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplicationPackageManager; @RunWith(SettingsRobolectricTestRunner.class) +@Config(shadows = ShadowApplicationPackageManager.class) public class ConnectedDeviceGroupControllerTest { private static final String PREFERENCE_KEY_1 = "pref_key_1"; @@ -61,33 +66,29 @@ public class ConnectedDeviceGroupControllerTest { private PreferenceScreen mPreferenceScreen; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private PreferenceManager mPreferenceManager; - @Mock - private PackageManager mPackageManager; + private ShadowApplicationPackageManager mPackageManager; private PreferenceGroup mPreferenceGroup; private Context mContext; private Preference mPreference; private ConnectedDeviceGroupController mConnectedDeviceGroupController; - private LifecycleOwner mLifecycleOwner; - private Lifecycle mLifecycle; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mContext = spy(RuntimeEnvironment.application); + mContext = RuntimeEnvironment.application; mPreference = new Preference(mContext); mPreference.setKey(PREFERENCE_KEY_1); - mLifecycleOwner = () -> mLifecycle; - mLifecycle = new Lifecycle(mLifecycleOwner); + mPackageManager = (ShadowApplicationPackageManager) Shadows.shadowOf( + mContext.getPackageManager()); mPreferenceGroup = spy(new PreferenceScreen(mContext, null)); when(mPreferenceGroup.getPreferenceManager()).thenReturn(mPreferenceManager); doReturn(mContext).when(mDashboardFragment).getContext(); - doReturn(mPackageManager).when(mContext).getPackageManager(); - doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); - mConnectedDeviceGroupController = new ConnectedDeviceGroupController(mDashboardFragment, - mLifecycle, mConnectedBluetoothDeviceUpdater, mConnectedUsbDeviceUpdater); + mConnectedDeviceGroupController = new ConnectedDeviceGroupController(mContext); + mConnectedDeviceGroupController + .init(mConnectedBluetoothDeviceUpdater, mConnectedUsbDeviceUpdater); mConnectedDeviceGroupController.mPreferenceGroup = mPreferenceGroup; } @@ -130,23 +131,34 @@ public class ConnectedDeviceGroupControllerTest { } @Test - public void testLifecycle() { + public void testRegister() { // register the callback in onStart() - mLifecycle.handleLifecycleEvent(android.arch.lifecycle.Lifecycle.Event.ON_START); + mConnectedDeviceGroupController.onStart(); verify(mConnectedBluetoothDeviceUpdater).registerCallback(); verify(mConnectedUsbDeviceUpdater).registerCallback(); + } + @Test + public void testUnregister() { // unregister the callback in onStop() - mLifecycle.handleLifecycleEvent(android.arch.lifecycle.Lifecycle.Event.ON_STOP); + mConnectedDeviceGroupController.onStop(); verify(mConnectedBluetoothDeviceUpdater).unregisterCallback(); verify(mConnectedUsbDeviceUpdater).unregisterCallback(); } @Test public void testGetAvailabilityStatus_noBluetoothFeature_returnUnSupported() { - doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); + mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, false); assertThat(mConnectedDeviceGroupController.getAvailabilityStatus()).isEqualTo( DISABLED_UNSUPPORTED); } + + @Test + public void testGetAvailabilityStatus_BluetoothFeature_returnSupported() { + mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, true); + + assertThat(mConnectedDeviceGroupController.getAvailabilityStatus()).isEqualTo( + AVAILABLE); + } } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/SavedDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/SavedDeviceGroupControllerTest.java index a0d3d7bc574..1b1b88dc6bd 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/SavedDeviceGroupControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/SavedDeviceGroupControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright 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. @@ -14,9 +14,11 @@ * limitations under the License */ package com.android.settings.connecteddevice; + import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED; import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -28,6 +30,7 @@ import com.android.settings.bluetooth.BluetoothDeviceUpdater; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settingslib.core.lifecycle.Lifecycle; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,6 +42,7 @@ import org.robolectric.RuntimeEnvironment; @RunWith(SettingsRobolectricTestRunner.class) public class SavedDeviceGroupControllerTest { private static final String PREFERENCE_KEY_1 = "pref_key_1"; + @Mock private DashboardFragment mDashboardFragment; @Mock @@ -47,10 +51,12 @@ public class SavedDeviceGroupControllerTest { private PreferenceManager mPreferenceManager; @Mock private PackageManager mPackageManager; + private Context mContext; private SavedDeviceGroupController mSavedDeviceGroupController; private LifecycleOwner mLifecycleOwner; private Lifecycle mLifecycle; + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -59,9 +65,10 @@ public class SavedDeviceGroupControllerTest { mLifecycle = new Lifecycle(mLifecycleOwner); doReturn(mContext).when(mDashboardFragment).getContext(); doReturn(mPackageManager).when(mContext).getPackageManager(); - mSavedDeviceGroupController = new SavedDeviceGroupController(mDashboardFragment, - mBluetoothDeviceUpdater); + mSavedDeviceGroupController = new SavedDeviceGroupController(mContext); + mSavedDeviceGroupController.setBluetoothDeviceUpdater(mBluetoothDeviceUpdater); } + @Test public void testRegister() { // register the callback in onStart() diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java index ed53eeaaf54..6817648f09b 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java @@ -16,23 +16,58 @@ package com.android.settings.testutils.shadow; +import static org.robolectric.RuntimeEnvironment.application; + +import android.media.AudioDeviceCallback; import android.media.AudioManager; +import android.os.Handler; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; +import org.robolectric.shadow.api.Shadow; -@Implements(AudioManager.class) -public class ShadowAudioManager { +import java.util.ArrayList; +@Implements(value = AudioManager.class, inheritImplementationMethods = true) +public class ShadowAudioManager extends org.robolectric.shadows.ShadowAudioManager { private int mRingerMode; - - @Implementation - public void setRingerModeInternal(int mode) { - mRingerMode = mode; - } + private boolean mMusicActiveRemotely = false; + private ArrayList mDeviceCallbacks = new ArrayList(); @Implementation private int getRingerModeInternal() { return mRingerMode; } + + public static ShadowAudioManager getShadow() { + return Shadow.extract(application.getSystemService(AudioManager.class)); + } + + public void setRingerModeInternal(int mode) { + mRingerMode = mode; + } + + public void registerAudioDeviceCallback(AudioDeviceCallback callback, Handler handler) { + mDeviceCallbacks.add(callback); + } + + public void unregisterAudioDeviceCallback(AudioDeviceCallback callback) { + if (mDeviceCallbacks.contains(callback)) { + mDeviceCallbacks.remove(callback); + } + } + + public void setMusicActiveRemotely(boolean flag) { + mMusicActiveRemotely = flag; + } + + public boolean isMusicActiveRemotely() { + return mMusicActiveRemotely; + } + + @Resetter + public void reset() { + mDeviceCallbacks.clear(); + } }