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

Commit 9628692e authored by Beth Thibodeau's avatar Beth Thibodeau Committed by Android (Google) Code Review
Browse files

Merge "Add logging for media controls" into tm-dev

parents 58f33528 21169ec3
Loading
Loading
Loading
Loading
+20 −12
Original line number Original line Diff line number Diff line
@@ -12,6 +12,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.LinearLayout
import androidx.annotation.VisibleForTesting
import androidx.annotation.VisibleForTesting
import com.android.internal.logging.InstanceId
import com.android.systemui.Dumpable
import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.R
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollector
@@ -59,7 +60,7 @@ class MediaCarouselController @Inject constructor(
    falsingCollector: FalsingCollector,
    falsingCollector: FalsingCollector,
    falsingManager: FalsingManager,
    falsingManager: FalsingManager,
    dumpManager: DumpManager,
    dumpManager: DumpManager,
    private val mediaFlags: MediaFlags
    private val logger: MediaUiEventLogger
) : Dumpable {
) : Dumpable {
    /**
    /**
     * The current width of the carousel
     * The current width of the carousel
@@ -119,7 +120,9 @@ class MediaCarouselController @Inject constructor(
    private val mediaCarousel: MediaScrollView
    private val mediaCarousel: MediaScrollView
    val mediaCarouselScrollHandler: MediaCarouselScrollHandler
    val mediaCarouselScrollHandler: MediaCarouselScrollHandler
    val mediaFrame: ViewGroup
    val mediaFrame: ViewGroup
    private lateinit var settingsButton: View
    @VisibleForTesting
    lateinit var settingsButton: View
        private set
    private val mediaContent: ViewGroup
    private val mediaContent: ViewGroup
    private val pageIndicator: PageIndicator
    private val pageIndicator: PageIndicator
    private val visualStabilityCallback: OnReorderingAllowedListener
    private val visualStabilityCallback: OnReorderingAllowedListener
@@ -183,7 +186,8 @@ class MediaCarouselController @Inject constructor(
        pageIndicator = mediaFrame.requireViewById(R.id.media_page_indicator)
        pageIndicator = mediaFrame.requireViewById(R.id.media_page_indicator)
        mediaCarouselScrollHandler = MediaCarouselScrollHandler(mediaCarousel, pageIndicator,
        mediaCarouselScrollHandler = MediaCarouselScrollHandler(mediaCarousel, pageIndicator,
                executor, this::onSwipeToDismiss, this::updatePageIndicatorLocation,
                executor, this::onSwipeToDismiss, this::updatePageIndicatorLocation,
                this::closeGuts, falsingCollector, falsingManager, this::logSmartspaceImpression)
                this::closeGuts, falsingCollector, falsingManager, this::logSmartspaceImpression,
                logger)
        isRtl = context.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
        isRtl = context.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
        inflateSettingsButton()
        inflateSettingsButton()
        mediaContent = mediaCarousel.requireViewById(R.id.media_carousel)
        mediaContent = mediaCarousel.requireViewById(R.id.media_carousel)
@@ -220,7 +224,7 @@ class MediaCarouselController @Inject constructor(
                    MediaPlayerData.getMediaPlayer(key)?.let {
                    MediaPlayerData.getMediaPlayer(key)?.let {
                        /* ktlint-disable max-line-length */
                        /* ktlint-disable max-line-length */
                        logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                        logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                                it.mInstanceId,
                                it.mSmartspaceId,
                                it.mUid,
                                it.mUid,
                                /* isRecommendationCard */ false,
                                /* isRecommendationCard */ false,
                                intArrayOf(
                                intArrayOf(
@@ -239,12 +243,12 @@ class MediaCarouselController @Inject constructor(
                    // resume card is ranked first
                    // resume card is ranked first
                    MediaPlayerData.players().forEachIndexed { index, it ->
                    MediaPlayerData.players().forEachIndexed { index, it ->
                        if (it.recommendationViewHolder == null) {
                        if (it.recommendationViewHolder == null) {
                            it.mInstanceId = SmallHash.hash(it.mUid +
                            it.mSmartspaceId = SmallHash.hash(it.mUid +
                                    systemClock.currentTimeMillis().toInt())
                                    systemClock.currentTimeMillis().toInt())
                            it.mIsImpressed = false
                            it.mIsImpressed = false
                            /* ktlint-disable max-line-length */
                            /* ktlint-disable max-line-length */
                            logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                            logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                                    it.mInstanceId,
                                    it.mSmartspaceId,
                                    it.mUid,
                                    it.mUid,
                                    /* isRecommendationCard */ false,
                                    /* isRecommendationCard */ false,
                                    intArrayOf(
                                    intArrayOf(
@@ -291,12 +295,12 @@ class MediaCarouselController @Inject constructor(
                        // recommendation card is valid and ranked first
                        // recommendation card is valid and ranked first
                        MediaPlayerData.players().forEachIndexed { index, it ->
                        MediaPlayerData.players().forEachIndexed { index, it ->
                            if (it.recommendationViewHolder == null) {
                            if (it.recommendationViewHolder == null) {
                                it.mInstanceId = SmallHash.hash(it.mUid +
                                it.mSmartspaceId = SmallHash.hash(it.mUid +
                                        systemClock.currentTimeMillis().toInt())
                                        systemClock.currentTimeMillis().toInt())
                                it.mIsImpressed = false
                                it.mIsImpressed = false
                                /* ktlint-disable max-line-length */
                                /* ktlint-disable max-line-length */
                                logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                                logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                                        it.mInstanceId,
                                        it.mSmartspaceId,
                                        it.mUid,
                                        it.mUid,
                                        /* isRecommendationCard */ false,
                                        /* isRecommendationCard */ false,
                                        intArrayOf(
                                        intArrayOf(
@@ -312,7 +316,7 @@ class MediaCarouselController @Inject constructor(
                    MediaPlayerData.getMediaPlayer(key)?.let {
                    MediaPlayerData.getMediaPlayer(key)?.let {
                        /* ktlint-disable max-line-length */
                        /* ktlint-disable max-line-length */
                        logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                        logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                                it.mInstanceId,
                                it.mSmartspaceId,
                                it.mUid,
                                it.mUid,
                                /* isRecommendationCard */ true,
                                /* isRecommendationCard */ true,
                                intArrayOf(
                                intArrayOf(
@@ -369,6 +373,7 @@ class MediaCarouselController @Inject constructor(
        mediaFrame.addView(settingsButton)
        mediaFrame.addView(settingsButton)
        mediaCarouselScrollHandler.onSettingsButtonUpdated(settings)
        mediaCarouselScrollHandler.onSettingsButtonUpdated(settings)
        settingsButton.setOnClickListener {
        settingsButton.setOnClickListener {
            logger.logCarouselSettings()
            activityStarter.startActivity(settingsIntent, true /* dismissShade */)
            activityStarter.startActivity(settingsIntent, true /* dismissShade */)
        }
        }
    }
    }
@@ -752,7 +757,7 @@ class MediaCarouselController @Inject constructor(
                return
                return
            }
            }
            logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN
            logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN
                    mediaControlPanel.mInstanceId,
                    mediaControlPanel.mSmartspaceId,
                    mediaControlPanel.mUid,
                    mediaControlPanel.mUid,
                    isRecommendationCard,
                    isRecommendationCard,
                    intArrayOf(mediaControlPanel.surfaceForSmartspaceLogging))
                    intArrayOf(mediaControlPanel.surfaceForSmartspaceLogging))
@@ -836,7 +841,7 @@ class MediaCarouselController @Inject constructor(
            index, it ->
            index, it ->
            if (it.mIsImpressed) {
            if (it.mIsImpressed) {
                logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT,
                logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT,
                        it.mInstanceId,
                        it.mSmartspaceId,
                        it.mUid,
                        it.mUid,
                        it.recommendationViewHolder != null,
                        it.recommendationViewHolder != null,
                        intArrayOf(it.surfaceForSmartspaceLogging),
                        intArrayOf(it.surfaceForSmartspaceLogging),
@@ -846,6 +851,7 @@ class MediaCarouselController @Inject constructor(
                it.mIsImpressed = false
                it.mIsImpressed = false
            }
            }
        }
        }
        logger.logSwipeDismiss()
        mediaManager.onSwipeToDismiss()
        mediaManager.onSwipeToDismiss()
    }
    }


@@ -881,7 +887,9 @@ internal object MediaPlayerData {
            clickIntent = null,
            clickIntent = null,
            device = null,
            device = null,
            active = true,
            active = true,
            resumeAction = null)
            resumeAction = null,
            instanceId = InstanceId.fakeInstanceId(-1),
            appUid = -1)
    // Whether should prioritize Smartspace card.
    // Whether should prioritize Smartspace card.
    internal var shouldPrioritizeSs: Boolean = false
    internal var shouldPrioritizeSs: Boolean = false
        private set
        private set
+4 −2
Original line number Original line Diff line number Diff line
@@ -57,12 +57,13 @@ class MediaCarouselScrollHandler(
    private val scrollView: MediaScrollView,
    private val scrollView: MediaScrollView,
    private val pageIndicator: PageIndicator,
    private val pageIndicator: PageIndicator,
    private val mainExecutor: DelayableExecutor,
    private val mainExecutor: DelayableExecutor,
    private val dismissCallback: () -> Unit,
    val dismissCallback: () -> Unit,
    private var translationChangedListener: () -> Unit,
    private var translationChangedListener: () -> Unit,
    private val closeGuts: (immediate: Boolean) -> Unit,
    private val closeGuts: (immediate: Boolean) -> Unit,
    private val falsingCollector: FalsingCollector,
    private val falsingCollector: FalsingCollector,
    private val falsingManager: FalsingManager,
    private val falsingManager: FalsingManager,
    private val logSmartspaceImpression: (Boolean) -> Unit
    private val logSmartspaceImpression: (Boolean) -> Unit,
    private val logger: MediaUiEventLogger
) {
) {
    /**
    /**
     * Is the view in RTL
     * Is the view in RTL
@@ -476,6 +477,7 @@ class MediaCarouselScrollHandler(
            visibleMediaIndex = newIndex
            visibleMediaIndex = newIndex
            if (oldIndex != visibleMediaIndex && visibleToUser) {
            if (oldIndex != visibleMediaIndex && visibleToUser) {
                logSmartspaceImpression(qsExpanded)
                logSmartspaceImpression(qsExpanded)
                logger.logMediaCarouselPage(newIndex)
            }
            }
            closeGuts(false)
            closeGuts(false)
            updatePlayerVisibilities()
            updatePlayerVisibilities()
+25 −16
Original line number Original line Diff line number Diff line
@@ -53,6 +53,7 @@ import androidx.annotation.UiThread;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.constraintlayout.widget.ConstraintSet;


import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.InstanceId;
import com.android.settingslib.widget.AdaptiveIcon;
import com.android.settingslib.widget.AdaptiveIcon;
import com.android.systemui.R;
import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.ActivityLaunchAnimator;
@@ -131,8 +132,6 @@ public class MediaControlPanel {
    private MediaController mController;
    private MediaController mController;
    private Lazy<MediaDataManager> mMediaDataManagerLazy;
    private Lazy<MediaDataManager> mMediaDataManagerLazy;
    private int mBackgroundColor;
    private int mBackgroundColor;
    // Instance id for logging purpose.
    protected int mInstanceId = -1;
    // Uid for the media app.
    // Uid for the media app.
    protected int mUid = Process.INVALID_UID;
    protected int mUid = Process.INVALID_UID;
    private int mSmartspaceMediaItemsCount;
    private int mSmartspaceMediaItemsCount;
@@ -140,9 +139,13 @@ public class MediaControlPanel {
    private final MediaOutputDialogFactory mMediaOutputDialogFactory;
    private final MediaOutputDialogFactory mMediaOutputDialogFactory;
    private final FalsingManager mFalsingManager;
    private final FalsingManager mFalsingManager;


    // Used for swipe-to-dismiss logging.
    // Used for logging.
    protected boolean mIsImpressed = false;
    protected boolean mIsImpressed = false;
    private SystemClock mSystemClock;
    private SystemClock mSystemClock;
    private MediaUiEventLogger mLogger;
    private InstanceId mInstanceId;
    protected int mSmartspaceId = -1;
    private String mPackageName;


    /**
    /**
     * Initialize a new control panel
     * Initialize a new control panel
@@ -157,7 +160,7 @@ public class MediaControlPanel {
            Lazy<MediaDataManager> lazyMediaDataManager,
            Lazy<MediaDataManager> lazyMediaDataManager,
            MediaOutputDialogFactory mediaOutputDialogFactory,
            MediaOutputDialogFactory mediaOutputDialogFactory,
            MediaCarouselController mediaCarouselController,
            MediaCarouselController mediaCarouselController,
            FalsingManager falsingManager, SystemClock systemClock) {
            FalsingManager falsingManager, SystemClock systemClock, MediaUiEventLogger logger) {
        mContext = context;
        mContext = context;
        mBackgroundExecutor = backgroundExecutor;
        mBackgroundExecutor = backgroundExecutor;
        mActivityStarter = activityStarter;
        mActivityStarter = activityStarter;
@@ -169,8 +172,12 @@ public class MediaControlPanel {
        mMediaCarouselController = mediaCarouselController;
        mMediaCarouselController = mediaCarouselController;
        mFalsingManager = falsingManager;
        mFalsingManager = falsingManager;
        mSystemClock = systemClock;
        mSystemClock = systemClock;
        mLogger = logger;


        mSeekBarViewModel.setLogSmartspaceClick(() -> {
        mSeekBarViewModel.setLogSeek(() -> {
            if (mPackageName != null && mInstanceId != null) {
                mLogger.logSeek(mUid, mPackageName, mInstanceId);
            }
            logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT,
            logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT,
                    /* isRecommendationCard */ false);
                    /* isRecommendationCard */ false);
            return Unit.INSTANCE;
            return Unit.INSTANCE;
@@ -261,6 +268,7 @@ public class MediaControlPanel {
        });
        });
        vh.getSettings().setOnClickListener(v -> {
        vh.getSettings().setOnClickListener(v -> {
            if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
            if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
                mLogger.logLongPressSettings(mUid, mPackageName, mInstanceId);
                mActivityStarter.startActivity(SETTINGS_INTENT, true /* dismissShade */);
                mActivityStarter.startActivity(SETTINGS_INTENT, true /* dismissShade */);
            }
            }
        });
        });
@@ -301,16 +309,13 @@ public class MediaControlPanel {
        }
        }
        mKey = key;
        mKey = key;
        MediaSession.Token token = data.getToken();
        MediaSession.Token token = data.getToken();
        PackageManager packageManager = mContext.getPackageManager();
        mPackageName = data.getPackageName();
        try {
        mUid = data.getAppUid();
            mUid = packageManager.getApplicationInfo(data.getPackageName(), 0 /* flags */).uid;
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Unable to look up package name", e);
        }
        // Only assigns instance id if it's unassigned.
        // Only assigns instance id if it's unassigned.
        if (mInstanceId == -1) {
        if (mSmartspaceId == -1) {
            mInstanceId = SmallHash.hash(mUid + (int) mSystemClock.currentTimeMillis());
            mSmartspaceId = SmallHash.hash(mUid + (int) mSystemClock.currentTimeMillis());
        }
        }
        mInstanceId = data.getInstanceId();


        mBackgroundColor = data.getBackgroundColor();
        mBackgroundColor = data.getBackgroundColor();
        if (mToken == null || !mToken.equals(token)) {
        if (mToken == null || !mToken.equals(token)) {
@@ -401,6 +406,7 @@ public class MediaControlPanel {
                    if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
                    if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
                        return;
                        return;
                    }
                    }
                    mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId);
                    if (device.getIntent() != null) {
                    if (device.getIntent() != null) {
                        if (device.getIntent().isActivity()) {
                        if (device.getIntent().isActivity()) {
                            mActivityStarter.startActivity(
                            mActivityStarter.startActivity(
@@ -413,7 +419,7 @@ public class MediaControlPanel {
                            }
                            }
                        }
                        }
                    } else {
                    } else {
                        mMediaOutputDialogFactory.create(data.getPackageName(), true,
                        mMediaOutputDialogFactory.create(mPackageName, true,
                                mMediaViewHolder.getSeamlessButton());
                                mMediaViewHolder.getSeamlessButton());
                    }
                    }
                });
                });
@@ -437,6 +443,7 @@ public class MediaControlPanel {


            logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT,
            logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT,
                    /* isRecommendationCard */ false);
                    /* isRecommendationCard */ false);
            mLogger.logLongPressDismiss(mUid, mPackageName, mInstanceId);


            if (mKey != null) {
            if (mKey != null) {
                closeGuts();
                closeGuts();
@@ -675,6 +682,7 @@ public class MediaControlPanel {
                button.setEnabled(true);
                button.setEnabled(true);
                button.setOnClickListener(v -> {
                button.setOnClickListener(v -> {
                    if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
                    if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
                        mLogger.logTapAction(button.getId(), mUid, mPackageName, mInstanceId);
                        logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT,
                        logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT,
                                /* isRecommendationCard */ false);
                                /* isRecommendationCard */ false);
                        action.run();
                        action.run();
@@ -794,7 +802,7 @@ public class MediaControlPanel {
            return;
            return;
        }
        }


        mInstanceId = SmallHash.hash(data.getTargetId());
        mSmartspaceId = SmallHash.hash(data.getTargetId());
        mBackgroundColor = data.getBackgroundColor();
        mBackgroundColor = data.getBackgroundColor();
        TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations();
        TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations();
        recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor));
        recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor));
@@ -976,6 +984,7 @@ public class MediaControlPanel {
            mRecommendationViewHolder.marquee(true, mMediaViewController.GUTS_ANIMATION_DURATION);
            mRecommendationViewHolder.marquee(true, mMediaViewController.GUTS_ANIMATION_DURATION);
        }
        }
        mMediaViewController.openGuts();
        mMediaViewController.openGuts();
        mLogger.logLongPressOpen(mUid, mPackageName, mInstanceId);
    }
    }


    /**
    /**
@@ -1138,7 +1147,7 @@ public class MediaControlPanel {
    private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard,
    private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard,
            int interactedSubcardRank, int interactedSubcardCardinality) {
            int interactedSubcardRank, int interactedSubcardCardinality) {
        mMediaCarouselController.logSmartspaceCardReported(eventId,
        mMediaCarouselController.logSmartspaceCardReported(eventId,
                mInstanceId,
                mSmartspaceId,
                mUid,
                mUid,
                isRecommendationCard,
                isRecommendationCard,
                new int[]{getSurfaceForSmartspaceLogging()},
                new int[]{getSurfaceForSmartspaceLogging()},
+12 −1
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.app.PendingIntent
import android.graphics.drawable.Drawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon
import android.graphics.drawable.Icon
import android.media.session.MediaSession
import android.media.session.MediaSession
import com.android.internal.logging.InstanceId
import com.android.systemui.R
import com.android.systemui.R


/** State of a media view. */
/** State of a media view. */
@@ -115,7 +116,17 @@ data class MediaData(
    /**
    /**
     * Timestamp when this player was last active.
     * Timestamp when this player was last active.
     */
     */
    var lastActive: Long = 0L
    var lastActive: Long = 0L,

    /**
     * Instance ID for logging purposes
     */
    val instanceId: InstanceId,

    /**
     * The UID of the app, used for logging
     */
    val appUid: Int
) {
) {
    companion object {
    companion object {
        /** Media is playing on the local device */
        /** Media is playing on the local device */
+75 −15
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import android.content.ContentResolver
import android.content.Context
import android.content.Context
import android.content.Intent
import android.content.Intent
import android.content.IntentFilter
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Bitmap
import android.graphics.ImageDecoder
import android.graphics.ImageDecoder
import android.graphics.drawable.Icon
import android.graphics.drawable.Icon
@@ -37,6 +38,7 @@ import android.media.session.MediaSession
import android.media.session.PlaybackState
import android.media.session.PlaybackState
import android.net.Uri
import android.net.Uri
import android.os.Parcelable
import android.os.Parcelable
import android.os.Process
import android.os.UserHandle
import android.os.UserHandle
import android.provider.Settings
import android.provider.Settings
import android.service.notification.StatusBarNotification
import android.service.notification.StatusBarNotification
@@ -44,6 +46,7 @@ import android.text.TextUtils
import android.util.Log
import android.util.Log
import androidx.media.utils.MediaConstants
import androidx.media.utils.MediaConstants
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.logging.InstanceId
import com.android.systemui.Dumpable
import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.broadcast.BroadcastDispatcher
@@ -94,7 +97,9 @@ private val LOADING = MediaData(
        clickIntent = null,
        clickIntent = null,
        device = null,
        device = null,
        active = true,
        active = true,
        resumeAction = null)
        resumeAction = null,
        instanceId = InstanceId.fakeInstanceId(-1),
        appUid = Process.INVALID_UID)


@VisibleForTesting
@VisibleForTesting
internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false,
internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false,
@@ -138,7 +143,8 @@ class MediaDataManager(
    private val useQsMediaPlayer: Boolean,
    private val useQsMediaPlayer: Boolean,
    private val systemClock: SystemClock,
    private val systemClock: SystemClock,
    private val tunerService: TunerService,
    private val tunerService: TunerService,
    private val mediaFlags: MediaFlags
    private val mediaFlags: MediaFlags,
    private val logger: MediaUiEventLogger
) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener {
) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener {


    companion object {
    companion object {
@@ -202,12 +208,13 @@ class MediaDataManager(
        smartspaceMediaDataProvider: SmartspaceMediaDataProvider,
        smartspaceMediaDataProvider: SmartspaceMediaDataProvider,
        clock: SystemClock,
        clock: SystemClock,
        tunerService: TunerService,
        tunerService: TunerService,
        mediaFlags: MediaFlags
        mediaFlags: MediaFlags,
        logger: MediaUiEventLogger
    ) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory,
    ) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory,
            broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener,
            broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener,
            mediaSessionBasedFilter, mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter,
            mediaSessionBasedFilter, mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter,
            activityStarter, smartspaceMediaDataProvider, Utils.useMediaResumption(context),
            activityStarter, smartspaceMediaDataProvider, Utils.useMediaResumption(context),
            Utils.useQsMediaPlayer(context), clock, tunerService, mediaFlags)
            Utils.useQsMediaPlayer(context), clock, tunerService, mediaFlags, logger)


    private val appChangeReceiver = object : BroadcastReceiver() {
    private val appChangeReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
        override fun onReceive(context: Context, intent: Intent) {
@@ -298,17 +305,24 @@ class MediaDataManager(


    fun onNotificationAdded(key: String, sbn: StatusBarNotification) {
    fun onNotificationAdded(key: String, sbn: StatusBarNotification) {
        if (useQsMediaPlayer && isMediaNotification(sbn)) {
        if (useQsMediaPlayer && isMediaNotification(sbn)) {
            var logEvent = false
            Assert.isMainThread()
            Assert.isMainThread()
            val oldKey = findExistingEntry(key, sbn.packageName)
            val oldKey = findExistingEntry(key, sbn.packageName)
            if (oldKey == null) {
            if (oldKey == null) {
                val temp = LOADING.copy(packageName = sbn.packageName)
                val instanceId = logger.getNewInstanceId()
                val temp = LOADING.copy(
                    packageName = sbn.packageName,
                    instanceId = instanceId
                )
                mediaEntries.put(key, temp)
                mediaEntries.put(key, temp)
                logEvent = true
            } else if (oldKey != key) {
            } else if (oldKey != key) {
                // Move to new key
                // Resume -> active conversion; move to new key
                val oldData = mediaEntries.remove(oldKey)!!
                val oldData = mediaEntries.remove(oldKey)!!
                logEvent = true
                mediaEntries.put(key, oldData)
                mediaEntries.put(key, oldData)
            }
            }
            loadMediaData(key, sbn, oldKey)
            loadMediaData(key, sbn, oldKey, logEvent)
        } else {
        } else {
            onNotificationRemoved(key)
            onNotificationRemoved(key)
        }
        }
@@ -340,9 +354,23 @@ class MediaDataManager(
    ) {
    ) {
        // Resume controls don't have a notification key, so store by package name instead
        // Resume controls don't have a notification key, so store by package name instead
        if (!mediaEntries.containsKey(packageName)) {
        if (!mediaEntries.containsKey(packageName)) {
            val resumeData = LOADING.copy(packageName = packageName, resumeAction = action,
            val instanceId = logger.getNewInstanceId()
                hasCheckedForResume = true)
            val appUid = try {
                context.packageManager.getApplicationInfo(packageName, 0)?.uid!!
            } catch (e: PackageManager.NameNotFoundException) {
                Log.w(TAG, "Could not get app UID for $packageName", e)
                Process.INVALID_UID
            }

            val resumeData = LOADING.copy(
                packageName = packageName,
                resumeAction = action,
                hasCheckedForResume = true,
                instanceId = instanceId,
                appUid = appUid
            )
            mediaEntries.put(packageName, resumeData)
            mediaEntries.put(packageName, resumeData)
            logger.logResumeMediaAdded(appUid, packageName, instanceId)
        }
        }
        backgroundExecutor.execute {
        backgroundExecutor.execute {
            loadMediaDataInBgForResumption(userId, desc, action, token, appName, appIntent,
            loadMediaDataInBgForResumption(userId, desc, action, token, appName, appIntent,
@@ -368,10 +396,11 @@ class MediaDataManager(
    private fun loadMediaData(
    private fun loadMediaData(
        key: String,
        key: String,
        sbn: StatusBarNotification,
        sbn: StatusBarNotification,
        oldKey: String?
        oldKey: String?,
        logEvent: Boolean = false
    ) {
    ) {
        backgroundExecutor.execute {
        backgroundExecutor.execute {
            loadMediaDataInBg(key, sbn, oldKey)
            loadMediaDataInBg(key, sbn, oldKey, logEvent)
        }
        }
    }
    }


@@ -449,6 +478,10 @@ class MediaDataManager(
     */
     */
    internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) {
    internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) {
        mediaEntries[key]?.let {
        mediaEntries[key]?.let {
            if (timedOut && !forceUpdate) {
                // Only log this event when media expires on its own
                logger.logMediaTimeout(it.appUid, it.packageName, it.instanceId)
            }
            if (it.active == !timedOut && !forceUpdate) {
            if (it.active == !timedOut && !forceUpdate) {
                if (it.resumption) {
                if (it.resumption) {
                    if (DEBUG) Log.d(TAG, "timing out resume player $key")
                    if (DEBUG) Log.d(TAG, "timing out resume player $key")
@@ -463,7 +496,9 @@ class MediaDataManager(
    }
    }


    private fun removeEntry(key: String) {
    private fun removeEntry(key: String) {
        mediaEntries.remove(key)
        mediaEntries.remove(key)?.let {
            logger.logMediaRemoved(it.appUid, it.packageName, it.instanceId)
        }
        notifyMediaDataRemoved(key)
        notifyMediaDataRemoved(key)
    }
    }


@@ -537,6 +572,10 @@ class MediaDataManager(
            null
            null
        }
        }


        val currentEntry = mediaEntries.get(packageName)
        val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId()
        val appUid = currentEntry?.appUid ?: Process.INVALID_UID

        val mediaAction = getResumeMediaAction(resumeAction)
        val mediaAction = getResumeMediaAction(resumeAction)
        val lastActive = systemClock.elapsedRealtime()
        val lastActive = systemClock.elapsedRealtime()
        foregroundExecutor.execute {
        foregroundExecutor.execute {
@@ -545,14 +584,16 @@ class MediaDataManager(
                    MediaButton(playOrPause = mediaAction), packageName, token, appIntent,
                    MediaButton(playOrPause = mediaAction), packageName, token, appIntent,
                    device = null, active = false,
                    device = null, active = false,
                    resumeAction = resumeAction, resumption = true, notificationKey = packageName,
                    resumeAction = resumeAction, resumption = true, notificationKey = packageName,
                    hasCheckedForResume = true, lastActive = lastActive))
                    hasCheckedForResume = true, lastActive = lastActive, instanceId = instanceId,
                    appUid = appUid))
        }
        }
    }
    }


    private fun loadMediaDataInBg(
    private fun loadMediaDataInBg(
        key: String,
        key: String,
        sbn: StatusBarNotification,
        sbn: StatusBarNotification,
        oldKey: String?
        oldKey: String?,
        logEvent: Boolean = false
    ) {
    ) {
        val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION)
        val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION)
                as MediaSession.Token?
                as MediaSession.Token?
@@ -636,6 +677,22 @@ class MediaDataManager(
                        MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL) MediaData.PLAYBACK_LOCAL
                        MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL) MediaData.PLAYBACK_LOCAL
                else MediaData.PLAYBACK_CAST_LOCAL
                else MediaData.PLAYBACK_CAST_LOCAL
        val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null
        val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null

        val currentEntry = mediaEntries.get(key)
        val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId()
        val appUid = try {
            context.packageManager.getApplicationInfo(sbn.packageName, 0)?.uid!!
        } catch (e: PackageManager.NameNotFoundException) {
            Log.w(TAG, "Could not get app UID for ${sbn.packageName}", e)
            Process.INVALID_UID
        }

        if (logEvent) {
            logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation)
        } else if (playbackLocation != currentEntry?.playbackLocation) {
            logger.logPlaybackLocationChange(appUid, sbn.packageName, instanceId, playbackLocation)
        }

        val lastActive = systemClock.elapsedRealtime()
        val lastActive = systemClock.elapsedRealtime()
        foregroundExecutor.execute {
        foregroundExecutor.execute {
            val resumeAction: Runnable? = mediaEntries[key]?.resumeAction
            val resumeAction: Runnable? = mediaEntries[key]?.resumeAction
@@ -647,7 +704,7 @@ class MediaDataManager(
                    active, resumeAction = resumeAction, playbackLocation = playbackLocation,
                    active, resumeAction = resumeAction, playbackLocation = playbackLocation,
                    notificationKey = key, hasCheckedForResume = hasCheckedForResume,
                    notificationKey = key, hasCheckedForResume = hasCheckedForResume,
                    isPlaying = isPlaying, isClearable = sbn.isClearable(),
                    isPlaying = isPlaying, isClearable = sbn.isClearable(),
                    lastActive = lastActive))
                    lastActive = lastActive, instanceId = instanceId, appUid = appUid))
        }
        }
    }
    }


@@ -989,10 +1046,12 @@ class MediaDataManager(
                notifyMediaDataRemoved(key)
                notifyMediaDataRemoved(key)
                notifyMediaDataLoaded(pkg, pkg, updated)
                notifyMediaDataLoaded(pkg, pkg, updated)
            }
            }
            logger.logActiveConvertedToResume(updated.appUid, pkg, updated.instanceId)
            return
            return
        }
        }
        if (removed != null) {
        if (removed != null) {
            notifyMediaDataRemoved(key)
            notifyMediaDataRemoved(key)
            logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId)
        }
        }
    }
    }


@@ -1009,6 +1068,7 @@ class MediaDataManager(
            filtered.forEach {
            filtered.forEach {
                mediaEntries.remove(it.key)
                mediaEntries.remove(it.key)
                notifyMediaDataRemoved(it.key)
                notifyMediaDataRemoved(it.key)
                logger.logMediaRemoved(it.value.appUid, it.value.packageName, it.value.instanceId)
            }
            }
        }
        }
    }
    }
Loading