diff --git a/src/com/android/settings/media/MediaOutputIndicatorSlice.java b/src/com/android/settings/media/MediaOutputIndicatorSlice.java index de2f85fae16..860a933ee4e 100644 --- a/src/com/android/settings/media/MediaOutputIndicatorSlice.java +++ b/src/com/android/settings/media/MediaOutputIndicatorSlice.java @@ -20,51 +20,33 @@ import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDIC import android.annotation.ColorInt; import android.app.PendingIntent; -import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.media.session.MediaController; import android.net.Uri; -import android.util.Log; import androidx.core.graphics.drawable.IconCompat; import androidx.slice.Slice; import androidx.slice.builders.ListBuilder; import androidx.slice.builders.SliceAction; -import com.android.internal.util.CollectionUtils; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.slices.CustomSliceable; import com.android.settings.slices.SliceBackgroundWorker; import com.android.settings.slices.SliceBroadcastReceiver; -import com.android.settingslib.bluetooth.A2dpProfile; -import com.android.settingslib.bluetooth.HearingAidProfile; -import com.android.settingslib.bluetooth.LocalBluetoothManager; -import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.settingslib.media.MediaOutputSliceConstants; -import java.util.ArrayList; -import java.util.List; - public class MediaOutputIndicatorSlice implements CustomSliceable { - private static final String TAG = "MediaOutputIndicatorSlice"; + private static final String TAG = "MediaOutputIndSlice"; private Context mContext; - private LocalBluetoothManager mLocalBluetoothManager; - private LocalBluetoothProfileManager mProfileManager; private MediaOutputIndicatorWorker mWorker; public MediaOutputIndicatorSlice(Context context) { mContext = context; - mLocalBluetoothManager = com.android.settings.bluetooth.Utils.getLocalBtManager(context); - if (mLocalBluetoothManager == null) { - Log.e(TAG, "Bluetooth is not supported on this device"); - return; - } - mProfileManager = mLocalBluetoothManager.getProfileManager(); } @Override @@ -86,7 +68,7 @@ public class MediaOutputIndicatorSlice implements CustomSliceable { .addRow(new ListBuilder.RowBuilder() .setTitle(title) .setTitleItem(createEmptyIcon(), ListBuilder.ICON_IMAGE) - .setSubtitle(findActiveDeviceName()) + .setSubtitle(getWorker().getCurrentConnectedMediaDevice().getName()) .setPrimaryAction(primarySliceAction)); return listBuilder.build(); } @@ -146,63 +128,10 @@ public class MediaOutputIndicatorSlice implements CustomSliceable { // To decide Slice's visibility. // Return true if // 1. AudioMode is not in on-going call - // 2. Bluetooth device is connected - return (!CollectionUtils.isEmpty(getConnectedA2dpDevices()) - || !CollectionUtils.isEmpty(getConnectedHearingAidDevices())) - && !com.android.settingslib.Utils.isAudioModeOngoingCall(mContext); - } - - private List getConnectedA2dpDevices() { - // Get A2dp devices on states - // (STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING) - final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); - if (a2dpProfile == null) { - return new ArrayList<>(); - } - return a2dpProfile.getConnectedDevices(); - } - - private List getConnectedHearingAidDevices() { - // Get hearing aid profile devices on states - // (STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING) - final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile(); - if (hapProfile == null) { - return new ArrayList<>(); - } - - return hapProfile.getConnectedDevices(); - } - - private CharSequence findActiveDeviceName() { - // Return Hearing Aid device name if it is active - BluetoothDevice activeDevice = findActiveHearingAidDevice(); - if (activeDevice != null) { - return activeDevice.getAlias(); - } - // Return A2DP device name if it is active - final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); - if (a2dpProfile != null) { - activeDevice = a2dpProfile.getActiveDevice(); - if (activeDevice != null) { - return activeDevice.getAlias(); - } - } - // No active device, return default summary - return mContext.getText(R.string.media_output_default_summary); - } - - private BluetoothDevice findActiveHearingAidDevice() { - final HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile(); - if (hearingAidProfile == null) { - return null; - } - - final List activeDevices = hearingAidProfile.getActiveDevices(); - for (BluetoothDevice btDevice : activeDevices) { - if (btDevice != null) { - return btDevice; - } - } - return null; + // 2. worker is not null + // 3. Available devices are more than 1 + return getWorker() != null + && !com.android.settingslib.Utils.isAudioModeOngoingCall(mContext) + && getWorker().getMediaDevices().size() > 1; } } diff --git a/src/com/android/settings/media/MediaOutputIndicatorWorker.java b/src/com/android/settings/media/MediaOutputIndicatorWorker.java index 4ceeade986f..6daa745d5f0 100644 --- a/src/com/android/settings/media/MediaOutputIndicatorWorker.java +++ b/src/com/android/settings/media/MediaOutputIndicatorWorker.java @@ -18,7 +18,6 @@ package com.android.settings.media; import static android.media.AudioManager.STREAM_DEVICES_CHANGED_ACTION; -import android.bluetooth.BluetoothProfile; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -36,21 +35,33 @@ import androidx.annotation.Nullable; import com.android.settings.bluetooth.Utils; import com.android.settings.slices.SliceBackgroundWorker; import com.android.settingslib.bluetooth.BluetoothCallback; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.media.LocalMediaManager; +import com.android.settingslib.media.MediaDevice; + +import com.google.common.annotations.VisibleForTesting; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * Listener for background change from {@code BluetoothCallback} to update media output indicator. */ -public class MediaOutputIndicatorWorker extends SliceBackgroundWorker implements BluetoothCallback { +public class MediaOutputIndicatorWorker extends SliceBackgroundWorker implements BluetoothCallback, + LocalMediaManager.DeviceCallback { - private static final String TAG = "MediaOutputIndicatorWorker"; + private static final String TAG = "MediaOutputIndWorker"; private final DevicesChangedBroadcastReceiver mReceiver; private final Context mContext; + private final Collection mMediaDevices = new CopyOnWriteArrayList<>(); private LocalBluetoothManager mLocalBluetoothManager; + @VisibleForTesting + LocalMediaManager mLocalMediaManager; + public MediaOutputIndicatorWorker(Context context, Uri uri) { super(context, uri); mReceiver = new DevicesChangedBroadcastReceiver(); @@ -59,6 +70,7 @@ public class MediaOutputIndicatorWorker extends SliceBackgroundWorker implements @Override protected void onSlicePinned() { + mMediaDevices.clear(); mLocalBluetoothManager = Utils.getLocalBtManager(getContext()); if (mLocalBluetoothManager == null) { Log.e(TAG, "Bluetooth is not supported on this device"); @@ -67,10 +79,25 @@ public class MediaOutputIndicatorWorker extends SliceBackgroundWorker implements final IntentFilter intentFilter = new IntentFilter(STREAM_DEVICES_CHANGED_ACTION); mContext.registerReceiver(mReceiver, intentFilter); mLocalBluetoothManager.getEventManager().registerCallback(this); + + if (mLocalMediaManager == null) { + final MediaController controller = getActiveLocalMediaController(); + String packageName = null; + if (controller != null) { + packageName = controller.getPackageName(); + } + mLocalMediaManager = new LocalMediaManager(mContext, packageName, null); + } + + mLocalMediaManager.registerCallback(this); + mLocalMediaManager.startScan(); } @Override protected void onSliceUnpinned() { + mLocalMediaManager.unregisterCallback(this); + mLocalMediaManager.stopScan(); + if (mLocalBluetoothManager == null) { Log.e(TAG, "Bluetooth is not supported on this device"); return; @@ -82,20 +109,7 @@ public class MediaOutputIndicatorWorker extends SliceBackgroundWorker implements @Override public void close() { mLocalBluetoothManager = null; - } - - @Override - public void onBluetoothStateChanged(int bluetoothState) { - // To handle the case that Bluetooth on and no connected devices - notifySliceChange(); - } - - @Override - public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) { - if (bluetoothProfile == BluetoothProfile.A2DP || - bluetoothProfile == BluetoothProfile.HEARING_AID) { - notifySliceChange(); - } + mLocalMediaManager = null; } @Override @@ -124,6 +138,36 @@ public class MediaOutputIndicatorWorker extends SliceBackgroundWorker implements } return null; } + + @Override + public void onDeviceListUpdate(List devices) { + buildMediaDevices(devices); + notifySliceChange(); + } + + private void buildMediaDevices(List devices) { + mMediaDevices.clear(); + mMediaDevices.addAll(devices); + } + + @Override + public void onSelectedDeviceStateChanged(MediaDevice device, int state) { + notifySliceChange(); + } + + @Override + public void onDeviceAttributesChanged() { + notifySliceChange(); + } + + Collection getMediaDevices() { + return mMediaDevices; + } + + MediaDevice getCurrentConnectedMediaDevice() { + return mLocalMediaManager.getCurrentConnectedDevice(); + } + private class DevicesChangedBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java index 92fa843a8c7..eff838decc2 100644 --- a/src/com/android/settings/media/MediaOutputSlice.java +++ b/src/com/android/settings/media/MediaOutputSlice.java @@ -22,7 +22,6 @@ import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE; import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_SLICE_URI; import android.app.PendingIntent; -import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.content.Intent; import android.graphics.Color; @@ -246,11 +245,10 @@ public class MediaOutputSlice implements CustomSliceable { // Return true if // 1. AudioMode is not in on-going call // 2. worker is not null - // 3. Bluetooth is enabled - final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - - return adapter.isEnabled() + // 3. Available devices are more than 1 + return getWorker() != null && !com.android.settingslib.Utils.isAudioModeOngoingCall(mContext) - && getWorker() != null; + && getWorker().getMediaDevices().size() > 1; + } } diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorSliceTest.java index 70978894cf0..cc4a870fb4e 100644 --- a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorSliceTest.java +++ b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorSliceTest.java @@ -26,11 +26,9 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothManager; import android.content.Context; import android.content.Intent; +import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.media.session.MediaController; import android.media.session.MediaSession; @@ -46,14 +44,12 @@ import androidx.slice.widget.SliceLiveData; import com.android.settings.R; import com.android.settings.slices.SliceBackgroundWorker; import com.android.settings.testutils.shadow.ShadowBluetoothUtils; -import com.android.settingslib.bluetooth.A2dpProfile; -import com.android.settingslib.bluetooth.HearingAidProfile; import com.android.settingslib.bluetooth.LocalBluetoothManager; -import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; +import com.android.settingslib.media.LocalMediaManager; +import com.android.settingslib.media.MediaDevice; import com.android.settingslib.media.MediaOutputSliceConstants; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -73,31 +69,28 @@ import java.util.List; MediaOutputIndicatorSliceTest.ShadowSliceBackgroundWorker.class}) public class MediaOutputIndicatorSliceTest { - private static final String TEST_A2DP_DEVICE_NAME = "Test_A2DP_BT_Device_NAME"; - private static final String TEST_HAP_DEVICE_NAME = "Test_HAP_BT_Device_NAME"; - private static final String TEST_A2DP_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1"; - private static final String TEST_HAP_DEVICE_ADDRESS = "00:B2:B2:B2:B2:B2"; + private static final String TEST_DEVICE_1_NAME = "test_device_1_name"; + private static final String TEST_DEVICE_2_NAME = "test_device_2_name"; private static final String TEST_PACKAGE_NAME = "com.test"; private static MediaOutputIndicatorWorker sMediaOutputIndicatorWorker; - @Mock - private A2dpProfile mA2dpProfile; - @Mock - private HearingAidProfile mHearingAidProfile; + private final List mDevices = new ArrayList<>(); + @Mock private LocalBluetoothManager mLocalBluetoothManager; @Mock - private LocalBluetoothProfileManager mLocalBluetoothProfileManager; - @Mock private MediaController mMediaController; + @Mock + private LocalMediaManager mLocalMediaManager; + @Mock + private MediaDevice mDevice1; + @Mock + private MediaDevice mDevice2; + @Mock + private Drawable mTestDrawable; - private BluetoothAdapter mBluetoothAdapter; - private BluetoothDevice mA2dpDevice; - private BluetoothDevice mHapDevice; - private BluetoothManager mBluetoothManager; private Context mContext; - private List mDevicesList; private MediaOutputIndicatorSlice mMediaOutputIndicatorSlice; private AudioManager mAudioManager; private MediaSession.Token mToken; @@ -107,7 +100,6 @@ public class MediaOutputIndicatorSliceTest { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - mAudioManager.setMode(AudioManager.MODE_NORMAL); sMediaOutputIndicatorWorker = spy(new MediaOutputIndicatorWorker(mContext, MEDIA_OUTPUT_INDICATOR_SLICE_URI)); mToken = new MediaSession.Token(Process.myUid(), null); @@ -115,109 +107,86 @@ public class MediaOutputIndicatorSliceTest { SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); // Setup Bluetooth environment ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager; - mBluetoothManager = new BluetoothManager(mContext); - mBluetoothAdapter = mBluetoothManager.getAdapter(); - when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); - when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile); - when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); - - // Setup A2dp device - mA2dpDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_A2DP_DEVICE_ADDRESS)); - when(mA2dpDevice.getName()).thenReturn(TEST_A2DP_DEVICE_NAME); - when(mA2dpDevice.isConnected()).thenReturn(true); - // Setup HearingAid device - mHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_HAP_DEVICE_ADDRESS)); - when(mHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME); - when(mHapDevice.isConnected()).thenReturn(true); + // Setup mock devices + when(mDevice1.getName()).thenReturn(TEST_DEVICE_1_NAME); + when(mDevice1.getIcon()).thenReturn(mTestDrawable); + when(mDevice1.getMaxVolume()).thenReturn(100); + when(mDevice1.isConnected()).thenReturn(true); + when(mDevice2.getName()).thenReturn(TEST_DEVICE_2_NAME); + when(mDevice2.getIcon()).thenReturn(mTestDrawable); + when(mDevice2.getMaxVolume()).thenReturn(100); + when(mDevice2.isConnected()).thenReturn(false); mMediaOutputIndicatorSlice = new MediaOutputIndicatorSlice(mContext); - mDevicesList = new ArrayList<>(); + } + + @Test + public void getSlice_withConnectedDevice_verifyMetadata() { + mDevices.add(mDevice1); + mDevices.add(mDevice2); + when(sMediaOutputIndicatorWorker.getMediaDevices()).thenReturn(mDevices); + doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice(); + mAudioManager.setMode(AudioManager.MODE_NORMAL); + + final Slice mediaSlice = mMediaOutputIndicatorSlice.getSlice(); + final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice); + + assertThat(metadata.getTitle()).isEqualTo(mContext.getText(R.string.media_output_title)); + assertThat(metadata.getSubtitle()).isEqualTo(TEST_DEVICE_1_NAME); + assertThat(metadata.isErrorSlice()).isFalse(); } @Test public void getSlice_noConnectedDevice_returnErrorSlice() { - mDevicesList.clear(); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mDevicesList); + mDevices.clear(); + when(sMediaOutputIndicatorWorker.getMediaDevices()).thenReturn(mDevices); + mAudioManager.setMode(AudioManager.MODE_NORMAL); final Slice mediaSlice = mMediaOutputIndicatorSlice.getSlice(); final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice); + assertThat(metadata.isErrorSlice()).isTrue(); } - @Test - public void getSlice_noActiveDevice_verifyDefaultName() { - mDevicesList.add(mA2dpDevice); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mDevicesList); - when(mA2dpProfile.getActiveDevice()).thenReturn(null); - - // Verify slice title and subtitle - final Slice mediaSlice = mMediaOutputIndicatorSlice.getSlice(); - final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice); - assertThat(metadata.getTitle()).isEqualTo(mContext.getText(R.string.media_output_title)); - assertThat(metadata.getSubtitle()).isEqualTo(mContext.getText( - R.string.media_output_default_summary)); - assertThat(metadata.isErrorSlice()).isFalse(); - } - - @Test - @Ignore - public void getSlice_A2dpDeviceActive_verifyName() { - mDevicesList.add(mA2dpDevice); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mDevicesList); - when(mA2dpProfile.getActiveDevice()).thenReturn(mA2dpDevice); - - final Slice mediaSlice = mMediaOutputIndicatorSlice.getSlice(); - final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice); - assertThat(metadata.getTitle()).isEqualTo(mContext.getText(R.string.media_output_title)); - assertThat(metadata.getSubtitle()).isEqualTo(TEST_A2DP_DEVICE_NAME); - assertThat(metadata.isErrorSlice()).isFalse(); - } - - @Test - @Ignore - public void getSlice_HADeviceActive_verifyName() { - mDevicesList.add(mHapDevice); - when(mHearingAidProfile.getConnectedDevices()).thenReturn(mDevicesList); - when(mHearingAidProfile.getActiveDevices()).thenReturn(mDevicesList); - - // Verify slice title and subtitle - final Slice mediaSlice = mMediaOutputIndicatorSlice.getSlice(); - final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice); - assertThat(metadata.getTitle()).isEqualTo(mContext.getText(R.string.media_output_title)); - assertThat(metadata.getSubtitle()).isEqualTo(TEST_HAP_DEVICE_NAME); - assertThat(metadata.isErrorSlice()).isFalse(); - } - @Test public void getSlice_audioModeIsInCommunication_returnErrorSlice() { - mDevicesList.add(mA2dpDevice); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mDevicesList); + mDevices.add(mDevice1); + mDevices.add(mDevice2); + when(sMediaOutputIndicatorWorker.getMediaDevices()).thenReturn(mDevices); + doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice(); mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); final Slice mediaSlice = mMediaOutputIndicatorSlice.getSlice(); final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice); + assertThat(metadata.isErrorSlice()).isTrue(); } @Test public void getSlice_audioModeIsRingtone_returnErrorSlice() { - mDevicesList.add(mA2dpDevice); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mDevicesList); + mDevices.add(mDevice1); + mDevices.add(mDevice2); + when(sMediaOutputIndicatorWorker.getMediaDevices()).thenReturn(mDevices); + doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice(); mAudioManager.setMode(AudioManager.MODE_RINGTONE); final Slice mediaSlice = mMediaOutputIndicatorSlice.getSlice(); final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice); + assertThat(metadata.isErrorSlice()).isTrue(); } @Test public void getSlice_audioModeIsInCall_returnErrorSlice() { - mDevicesList.add(mA2dpDevice); - when(mA2dpProfile.getConnectedDevices()).thenReturn(mDevicesList); + mDevices.add(mDevice1); + mDevices.add(mDevice2); + when(sMediaOutputIndicatorWorker.getMediaDevices()).thenReturn(mDevices); + doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice(); mAudioManager.setMode(AudioManager.MODE_IN_CALL); final Slice mediaSlice = mMediaOutputIndicatorSlice.getSlice(); final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice); + assertThat(metadata.isErrorSlice()).isTrue(); } diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java index b6231a3c247..d96541d43b6 100644 --- a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java +++ b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java @@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -38,9 +39,11 @@ import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.net.Uri; +import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; import com.android.settings.testutils.shadow.ShadowBluetoothUtils; import com.android.settingslib.bluetooth.BluetoothEventManager; import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.settingslib.media.LocalMediaManager; import org.junit.Before; import org.junit.Test; @@ -56,7 +59,7 @@ import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) -@Config(shadows = {ShadowBluetoothUtils.class}) +@Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class}) public class MediaOutputIndicatorWorkerTest { private static final Uri URI = Uri.parse("content://com.android.settings.slices/test"); @@ -68,6 +71,8 @@ public class MediaOutputIndicatorWorkerTest { private MediaSessionManager mMediaSessionManager; @Mock private MediaController mMediaController; + @Mock + private LocalMediaManager mLocalMediaManager; private Context mContext; private MediaOutputIndicatorWorker mMediaOutputIndicatorWorker; @@ -95,29 +100,40 @@ public class MediaOutputIndicatorWorkerTest { @Test public void onSlicePinned_registerCallback() { + mMediaOutputIndicatorWorker.mLocalMediaManager = mLocalMediaManager; mMediaOutputIndicatorWorker.onSlicePinned(); + verify(mBluetoothEventManager).registerCallback(mMediaOutputIndicatorWorker); verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class)); + verify(mLocalMediaManager).registerCallback(mMediaOutputIndicatorWorker); + verify(mLocalMediaManager).startScan(); } @Test public void onSliceUnpinned_unRegisterCallback() { + mMediaOutputIndicatorWorker.mLocalMediaManager = mLocalMediaManager; mMediaOutputIndicatorWorker.onSlicePinned(); mMediaOutputIndicatorWorker.onSliceUnpinned(); + verify(mBluetoothEventManager).unregisterCallback(mMediaOutputIndicatorWorker); verify(mContext).unregisterReceiver(any(BroadcastReceiver.class)); + verify(mLocalMediaManager).unregisterCallback(mMediaOutputIndicatorWorker); + verify(mLocalMediaManager).stopScan(); } @Test public void onReceive_shouldNotifyChange() { mMediaOutputIndicatorWorker.onSlicePinned(); + // onSlicePinned will registerCallback() and get first callback. Callback triggers this at + // the first time. + verify(mResolver, times(1)).notifyChange(URI, null); final Intent intent = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION); for (BroadcastReceiver receiver : mShadowApplication.getReceiversForIntent(intent)) { receiver.onReceive(mContext, intent); } - - verify(mResolver).notifyChange(URI, null); + // Intent receiver triggers notifyChange() again + verify(mResolver, times(2)).notifyChange(URI, null /* observer */); } @Test