diff options
| author | 2024-05-29 21:37:45 +0000 | |
|---|---|---|
| committer | 2024-05-29 21:37:45 +0000 | |
| commit | e7cf4e23d6de3f029e34c662328d5761ecda4a00 (patch) | |
| tree | 8c923bbe4f9a121d2027a89d18aaf4e1c17e0fb8 | |
| parent | 48952cc73e864c11e3a512a8cb288e8fd5d27a4b (diff) | |
| parent | e324748656fd80168c79757285e6397be33a0b46 (diff) | |
Merge "Send media controller code to background thread." into main
4 files changed, 108 insertions, 10 deletions
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 1df9c88e48ac..7ce8f98a4cbb 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -1026,3 +1026,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "notification_media_manager_background_execution" + namespace: "systemui" + description: "Decide whether to execute binder calls in background thread" + bug: "336612071" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationMediaManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationMediaManagerTest.kt index a67a8ab643fb..fed613153a4e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationMediaManagerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationMediaManagerTest.kt @@ -16,6 +16,10 @@ package com.android.systemui.statusbar +import android.media.MediaMetadata +import android.media.session.MediaController +import android.media.session.MediaSession +import android.os.fakeExecutorHandler import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.service.notification.NotificationListenerService @@ -54,6 +58,7 @@ class NotificationMediaManagerTest : SysuiTestCase() { private val notifPipeline = kosmos.notifPipeline private val notifCollection = kosmos.mockNotifCollection private val dumpManager = kosmos.dumpManager + private val handler = kosmos.fakeExecutorHandler private val mediaDataManager = mock<MediaDataManager>() private val backgroundExecutor = FakeExecutor(FakeSystemClock()) @@ -72,7 +77,11 @@ class NotificationMediaManagerTest : SysuiTestCase() { mediaDataManager, dumpManager, backgroundExecutor, + handler, ) + val mediaSession = MediaSession(context, "TEST") + notificationMediaManager.mMediaController = + MediaController(context, mediaSession.sessionToken) verify(mediaDataManager).addListener(listenerCaptor.capture()) } @@ -114,4 +123,32 @@ class NotificationMediaManagerTest : SysuiTestCase() { verify(notifCollection).dismissNotification(notifEntryCaptor.capture(), any()) assertThat(notifEntryCaptor.lastValue.key).isEqualTo(KEY) } + + @Test + @EnableFlags(Flags.FLAG_NOTIFICATION_MEDIA_MANAGER_BACKGROUND_EXECUTION) + fun clearMediaNotification_flagOn_resetMediaMetadata() { + // set up media metadata. + notificationMediaManager.mMediaListener.onMetadataChanged(MediaMetadata.Builder().build()) + backgroundExecutor.runAllReady() + + // clear media notification. + notificationMediaManager.clearCurrentMediaNotification() + backgroundExecutor.runAllReady() + + assertThat(notificationMediaManager.mediaMetadata).isNull() + assertThat(notificationMediaManager.mMediaController).isNull() + } + + @Test + @DisableFlags(Flags.FLAG_NOTIFICATION_MEDIA_MANAGER_BACKGROUND_EXECUTION) + fun clearMediaNotification_flagOff_resetMediaMetadata() { + // set up media metadata. + notificationMediaManager.mMediaListener.onMetadataChanged(MediaMetadata.Builder().build()) + + // clear media notification. + notificationMediaManager.clearCurrentMediaNotification() + + assertThat(notificationMediaManager.mediaMetadata).isNull() + assertThat(notificationMediaManager.mMediaController).isNull() + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index 03c667034609..6d34a0fa9c24 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar; import static com.android.systemui.Flags.mediaControlsUserInitiatedDeleteintent; +import static com.android.systemui.Flags.notificationMediaManagerBackgroundExecution; import android.annotation.NonNull; import android.annotation.Nullable; @@ -26,12 +27,16 @@ import android.media.MediaMetadata; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.PlaybackState; +import android.os.Handler; import android.service.notification.NotificationStats; import android.service.notification.StatusBarNotification; import android.util.Log; +import androidx.annotation.VisibleForTesting; + import com.android.systemui.Dumpable; import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.media.controls.domain.pipeline.MediaDataManager; import com.android.systemui.media.controls.shared.model.MediaData; @@ -48,6 +53,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.concurrent.Executor; @@ -80,13 +86,16 @@ public class NotificationMediaManager implements Dumpable { private final ArrayList<MediaListener> mMediaListeners; private final Executor mBackgroundExecutor; + private final Handler mHandler; protected NotificationPresenter mPresenter; - private MediaController mMediaController; + @VisibleForTesting + MediaController mMediaController; private String mMediaNotificationKey; private MediaMetadata mMediaMetadata; - private final MediaController.Callback mMediaListener = new MediaController.Callback() { + @VisibleForTesting + final MediaController.Callback mMediaListener = new MediaController.Callback() { @Override public void onPlaybackStateChanged(PlaybackState state) { super.onPlaybackStateChanged(state); @@ -107,11 +116,20 @@ public class NotificationMediaManager implements Dumpable { if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: onMetadataChanged: " + metadata); } - mMediaMetadata = metadata; + if (notificationMediaManagerBackgroundExecution()) { + mBackgroundExecutor.execute(() -> setMediaMetadata(metadata)); + } else { + setMediaMetadata(metadata); + } + dispatchUpdateMediaMetaData(); } }; + private void setMediaMetadata(MediaMetadata metadata) { + mMediaMetadata = metadata; + } + /** * Injected constructor. See {@link CentralSurfacesModule}. */ @@ -122,7 +140,9 @@ public class NotificationMediaManager implements Dumpable { NotifCollection notifCollection, MediaDataManager mediaDataManager, DumpManager dumpManager, - @Background Executor backgroundExecutor) { + @Background Executor backgroundExecutor, + @Main Handler handler + ) { mContext = context; mMediaListeners = new ArrayList<>(); mVisibilityProvider = visibilityProvider; @@ -130,6 +150,7 @@ public class NotificationMediaManager implements Dumpable { mNotifPipeline = notifPipeline; mNotifCollection = notifCollection; mBackgroundExecutor = backgroundExecutor; + mHandler = handler; setupNotifPipeline(); @@ -262,6 +283,14 @@ public class NotificationMediaManager implements Dumpable { public void addCallback(MediaListener callback) { mMediaListeners.add(callback); + if (notificationMediaManagerBackgroundExecution()) { + mBackgroundExecutor.execute(() -> updateMediaMetaData(callback)); + } else { + updateMediaMetaData(callback); + } + } + + private void updateMediaMetaData(MediaListener callback) { callback.onPrimaryMetadataOrStateChanged(mMediaMetadata, getMediaControllerPlaybackState(mMediaController)); } @@ -273,7 +302,11 @@ public class NotificationMediaManager implements Dumpable { public void findAndUpdateMediaNotifications() { // TODO(b/169655907): get the semi-filtered notifications for current user Collection<NotificationEntry> allNotifications = mNotifPipeline.getAllNotifs(); - findPlayingMediaNotification(allNotifications); + if (notificationMediaManagerBackgroundExecution()) { + mBackgroundExecutor.execute(() -> findPlayingMediaNotification(allNotifications)); + } else { + findPlayingMediaNotification(allNotifications); + } dispatchUpdateMediaMetaData(); } @@ -312,7 +345,7 @@ public class NotificationMediaManager implements Dumpable { // We have a new media session clearCurrentMediaNotificationSession(); mMediaController = controller; - mMediaController.registerCallback(mMediaListener); + mMediaController.registerCallback(mMediaListener, mHandler); mMediaMetadata = mMediaController.getMetadata(); if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: insert listener, found new controller: " @@ -331,13 +364,29 @@ public class NotificationMediaManager implements Dumpable { } public void clearCurrentMediaNotification() { + if (notificationMediaManagerBackgroundExecution()) { + mBackgroundExecutor.execute(this::clearMediaNotification); + } else { + clearMediaNotification(); + } + } + + private void clearMediaNotification() { mMediaNotificationKey = null; clearCurrentMediaNotificationSession(); } private void dispatchUpdateMediaMetaData() { - @PlaybackState.State int state = getMediaControllerPlaybackState(mMediaController); ArrayList<MediaListener> callbacks = new ArrayList<>(mMediaListeners); + if (notificationMediaManagerBackgroundExecution()) { + mBackgroundExecutor.execute(() -> updateMediaMetaData(callbacks)); + } else { + updateMediaMetaData(callbacks); + } + } + + private void updateMediaMetaData(List<MediaListener> callbacks) { + @PlaybackState.State int state = getMediaControllerPlaybackState(mMediaController); for (int i = 0; i < callbacks.size(); i++) { callbacks.get(i).onPrimaryMetadataOrStateChanged(mMediaMetadata, state); } @@ -393,7 +442,6 @@ public class NotificationMediaManager implements Dumpable { Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: " + mMediaController.getPackageName()); } - // TODO(b/336612071): move to background thread mMediaController.unregisterCallback(mMediaListener); } mMediaController = null; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java index 05245898c161..7df7ef187e26 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.dagger; import static com.android.systemui.Flags.predictiveBackAnimateDialogs; import android.content.Context; +import android.os.Handler; import android.os.RemoteException; import android.service.dreams.IDreamManager; import android.util.Log; @@ -99,7 +100,8 @@ public interface CentralSurfacesDependenciesModule { NotifCollection notifCollection, MediaDataManager mediaDataManager, DumpManager dumpManager, - @Background Executor backgroundExecutor) { + @Background Executor backgroundExecutor, + @Main Handler handler) { return new NotificationMediaManager( context, visibilityProvider, @@ -107,7 +109,8 @@ public interface CentralSurfacesDependenciesModule { notifCollection, mediaDataManager, dumpManager, - backgroundExecutor); + backgroundExecutor, + handler); } /** */ |