diff --git a/src/com/android/settings/media/MediaDeviceUpdateWorker.java b/src/com/android/settings/media/MediaDeviceUpdateWorker.java index a9c9086d6fd..3b67886e31e 100644 --- a/src/com/android/settings/media/MediaDeviceUpdateWorker.java +++ b/src/com/android/settings/media/MediaDeviceUpdateWorker.java @@ -31,6 +31,7 @@ import android.text.TextUtils; import androidx.annotation.VisibleForTesting; import com.android.settings.slices.SliceBackgroundWorker; +import com.android.settingslib.Utils; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.settingslib.utils.ThreadUtils; @@ -49,6 +50,9 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker private final DevicesChangedBroadcastReceiver mReceiver; private final String mPackageName; + private boolean mIsTouched; + private MediaDevice mTopDevice; + @VisibleForTesting LocalMediaManager mLocalMediaManager; @@ -62,6 +66,7 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker @Override protected void onSlicePinned() { mMediaDevices.clear(); + mIsTouched = false; if (mLocalMediaManager == null) { mLocalMediaManager = new LocalMediaManager(mContext, mPackageName, null); } @@ -100,6 +105,11 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker notifySliceChange(); } + @Override + public void onDeviceAttributesChanged() { + notifySliceChange(); + } + public List getMediaDevices() { return new ArrayList<>(mMediaDevices); } @@ -118,11 +128,28 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker return mLocalMediaManager.getCurrentConnectedDevice(); } + void setIsTouched(boolean isTouched) { + mIsTouched = isTouched; + } + + boolean getIsTouched() { + return mIsTouched; + } + + void setTopDevice(MediaDevice device) { + mTopDevice = device; + } + + MediaDevice getTopDevice() { + return mTopDevice; + } + private class DevicesChangedBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); - if (TextUtils.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION, action)) { + if (TextUtils.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION, action) + && Utils.isAudioModeOngoingCall(mContext)) { notifySliceChange(); } } diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java index fbdf01c48d2..3bb9ec85a03 100644 --- a/src/com/android/settings/media/MediaOutputSlice.java +++ b/src/com/android/settings/media/MediaOutputSlice.java @@ -61,7 +61,7 @@ public class MediaOutputSlice implements CustomSliceable { } @VisibleForTesting - void init(String packageName, MediaDeviceUpdateWorker worker) { + void init(MediaDeviceUpdateWorker worker) { mWorker = worker; } @@ -79,15 +79,20 @@ public class MediaOutputSlice implements CustomSliceable { } final List devices = getMediaDevices(); + final MediaDeviceUpdateWorker worker = getWorker(); + final MediaDevice connectedDevice = worker.getCurrentConnectedMediaDevice(); + final boolean isTouched = worker.getIsTouched(); + // Fix the last top device when user press device to transfer. + final MediaDevice topDevice = isTouched ? worker.getTopDevice() : connectedDevice; - final MediaDevice connectedDevice = getWorker().getCurrentConnectedMediaDevice(); - if (connectedDevice != null) { - listBuilder.addRow(getActiveDeviceHeaderRow(connectedDevice)); + if (topDevice != null) { + listBuilder.addRow(getActiveDeviceHeaderRow(topDevice)); + worker.setTopDevice(topDevice); } for (MediaDevice device : devices) { - if (connectedDevice == null - || !TextUtils.equals(connectedDevice.getId(), device.getId())) { + if (topDevice == null + || !TextUtils.equals(topDevice.getId(), device.getId())) { listBuilder.addRow(getMediaDeviceRow(device)); } } @@ -173,6 +178,7 @@ public class MediaOutputSlice implements CustomSliceable { final MediaDevice device = worker.getMediaDeviceById(id); if (device != null) { Log.d(TAG, "onNotifyChange() device name : " + device.getName()); + worker.setIsTouched(true); worker.connectDevice(device); } } diff --git a/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java b/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java index 2e9fa30498d..0b2850b94d0 100644 --- a/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java +++ b/tests/robotests/src/com/android/settings/media/MediaDeviceUpdateWorkerTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -31,6 +32,7 @@ import android.content.Intent; import android.media.AudioManager; import android.net.Uri; +import com.android.settings.testutils.shadow.ShadowAudioManager; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; @@ -40,12 +42,14 @@ import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowAudioManager.class) public class MediaDeviceUpdateWorkerTest { private static final Uri URI = Uri.parse("content://com.android.settings.slices/test"); @@ -61,6 +65,7 @@ public class MediaDeviceUpdateWorkerTest { private MediaDevice mMediaDevice1; private MediaDevice mMediaDevice2; private ShadowApplication mShadowApplication; + private AudioManager mAudioManager; @Before public void setUp() { @@ -69,6 +74,7 @@ public class MediaDeviceUpdateWorkerTest { mMediaDeviceUpdateWorker = new MediaDeviceUpdateWorker(mContext, URI); mResolver = mock(ContentResolver.class); mShadowApplication = ShadowApplication.getInstance(); + mAudioManager = mContext.getSystemService(AudioManager.class); mMediaDevice1 = mock(MediaDevice.class); when(mMediaDevice1.getId()).thenReturn(TEST_DEVICE_1_ID); @@ -94,6 +100,13 @@ public class MediaDeviceUpdateWorkerTest { verify(mResolver).notifyChange(URI, null); } + @Test + public void onDeviceAttributesChanged_shouldNotifyChange() { + mMediaDeviceUpdateWorker.onDeviceAttributesChanged(); + + verify(mResolver).notifyChange(URI, null); + } + @Test public void onDeviceListUpdate_sameDeviceList_shouldBeEqual() { mMediaDeviceUpdateWorker.onDeviceListUpdate(mMediaDevices); @@ -140,8 +153,9 @@ public class MediaDeviceUpdateWorkerTest { } @Test - public void onReceive_shouldNotifyChange() { + public void onReceive_inCallState_shouldNotifyChange() { mMediaDeviceUpdateWorker.mLocalMediaManager = mock(LocalMediaManager.class); + mAudioManager.setMode(AudioManager.MODE_IN_CALL); mMediaDeviceUpdateWorker.onSlicePinned(); final Intent intent = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION); @@ -151,4 +165,18 @@ public class MediaDeviceUpdateWorkerTest { verify(mResolver).notifyChange(URI, null); } + + @Test + public void onReceive_notInCallState_doNothing() { + mMediaDeviceUpdateWorker.mLocalMediaManager = mock(LocalMediaManager.class); + mAudioManager.setMode(AudioManager.MODE_NORMAL); + + mMediaDeviceUpdateWorker.onSlicePinned(); + final Intent intent = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION); + for (BroadcastReceiver receiver : mShadowApplication.getReceiversForIntent(intent)) { + receiver.onReceive(mContext, intent); + } + + verify(mResolver, never()).notifyChange(URI, null); + } } diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java index 288c8e869d0..c9b9ff940c5 100644 --- a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java +++ b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java @@ -64,7 +64,6 @@ import java.util.List; @Config(shadows = {ShadowBluetoothAdapter.class}) public class MediaOutputSliceTest { - private static final String TEST_PACKAGE_NAME = "com.fake.android.music"; private static final String TEST_DEVICE_1_ID = "test_device_1_id"; private static final String TEST_DEVICE_1_NAME = "test_device_1_name"; private static final int TEST_DEVICE_1_ICON = @@ -100,12 +99,12 @@ public class MediaOutputSliceTest { mMediaDeviceUpdateWorker = new MediaDeviceUpdateWorker(mContext, MEDIA_OUTPUT_SLICE_URI); mMediaDeviceUpdateWorker.onDeviceListUpdate(mDevices); mMediaDeviceUpdateWorker.mLocalMediaManager = mLocalMediaManager; - mMediaOutputSlice.init(TEST_PACKAGE_NAME, mMediaDeviceUpdateWorker); + mMediaOutputSlice.init(mMediaDeviceUpdateWorker); } @Test public void getSlice_workerIsNull_shouldReturnZeroRow() { - mMediaOutputSlice.init(TEST_PACKAGE_NAME, null); + mMediaOutputSlice.init(null); final Slice slice = mMediaOutputSlice.getSlice();