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

Commit a7d4027e authored by Michael Mikhail's avatar Michael Mikhail
Browse files

Add logs when media is loaded or removed

This CL adds logs to new media pipeline when media is loaded or removed
at the ending point of the pipeline.

Flag: com.android.systemui.scene_container
Bug: 326958702
Test: atest MediaDataFilterImplTest
Change-Id: I668022c2d567a188917754d1482f227dec84dc46
parent 03482623
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -364,6 +364,16 @@ public class LogModule {
        return factory.create("MediaCarouselCtlrLog", 20);
    }

    /**
     * Provides a buffer for media loading changes
     */
    @Provides
    @SysUISingleton
    @MediaLoadingLog
    public static LogBuffer providesMediaLoadingLogBuffer(LogBufferFactory factory) {
        return factory.create("MediaLoadingLog", 20);
    }

    /** Allows logging buffers to be tweaked via adb on debug builds but not on prod builds. */
    @Provides
    @SysUISingleton
+26 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.log.dagger

import com.android.systemui.log.LogBuffer
import javax.inject.Qualifier

/** A [LogBuffer] for [com.android.systemui.media.controls.domain.pipeline.MediaLoadingLogger] */
@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class MediaLoadingLog
+32 −9
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import com.android.internal.annotations.KeepForWeakReference
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.logging.InstanceId
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.controls.data.repository.MediaFilterRepository
import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_RESUME
@@ -56,6 +57,7 @@ private const val RESUMABLE_MEDIA_MAX_AGE_SECONDS_KEY = "resumable_media_max_age
 * This is added at the end of the pipeline since we may still need to handle callbacks from
 * background users (e.g. timeouts).
 */
