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

Commit 719f5171 authored by Jieru Shi's avatar Jieru Shi Committed by Automerger Merge Worker
Browse files

Merge "Media impression logging bug fix" into sc-dev am: b247011e

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14728374

Change-Id: I99d7456fe5c791dc8ee4b8670e26c01442626a97
parents f152f0b7 b247011e
Loading
Loading
Loading
Loading
+67 −12
Original line number Diff line number Diff line
@@ -156,6 +156,12 @@ class MediaCarouselController @Inject constructor(
        }
    }

    /**
     * Update MediaCarouselScrollHandler.visibleToUser to reflect media card container visibility.
     * It will be called when the container is out of view.
     */
    lateinit var updateUserVisibility: () -> Unit

    init {
        mediaFrame = inflateMediaCarousel()
        mediaCarousel = mediaFrame.requireViewById(R.id.media_carousel_scroller)
@@ -177,6 +183,12 @@ class MediaCarouselController @Inject constructor(
            keysNeedRemoval.forEach { removePlayer(it) }
            keysNeedRemoval.clear()

            // Update user visibility so that no extra impression will be logged when
            // activeMediaIndex resets to 0
            if (this::updateUserVisibility.isInitialized) {
                updateUserVisibility()
            }

            // Let's reset our scroll position
            mediaCarouselScrollHandler.scrollToStart()
        }
@@ -187,16 +199,24 @@ class MediaCarouselController @Inject constructor(
                key: String,
                oldKey: String?,
                data: MediaData,
                immediately: Boolean
                immediately: Boolean,
                isSsReactivated: Boolean
            ) {
                if (addOrUpdatePlayer(key, oldKey, data)) {
                    MediaPlayerData.getMediaPlayer(key, null)?.let {
                        logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                                it.mInstanceId,
                                /* isRecommendationCard */ false,
                                it.surfaceForSmartspaceLogging)
                                it.surfaceForSmartspaceLogging,
                                rank = MediaPlayerData.getMediaPlayerIndex(key))
                    }
                }
                if (mediaCarouselScrollHandler.visibleToUser &&
                        isSsReactivated && !mediaCarouselScrollHandler.qsExpanded) {
                    // It could happen that reactived media player isn't visible to user because
                    // of it is a resumption card.
                    logSmartspaceImpression(mediaCarouselScrollHandler.qsExpanded)
                }
                val canRemove = data.isPlaying?.let { !it } ?: data.isClearable && !data.active
                if (canRemove && !Utils.useMediaResumption(context)) {
                    // This view isn't playing, let's remove this! This happens e.g when
@@ -222,12 +242,19 @@ class MediaCarouselController @Inject constructor(
                    addSmartspaceMediaRecommendations(key, data, shouldPrioritize)
                    MediaPlayerData.getMediaPlayer(key, null)?.let {
                        logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
                                it.mInstanceId,
                                /* isRecommendationCard */ true,
                                it.surfaceForSmartspaceLogging,
                                rank = MediaPlayerData.getMediaPlayerIndex(key))

                        if (mediaCarouselScrollHandler.visibleToUser &&
                                mediaCarouselScrollHandler.visibleMediaIndex ==
                                MediaPlayerData.getMediaPlayerIndex(key)) {
                            logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN
                                    it.mInstanceId,
                                    /* isRecommendationCard */ true,
                                    it.surfaceForSmartspaceLogging)
                        }
                    if (mediaCarouselScrollHandler.visibleToUser) {
                        logSmartspaceImpression()
                    }
                } else {
                    onSmartspaceMediaDataRemoved(data.targetId, immediately = true)
@@ -644,17 +671,17 @@ class MediaCarouselController @Inject constructor(
    }

    /**
     * Log the user impression for media card.
     * Log the user impression for media card at visibleMediaIndex.
     */
    fun logSmartspaceImpression() {
    fun logSmartspaceImpression(qsExpanded: Boolean) {
        val visibleMediaIndex = mediaCarouselScrollHandler.visibleMediaIndex
        if (MediaPlayerData.players().size > visibleMediaIndex) {
            val mediaControlPanel = MediaPlayerData.players().elementAt(visibleMediaIndex)
            val isMediaActive =
                    MediaPlayerData.playerKeys().elementAt(visibleMediaIndex).data?.active
            val hasActiveMediaOrRecommendationCard =
                    MediaPlayerData.hasActiveMediaOrRecommendationCard()
            val isRecommendationCard = mediaControlPanel.recommendationViewHolder != null
            if (!isRecommendationCard && !isMediaActive) {
                // Media control card time out or swiped away
            if (!hasActiveMediaOrRecommendationCard && !qsExpanded) {
                // Skip logging if on LS or QQS, and there is no active media card
                return
            }
            logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN
@@ -672,6 +699,13 @@ class MediaCarouselController @Inject constructor(
        surface: Int,
        rank: Int = mediaCarouselScrollHandler.visibleMediaIndex
    ) {
        // Only log media resume card when Smartspace data is available
        if (!isRecommendationCard &&
                        !mediaManager.smartspaceMediaData.isActive &&
                                MediaPlayerData.smartspaceMediaData == null) {
            return
        }

        /* ktlint-disable max-line-length */
        SysUiStatsLog.write(SysUiStatsLog.SMARTSPACE_CARD_REPORTED,
                eventId,
@@ -770,6 +804,16 @@ internal object MediaPlayerData {
        return mediaData.get(key)?.let { mediaPlayers.get(it) }
    }

    fun getMediaPlayerIndex(key: String): Int {
        val sortKey = mediaData.get(key)
        mediaPlayers.entries.forEachIndexed { index, e ->
            if (e.key == sortKey) {
                return index
            }
        }
        return -1
    }

    fun removeMediaPlayer(key: String) = mediaData.remove(key)?.let {
        if (it.isSsMediaRec) {
            smartspaceMediaData = null
@@ -808,4 +852,15 @@ internal object MediaPlayerData {
        mediaData.clear()
        mediaPlayers.clear()
    }

    /* Returns true if there is active media player card or recommendation card */
    fun hasActiveMediaOrRecommendationCard(): Boolean {
        if (smartspaceMediaData != null && smartspaceMediaData?.isActive!!) {
            return true
        }
        if (firstActiveMediaIndex() != -1) {
            return true
        }
        return false
    }
}
+11 −7
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ class MediaCarouselScrollHandler(
    private val closeGuts: (immediate: Boolean) -> Unit,
    private val falsingCollector: FalsingCollector,
    private val falsingManager: FalsingManager,
    private val logSmartspaceImpression: () -> Unit
    private val logSmartspaceImpression: (Boolean) -> Unit
) {
    /**
     * Is the view in RTL
@@ -195,18 +195,22 @@ class MediaCarouselScrollHandler(
            if (playerWidthPlusPadding == 0) {
                return
            }

            val relativeScrollX = scrollView.relativeScrollX
            onMediaScrollingChanged(relativeScrollX / playerWidthPlusPadding,
                    relativeScrollX % playerWidthPlusPadding)
        }
    }

    /**
     * Whether the media card is visible to user if any
     */
    var visibleToUser: Boolean = false
        set(value) {
            if (field != value) {
                field = value
            }
        }

    /**
     * Whether the quick setting is expanded or not
     */
    var qsExpanded: Boolean = false

    init {
        gestureDetector = GestureDetectorCompat(scrollView.context, gestureListener)
@@ -471,7 +475,7 @@ class MediaCarouselScrollHandler(
            val oldIndex = visibleMediaIndex
            visibleMediaIndex = newIndex
            if (oldIndex != visibleMediaIndex && visibleToUser) {
                logSmartspaceImpression()
                logSmartspaceImpression(qsExpanded)
            }
            closeGuts(false)
            updatePlayerVisibilities()
+2 −2
Original line number Diff line number Diff line
@@ -266,7 +266,7 @@ public class MediaControlPanel {
        }
        mKey = key;
        MediaSession.Token token = data.getToken();
        mInstanceId = data.getPackageName().hashCode();
        mInstanceId = SmallHash.hash(data.getPackageName());

        mBackgroundColor = data.getBackgroundColor();
        if (mToken == null || !mToken.equals(token)) {
@@ -504,7 +504,7 @@ public class MediaControlPanel {
            return;
        }

        mInstanceId = data.getTargetId().hashCode();
        mInstanceId = SmallHash.hash(data.getTargetId());
        mBackgroundColor = data.getBackgroundColor();
        TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations();
        recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor));
+2 −1
Original line number Diff line number Diff line
@@ -31,7 +31,8 @@ class MediaDataCombineLatest @Inject constructor() : MediaDataManager.Listener,
        key: String,
        oldKey: String?,
        data: MediaData,
        immediately: Boolean
        immediately: Boolean,
        isSsReactivated: Boolean
    ) {
        if (oldKey != null && oldKey != key && entries.contains(oldKey)) {
            entries[key] = data to entries.remove(oldKey)?.second
+10 −3
Original line number Diff line number Diff line
@@ -83,7 +83,8 @@ class MediaDataFilter @Inject constructor(
        key: String,
        oldKey: String?,
        data: MediaData,
        immediately: Boolean
        immediately: Boolean,
        isSsReactivated: Boolean
    ) {
        if (oldKey != null && oldKey != key) {
            allEntries.remove(oldKey)
@@ -101,7 +102,7 @@ class MediaDataFilter @Inject constructor(

        // Notify listeners
        listeners.forEach {
            it.onMediaDataLoaded(key, oldKey, data)
            it.onMediaDataLoaded(key, oldKey, data, isSsReactivated = isSsReactivated)
        }
    }

@@ -118,6 +119,8 @@ class MediaDataFilter @Inject constructor(
        // Override the pass-in value here, as the order of Smartspace card is only determined here.
        var shouldPrioritizeMutable = false
        smartspaceMediaData = data
        // Override the pass-in value here, as the Smartspace reactivation could only happen here.
        var isSsReactivated = false

        // Before forwarding the smartspace target, first check if we have recently inactive media
        val sorted = userEntries.toSortedMap(compareBy {
@@ -137,9 +140,13 @@ class MediaDataFilter @Inject constructor(
            // Notify listeners to consider this media active
            Log.d(TAG, "reactivating $lastActiveKey instead of smartspace")
            reactivatedKey = lastActiveKey
            if (MediaPlayerData.firstActiveMediaIndex() == -1) {
                isSsReactivated = true
            }
            val mediaData = sorted.get(lastActiveKey)!!.copy(active = true)
            listeners.forEach {
                it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData)
                it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData,
                        isSsReactivated = isSsReactivated)
            }
        } else {
            // Mark to prioritize Smartspace card if no recent media.
Loading