Loading packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -21,3 +21,13 @@ flag { description: "Enable Output Switcher when no media is playing." bug: "284227163" } flag { name: "remove_unnecessary_route_scanning" namespace: "media_solutions" description: "Avoid active scan requests on UI components that only display route status information." bug: "332515672" metadata { purpose: PURPOSE_BUGFIX } } packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java +26 −8 Original line number Diff line number Diff line Loading @@ -185,11 +185,7 @@ public abstract class InfoMediaManager { } public void startScan() { mMediaDevices.clear(); registerRouter(); startScanOnRouter(); updateRouteListingPreference(); refreshDevices(); } private void updateRouteListingPreference() { Loading @@ -203,7 +199,6 @@ public abstract class InfoMediaManager { public final void stopScan() { stopScanOnRouter(); unregisterRouter(); } protected abstract void stopScanOnRouter(); Loading Loading @@ -290,14 +285,37 @@ public abstract class InfoMediaManager { return null; } protected final void registerCallback(MediaDeviceCallback callback) { /** * Registers the specified {@code callback} to receive state updates about routing information. * * <p>As long as there is a registered {@link MediaDeviceCallback}, {@link InfoMediaManager} * will receive state updates from the platform. * * <p>Call {@link #unregisterCallback(MediaDeviceCallback)} once you no longer need platform * updates. */ public final void registerCallback(@NonNull MediaDeviceCallback callback) { boolean wasEmpty = mCallbacks.isEmpty(); if (!mCallbacks.contains(callback)) { mCallbacks.add(callback); if (wasEmpty) { mMediaDevices.clear(); registerRouter(); updateRouteListingPreference(); refreshDevices(); } } } protected final void unregisterCallback(MediaDeviceCallback callback) { mCallbacks.remove(callback); /** * Unregisters the specified {@code callback}. * * @see #registerCallback(MediaDeviceCallback) */ public final void unregisterCallback(@NonNull MediaDeviceCallback callback) { if (mCallbacks.remove(callback) && mCallbacks.isEmpty()) { unregisterRouter(); } } private void dispatchDeviceListAdded(@NonNull List<MediaDevice> devices) { Loading packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java +11 −8 Original line number Diff line number Diff line Loading @@ -106,14 +106,23 @@ public class LocalMediaManager implements BluetoothCallback { * Register to start receiving callbacks for MediaDevice events. */ public void registerCallback(DeviceCallback callback) { boolean wasEmpty = mCallbacks.isEmpty(); if (!mCallbacks.contains(callback)) { mCallbacks.add(callback); if (wasEmpty) { mInfoMediaManager.registerCallback(mMediaDeviceCallback); } } } /** * Unregister to stop receiving callbacks for MediaDevice events */ public void unregisterCallback(DeviceCallback callback) { mCallbacks.remove(callback); if (mCallbacks.remove(callback) && mCallbacks.isEmpty()) { mInfoMediaManager.unregisterCallback(mMediaDeviceCallback); unRegisterDeviceAttributeChangeCallback(); } } /** Loading Loading @@ -228,10 +237,6 @@ public class LocalMediaManager implements BluetoothCallback { * Start scan connected MediaDevice */ public void startScan() { synchronized (mMediaDevicesLock) { mMediaDevices.clear(); } mInfoMediaManager.registerCallback(mMediaDeviceCallback); mInfoMediaManager.startScan(); } Loading Loading @@ -281,9 +286,7 @@ public class LocalMediaManager implements BluetoothCallback { * Stop scan MediaDevice */ public void stopScan() { mInfoMediaManager.unregisterCallback(mMediaDeviceCallback); mInfoMediaManager.stopScan(); unRegisterDeviceAttributeChangeCallback(); } /** Loading packages/SettingsLib/src/com/android/settingslib/volume/data/repository/LocalMediaRepository.kt +7 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.settingslib.volume.data.repository import com.android.settingslib.media.LocalMediaManager import com.android.settingslib.media.MediaDevice import com.android.settingslib.media.flags.Flags import com.android.settingslib.volume.shared.AudioManagerEventsReceiver import com.android.settingslib.volume.shared.model.AudioManagerEvent import kotlinx.coroutines.CoroutineScope Loading Loading @@ -69,10 +70,14 @@ class LocalMediaRepositoryImpl( } } localMediaManager.registerCallback(callback) if (!Flags.removeUnnecessaryRouteScanning()) { localMediaManager.startScan() } awaitClose { if (!Flags.removeUnnecessaryRouteScanning()) { localMediaManager.stopScan() } localMediaManager.unregisterCallback(callback) } } Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java +20 −22 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ 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.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading Loading @@ -751,35 +752,31 @@ public class InfoMediaManagerTest { @Test public void onTransferred_getAvailableRoutes_shouldAddMediaDevice() { final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>(); final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class); routingSessionInfos.add(sessionInfo); final List<String> selectedRoutes = new ArrayList<>(); selectedRoutes.add(TEST_ID); when(sessionInfo.getSelectedRoutes()).thenReturn(selectedRoutes); mShadowRouter2Manager.setRoutingSessions(routingSessionInfos); mInfoMediaManager.mRouterManager = mRouterManager; // Since test is running in Robolectric, return a fake session to avoid NPE. when(mRouterManager.getRoutingSessions(anyString())) .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION)); when(mRouterManager.getSelectedRoutes(any())) .thenReturn(List.of(TEST_SELECTED_SYSTEM_ROUTE)); final MediaRoute2Info info = mock(MediaRoute2Info.class); mInfoMediaManager.registerCallback(mCallback); when(info.getDeduplicationIds()).thenReturn(Set.of()); when(info.getId()).thenReturn(TEST_ID); when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME); final List<MediaRoute2Info> routes = new ArrayList<>(); routes.add(info); mShadowRouter2Manager.setTransferableRoutes(routes); MediaDevice mediaDevice = mInfoMediaManager.getCurrentConnectedDevice(); assertThat(mediaDevice).isNotNull(); assertThat(mediaDevice.getId()).isEqualTo(TEST_SYSTEM_ROUTE_ID); final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID); assertThat(mediaDevice).isNull(); when(mRouterManager.getRoutingSessions(anyString())) .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION, TEST_REMOTE_ROUTING_SESSION)); when(mRouterManager.getSelectedRoutes(any())).thenReturn(List.of(TEST_REMOTE_ROUTE)); mInfoMediaManager.mMediaRouterCallback.onTransferred(sessionInfo, sessionInfo); mInfoMediaManager.mMediaRouterCallback.onTransferred( TEST_SYSTEM_ROUTING_SESSION, TEST_REMOTE_ROUTING_SESSION); final MediaDevice infoDevice = mInfoMediaManager.mMediaDevices.get(0); assertThat(infoDevice.getId()).isEqualTo(TEST_ID); assertThat(infoDevice).isNotNull(); assertThat(infoDevice.getId()).isEqualTo(TEST_REMOTE_ROUTE.getId()); assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice); assertThat(mInfoMediaManager.mMediaDevices).hasSize(routes.size()); verify(mCallback).onConnectedDeviceChanged(TEST_ID); verify(mCallback).onConnectedDeviceChanged(TEST_REMOTE_ROUTE.getId()); } @Test Loading @@ -795,7 +792,8 @@ public class InfoMediaManagerTest { mInfoMediaManager.mMediaRouterCallback.onSessionUpdated(TEST_SYSTEM_ROUTING_SESSION); verify(mCallback).onDeviceListAdded(any()); // Expecting 1st call after registerCallback() and 2nd call after onSessionUpdated(). verify(mCallback, times(2)).onDeviceListAdded(any()); } @Test Loading Loading
packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -21,3 +21,13 @@ flag { description: "Enable Output Switcher when no media is playing." bug: "284227163" } flag { name: "remove_unnecessary_route_scanning" namespace: "media_solutions" description: "Avoid active scan requests on UI components that only display route status information." bug: "332515672" metadata { purpose: PURPOSE_BUGFIX } }
packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java +26 −8 Original line number Diff line number Diff line Loading @@ -185,11 +185,7 @@ public abstract class InfoMediaManager { } public void startScan() { mMediaDevices.clear(); registerRouter(); startScanOnRouter(); updateRouteListingPreference(); refreshDevices(); } private void updateRouteListingPreference() { Loading @@ -203,7 +199,6 @@ public abstract class InfoMediaManager { public final void stopScan() { stopScanOnRouter(); unregisterRouter(); } protected abstract void stopScanOnRouter(); Loading Loading @@ -290,14 +285,37 @@ public abstract class InfoMediaManager { return null; } protected final void registerCallback(MediaDeviceCallback callback) { /** * Registers the specified {@code callback} to receive state updates about routing information. * * <p>As long as there is a registered {@link MediaDeviceCallback}, {@link InfoMediaManager} * will receive state updates from the platform. * * <p>Call {@link #unregisterCallback(MediaDeviceCallback)} once you no longer need platform * updates. */ public final void registerCallback(@NonNull MediaDeviceCallback callback) { boolean wasEmpty = mCallbacks.isEmpty(); if (!mCallbacks.contains(callback)) { mCallbacks.add(callback); if (wasEmpty) { mMediaDevices.clear(); registerRouter(); updateRouteListingPreference(); refreshDevices(); } } } protected final void unregisterCallback(MediaDeviceCallback callback) { mCallbacks.remove(callback); /** * Unregisters the specified {@code callback}. * * @see #registerCallback(MediaDeviceCallback) */ public final void unregisterCallback(@NonNull MediaDeviceCallback callback) { if (mCallbacks.remove(callback) && mCallbacks.isEmpty()) { unregisterRouter(); } } private void dispatchDeviceListAdded(@NonNull List<MediaDevice> devices) { Loading
packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java +11 −8 Original line number Diff line number Diff line Loading @@ -106,14 +106,23 @@ public class LocalMediaManager implements BluetoothCallback { * Register to start receiving callbacks for MediaDevice events. */ public void registerCallback(DeviceCallback callback) { boolean wasEmpty = mCallbacks.isEmpty(); if (!mCallbacks.contains(callback)) { mCallbacks.add(callback); if (wasEmpty) { mInfoMediaManager.registerCallback(mMediaDeviceCallback); } } } /** * Unregister to stop receiving callbacks for MediaDevice events */ public void unregisterCallback(DeviceCallback callback) { mCallbacks.remove(callback); if (mCallbacks.remove(callback) && mCallbacks.isEmpty()) { mInfoMediaManager.unregisterCallback(mMediaDeviceCallback); unRegisterDeviceAttributeChangeCallback(); } } /** Loading Loading @@ -228,10 +237,6 @@ public class LocalMediaManager implements BluetoothCallback { * Start scan connected MediaDevice */ public void startScan() { synchronized (mMediaDevicesLock) { mMediaDevices.clear(); } mInfoMediaManager.registerCallback(mMediaDeviceCallback); mInfoMediaManager.startScan(); } Loading Loading @@ -281,9 +286,7 @@ public class LocalMediaManager implements BluetoothCallback { * Stop scan MediaDevice */ public void stopScan() { mInfoMediaManager.unregisterCallback(mMediaDeviceCallback); mInfoMediaManager.stopScan(); unRegisterDeviceAttributeChangeCallback(); } /** Loading
packages/SettingsLib/src/com/android/settingslib/volume/data/repository/LocalMediaRepository.kt +7 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.settingslib.volume.data.repository import com.android.settingslib.media.LocalMediaManager import com.android.settingslib.media.MediaDevice import com.android.settingslib.media.flags.Flags import com.android.settingslib.volume.shared.AudioManagerEventsReceiver import com.android.settingslib.volume.shared.model.AudioManagerEvent import kotlinx.coroutines.CoroutineScope Loading Loading @@ -69,10 +70,14 @@ class LocalMediaRepositoryImpl( } } localMediaManager.registerCallback(callback) if (!Flags.removeUnnecessaryRouteScanning()) { localMediaManager.startScan() } awaitClose { if (!Flags.removeUnnecessaryRouteScanning()) { localMediaManager.stopScan() } localMediaManager.unregisterCallback(callback) } } Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java +20 −22 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ 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.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading Loading @@ -751,35 +752,31 @@ public class InfoMediaManagerTest { @Test public void onTransferred_getAvailableRoutes_shouldAddMediaDevice() { final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>(); final RoutingSessionInfo sessionInfo = mock(RoutingSessionInfo.class); routingSessionInfos.add(sessionInfo); final List<String> selectedRoutes = new ArrayList<>(); selectedRoutes.add(TEST_ID); when(sessionInfo.getSelectedRoutes()).thenReturn(selectedRoutes); mShadowRouter2Manager.setRoutingSessions(routingSessionInfos); mInfoMediaManager.mRouterManager = mRouterManager; // Since test is running in Robolectric, return a fake session to avoid NPE. when(mRouterManager.getRoutingSessions(anyString())) .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION)); when(mRouterManager.getSelectedRoutes(any())) .thenReturn(List.of(TEST_SELECTED_SYSTEM_ROUTE)); final MediaRoute2Info info = mock(MediaRoute2Info.class); mInfoMediaManager.registerCallback(mCallback); when(info.getDeduplicationIds()).thenReturn(Set.of()); when(info.getId()).thenReturn(TEST_ID); when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME); final List<MediaRoute2Info> routes = new ArrayList<>(); routes.add(info); mShadowRouter2Manager.setTransferableRoutes(routes); MediaDevice mediaDevice = mInfoMediaManager.getCurrentConnectedDevice(); assertThat(mediaDevice).isNotNull(); assertThat(mediaDevice.getId()).isEqualTo(TEST_SYSTEM_ROUTE_ID); final MediaDevice mediaDevice = mInfoMediaManager.findMediaDevice(TEST_ID); assertThat(mediaDevice).isNull(); when(mRouterManager.getRoutingSessions(anyString())) .thenReturn(List.of(TEST_SYSTEM_ROUTING_SESSION, TEST_REMOTE_ROUTING_SESSION)); when(mRouterManager.getSelectedRoutes(any())).thenReturn(List.of(TEST_REMOTE_ROUTE)); mInfoMediaManager.mMediaRouterCallback.onTransferred(sessionInfo, sessionInfo); mInfoMediaManager.mMediaRouterCallback.onTransferred( TEST_SYSTEM_ROUTING_SESSION, TEST_REMOTE_ROUTING_SESSION); final MediaDevice infoDevice = mInfoMediaManager.mMediaDevices.get(0); assertThat(infoDevice.getId()).isEqualTo(TEST_ID); assertThat(infoDevice).isNotNull(); assertThat(infoDevice.getId()).isEqualTo(TEST_REMOTE_ROUTE.getId()); assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice); assertThat(mInfoMediaManager.mMediaDevices).hasSize(routes.size()); verify(mCallback).onConnectedDeviceChanged(TEST_ID); verify(mCallback).onConnectedDeviceChanged(TEST_REMOTE_ROUTE.getId()); } @Test Loading @@ -795,7 +792,8 @@ public class InfoMediaManagerTest { mInfoMediaManager.mMediaRouterCallback.onSessionUpdated(TEST_SYSTEM_ROUTING_SESSION); verify(mCallback).onDeviceListAdded(any()); // Expecting 1st call after registerCallback() and 2nd call after onSessionUpdated(). verify(mCallback, times(2)).onDeviceListAdded(any()); } @Test Loading