@SysUISingleton
class MediaDataFilterImpl
@Inject
constructor(
@@ -68,11 +70,13 @@ constructor(
    private val logger: MediaUiEventLogger,
    private val mediaFlags: MediaFlags,
    private val mediaFilterRepository: MediaFilterRepository,
    private val mediaLoadingLogger: MediaLoadingLogger,
) : MediaDataManager.Listener {
    /** Non-UI listeners to media changes. */
    private val _listeners: MutableSet<MediaDataProcessor.Listener> = mutableSetOf()
    val listeners: Set<MediaDataProcessor.Listener>
        get() = _listeners.toSet()

    lateinit var mediaDataProcessor: MediaDataProcessor

    // Ensure the field (and associated reference) isn't removed during optimization.
@@ -114,6 +118,7 @@ constructor(

        mediaFilterRepository.addSelectedUserMediaEntry(data)

        mediaLoadingLogger.logMediaLoaded(data.instanceId, data.active, "loading media")
        mediaFilterRepository.addMediaDataLoadingState(
            MediaDataLoadingModel.Loaded(data.instanceId)
        )
@@ -167,7 +172,6 @@ constructor(
            if (shouldReactivate) {
                val lastActiveId = sorted.lastKey() // most recently active id
                // Update loading state to consider this media active
                Log.d(TAG, "reactivating $lastActiveId instead of smartspace")
                mediaFilterRepository.setReactivatedId(lastActiveId)
                val mediaData = sorted[lastActiveId]!!.copy(active = true)
                logger.logRecommendationActivated(
@@ -178,6 +182,11 @@ constructor(
                mediaFilterRepository.addMediaDataLoadingState(
                    MediaDataLoadingModel.Loaded(lastActiveId)
                )
                mediaLoadingLogger.logMediaLoaded(
                    mediaData.instanceId,
                    mediaData.active,
                    "reactivating media instead of smartspace"
                )
                listeners.forEach { listener ->
                    getKey(lastActiveId)?.let { lastActiveKey ->
                        listener.onMediaDataLoaded(
@@ -210,6 +219,7 @@ constructor(
        mediaFilterRepository.setRecommendationsLoadingState(
            SmartspaceMediaLoadingModel.Loaded(key, shouldPrioritizeMutable)
        )
        mediaLoadingLogger.logRecommendationLoaded(key, data.isActive, "loading recommendations")
        listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable) }
    }

@@ -220,6 +230,7 @@ constructor(
                mediaFilterRepository.addMediaDataLoadingState(
                    MediaDataLoadingModel.Removed(instanceId)
                )
                mediaLoadingLogger.logMediaRemoved(instanceId, "removing media card")
                // Only notify listeners if something actually changed
                listeners.forEach { it.onMediaDataRemoved(key, userInitiated) }
            }
@@ -230,12 +241,16 @@ constructor(
        // First check if we had reactivated media instead of forwarding smartspace
        mediaFilterRepository.reactivatedId.value?.let { lastActiveId ->
            mediaFilterRepository.setReactivatedId(null)
            Log.d(TAG, "expiring reactivated key $lastActiveId")
            // Update loading state with actual active value
            mediaFilterRepository.selectedUserEntries.value[lastActiveId]?.let {
                mediaFilterRepository.addMediaDataLoadingState(
                    MediaDataLoadingModel.Loaded(lastActiveId, immediately)
                )
                mediaLoadingLogger.logMediaLoaded(
                    lastActiveId,
                    it.active,
                    "expiring reactivated id"
                )
                listeners.forEach { listener ->
                    getKey(lastActiveId)?.let { lastActiveKey ->
                        listener.onMediaDataLoaded(lastActiveKey, lastActiveKey, it, immediately)
@@ -256,6 +271,11 @@ constructor(
        mediaFilterRepository.setRecommendationsLoadingState(
            SmartspaceMediaLoadingModel.Removed(key, immediately)
        )
        mediaLoadingLogger.logRecommendationRemoved(
            key,
            immediately,
            "removing recommendations card"
        )
        listeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) }
    }

@@ -265,11 +285,14 @@ constructor(
        mediaFilterRepository.allUserEntries.value.forEach { (key, data) ->
            if (!lockscreenUserManager.isProfileAvailable(data.userId)) {
                // Only remove media when the profile is unavailable.
                if (DEBUG) Log.d(TAG, "Removing $key after profile change")
                mediaFilterRepository.removeSelectedUserMediaEntry(data.instanceId, data)
                mediaFilterRepository.addMediaDataLoadingState(
                    MediaDataLoadingModel.Removed(data.instanceId)
                )
                mediaLoadingLogger.logMediaRemoved(
                    data.instanceId,
                    "Removing $key after profile change"
                )
                listeners.forEach { listener -> listener.onMediaDataRemoved(key, false) }
            }
        }
@@ -283,10 +306,10 @@ constructor(
        // Clear the list first and update loading state to remove media from UI.
        mediaFilterRepository.clearSelectedUserMedia()
        keyCopy.forEach { instanceId ->
            if (DEBUG) Log.d(TAG, "Removing $instanceId after user change")
            mediaFilterRepository.addMediaDataLoadingState(
                MediaDataLoadingModel.Removed(instanceId)
            )
            mediaLoadingLogger.logMediaRemoved(instanceId, "Removing media after user change")
            getKey(instanceId)?.let {
                listenersCopy.forEach { listener -> listener.onMediaDataRemoved(it, false) }
            }
@@ -294,15 +317,15 @@ constructor(

        mediaFilterRepository.allUserEntries.value.forEach { (key, data) ->
            if (lockscreenUserManager.isCurrentProfile(data.userId)) {
                if (DEBUG)
                    Log.d(
                        TAG,
                        "Re-adding $key with instanceId=${data.instanceId} after user change"
                    )
                mediaFilterRepository.addSelectedUserMediaEntry(data)
                mediaFilterRepository.addMediaDataLoadingState(
                    MediaDataLoadingModel.Loaded(data.instanceId)
                )
                mediaLoadingLogger.logMediaLoaded(
                    data.instanceId,
                    data.active,
                    "Re-adding $key after user change"
                )
                listenersCopy.forEach { listener -> listener.onMediaDataLoaded(key, null, data) }
            }
        }
+84 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.media.controls.domain.pipeline

import com.android.internal.logging.InstanceId
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.dagger.MediaLoadingLog
import javax.inject.Inject

/** A buffered log for media loading events. */
@SysUISingleton
class MediaLoadingLogger @Inject constructor(@MediaLoadingLog private val buffer: LogBuffer) {

    fun logMediaLoaded(instanceId: InstanceId, active: Boolean, reason: String) {
        buffer.log(
            TAG,
            LogLevel.DEBUG,
            {
                str1 = instanceId.toString()
                bool1 = active
                str2 = reason
            },
            { "add media $str1, active: $bool1, reason: $str2" }
        )
    }

    fun logMediaRemoved(instanceId: InstanceId, reason: String) {
        buffer.log(
            TAG,
            LogLevel.DEBUG,
            {
                str1 = instanceId.toString()
                str2 = reason
            },
            { "removing media $str1, reason: $str2" }
        )
    }

    fun logRecommendationLoaded(key: String, isActive: Boolean, reason: String) {
        buffer.log(
            TAG,
            LogLevel.DEBUG,
            {
                str1 = key
                bool1 = isActive
                str2 = reason
            },
            { "add recommendation $str1, active $bool1, reason: $str2" }
        )
    }

    fun logRecommendationRemoved(key: String, immediately: Boolean, reason: String) {
        buffer.log(
            TAG,
            LogLevel.DEBUG,
            {
                str1 = key
                bool1 = immediately
                str2 = reason
            },
            { "removing recommendation $str1, immediate=$bool1, reason: $str2" }
        )
    }

    companion object {
        private const val TAG = "MediaLoadingLog"
    }
}
+9 −3
Original line number Diff line number Diff line
@@ -155,13 +155,17 @@ constructor(
                            mediaFlags.isPersistentSsCardEnabled(),
                    recsViewModel = recommendationsViewModel,
                    onAdded = { commonViewModel ->
                        onMediaRecommendationAddedOrUpdated(commonViewModel)
                        onMediaRecommendationAddedOrUpdated(
                            commonViewModel as MediaCommonViewModel.MediaRecommendations
                        )
                    },
                    onRemoved = { immediatelyRemove ->
                        onMediaRecommendationRemoved(commonModel, immediatelyRemove)
                    },
                    onUpdated = { commonViewModel ->
                        onMediaRecommendationAddedOrUpdated(commonViewModel)
                        onMediaRecommendationAddedOrUpdated(
                            commonViewModel as MediaCommonViewModel.MediaRecommendations
                        )
                    },
                )
                .also { mediaRecs = it }
@@ -185,7 +189,9 @@ constructor(
        }
    }

    private fun onMediaRecommendationAddedOrUpdated(commonViewModel: MediaCommonViewModel) {
    private fun onMediaRecommendationAddedOrUpdated(
        commonViewModel: MediaCommonViewModel.MediaRecommendations
    ) {
        if (!interactor.isRecommendationActive()) {
            if (!mediaFlags.isPersistentSsCardEnabled()) {
                commonViewModel.onRemoved(true)
Loading