Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7cf4e23 authored by Michael Mikhail's avatar Michael Mikhail Committed by Android (Google) Code Review
Browse files

Merge "Send media controller code to background thread." into main

parents 48952cc7 e3247486
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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
  }
}
+37 −0
Original line number Diff line number Diff line
@@ -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()
    }
}
+56 −8
Original line number Diff line number Diff line
@@ -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();
        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;
+5 −2
Original line number Diff line number Diff line
@@ -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);
    }

    /** */