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

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

Merge "Update media_controls_lock_screen setting behavior" into main

parents 3857a2ee f8371635
Loading
Loading
Loading
Loading
+0 −43
Original line number Diff line number Diff line
@@ -18,17 +18,11 @@ package com.android.systemui.media.controls.ui.controller

import android.content.Context
import android.content.res.Configuration
import android.database.ContentObserver
import android.net.Uri
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
import android.view.View
import android.view.ViewGroup
import androidx.annotation.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.MigrateClocksToBlueprint
import com.android.systemui.media.controls.ui.view.MediaHost
@@ -43,7 +37,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.SplitShadeStateController
import com.android.systemui.util.asIndenting
import com.android.systemui.util.println
import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.withIncreasedIndent
import java.io.PrintWriter
import javax.inject.Inject
@@ -61,8 +54,6 @@ constructor(
    private val bypassController: KeyguardBypassController,
    private val statusBarStateController: SysuiStatusBarStateController,
    private val context: Context,
    private val secureSettings: SecureSettings,
    @Main private val handler: Handler,
    configurationController: ConfigurationController,
    private val splitShadeStateController: SplitShadeStateController,
    private val logger: KeyguardMediaControllerLogger,
@@ -91,26 +82,6 @@ constructor(
            }
        )

        val settingsObserver: ContentObserver =
            object : ContentObserver(handler) {
                override fun onChange(selfChange: Boolean, uri: Uri?) {
                    if (uri == lockScreenMediaPlayerUri) {
                        allowMediaPlayerOnLockScreen =
                            secureSettings.getBoolForUser(
                                Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN,
                                true,
                                UserHandle.USER_CURRENT
                            )
                        refreshMediaPosition(reason = "allowMediaPlayerOnLockScreen changed")
                    }
                }
            }
        secureSettings.registerContentObserverForUser(
            Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN,
            settingsObserver,
            UserHandle.USER_ALL
        )

        // First let's set the desired state that we want for this host
        mediaHost.expansion = MediaHostState.EXPANDED
        mediaHost.showsOnlyActiveMedia = true
@@ -156,16 +127,6 @@ constructor(
        private set
    private var splitShadeContainer: ViewGroup? = null

    /** Track the media player setting status on lock screen. */
    private var allowMediaPlayerOnLockScreen: Boolean =
        secureSettings.getBoolForUser(
            Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN,
            true,
            UserHandle.USER_CURRENT
        )
    private val lockScreenMediaPlayerUri =
        secureSettings.getUriFor(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN)

    /**
     * Attaches media container in single pane mode, situated at the top of the notifications list
     */
@@ -229,14 +190,12 @@ constructor(
        // mediaHost.visible required for proper animations handling
        val isMediaHostVisible = mediaHost.visible
        val isBypassNotEnabled = !bypassController.bypassEnabled
        val currentAllowMediaPlayerOnLockScreen = allowMediaPlayerOnLockScreen
        val useSplitShade = useSplitShade
        val shouldBeVisibleForSplitShade = shouldBeVisibleForSplitShade()
        visible =
            isMediaHostVisible &&
                isBypassNotEnabled &&
                keyguardOrUserSwitcher &&
                currentAllowMediaPlayerOnLockScreen &&
                shouldBeVisibleForSplitShade
        logger.logRefreshMediaPosition(
            reason = reason,
@@ -246,7 +205,6 @@ constructor(
            keyguardOrUserSwitcher = keyguardOrUserSwitcher,
            mediaHostVisible = isMediaHostVisible,
            bypassNotEnabled = isBypassNotEnabled,
            currentAllowMediaPlayerOnLockScreen = currentAllowMediaPlayerOnLockScreen,
            shouldBeVisibleForSplitShade = shouldBeVisibleForSplitShade,
        )
        val currActiveContainer = activeContainer
@@ -321,7 +279,6 @@ constructor(
                println("Self", this@KeyguardMediaController)
                println("visible", visible)
                println("useSplitShade", useSplitShade)
                println("allowMediaPlayerOnLockScreen", allowMediaPlayerOnLockScreen)
                println("bypassController.bypassEnabled", bypassController.bypassEnabled)
                println("isDozeWakeUpAnimationWaiting", isDozeWakeUpAnimationWaiting)
                println("singlePaneContainer", singlePaneContainer)
+2 −5
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ constructor(@KeyguardMediaControllerLog private val logBuffer: LogBuffer) {
        keyguardOrUserSwitcher: Boolean,
        mediaHostVisible: Boolean,
        bypassNotEnabled: Boolean,
        currentAllowMediaPlayerOnLockScreen: Boolean,
        shouldBeVisibleForSplitShade: Boolean,
    ) {
        logBuffer.log(
@@ -50,8 +49,7 @@ constructor(@KeyguardMediaControllerLog private val logBuffer: LogBuffer) {
                bool3 = keyguardOrUserSwitcher
                bool4 = mediaHostVisible
                int2 = if (bypassNotEnabled) 1 else 0
                str2 = currentAllowMediaPlayerOnLockScreen.toString()
                str3 = shouldBeVisibleForSplitShade.toString()
                str2 = shouldBeVisibleForSplitShade.toString()
            },
            {
                "refreshMediaPosition(reason=$str1, " +
@@ -60,8 +58,7 @@ constructor(@KeyguardMediaControllerLog private val logBuffer: LogBuffer) {
                    "keyguardOrUserSwitcher=$bool3, " +
                    "mediaHostVisible=$bool4, " +
                    "bypassNotEnabled=${int2 == 1}, " +
                    "currentAllowMediaPlayerOnLockScreen=$str2, " +
                    "shouldBeVisibleForSplitShade=$str3)"
                    "shouldBeVisibleForSplitShade=$str2)"
            }
        )
    }
+66 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.Intent
import android.content.res.ColorStateList
import android.content.res.Configuration
import android.database.ContentObserver
import android.os.UserHandle
import android.provider.Settings
import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
import android.util.Log
@@ -44,6 +45,7 @@ import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
@@ -76,6 +78,8 @@ import com.android.systemui.util.animation.UniqueObjectHostView
import com.android.systemui.util.animation.requiresRemeasuring
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.settings.GlobalSettings
import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import java.util.Locale
@@ -83,10 +87,16 @@ import java.util.TreeMap
import java.util.concurrent.Executor
import javax.inject.Inject
import javax.inject.Provider
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

private const val TAG = "MediaCarouselController"
private val settingsIntent = Intent().setAction(ACTION_MEDIA_CONTROLS_SETTINGS)
@@ -108,6 +118,7 @@ constructor(
    private val systemClock: SystemClock,
    @Main executor: DelayableExecutor,
    @Background private val bgExecutor: Executor,
    @Background private val backgroundDispatcher: CoroutineDispatcher,
    private val mediaManager: MediaDataManager,
    configurationController: ConfigurationController,
    falsingManager: FalsingManager,
@@ -118,6 +129,7 @@ constructor(
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
    private val globalSettings: GlobalSettings,
    private val secureSettings: SecureSettings,
) : Dumpable {
    /** The current width of the carousel */
    var currentCarouselWidth: Int = 0
@@ -191,6 +203,8 @@ constructor(
            }
        }

    private var allowMediaPlayerOnLockScreen = false

    /** Whether the media card currently has the "expanded" layout */
    @VisibleForTesting
    var currentlyExpanded = true
@@ -532,8 +546,9 @@ constructor(
        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
        mediaCarousel.repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                // A backup to show media carousel (if available) once the keyguard is gone.
                listenForAnyStateToGoneKeyguardTransition(this)
                listenForAnyStateToLockscreenTransition(this)
                listenForLockscreenSettingChanges(this)
            }
        }

@@ -587,7 +602,49 @@ constructor(
        return scope.launch {
            keyguardTransitionInteractor.anyStateToGoneTransition
                .filter { it.transitionState == TransitionState.FINISHED }
                .collect { showMediaCarousel() }
                .collect {
                    showMediaCarousel()
                    updateHostVisibility()
                }
        }
    }

    @VisibleForTesting
    internal fun listenForAnyStateToLockscreenTransition(scope: CoroutineScope): Job {
        return scope.launch {
            keyguardTransitionInteractor.anyStateToLockscreenTransition
                .filter { it.transitionState == TransitionState.FINISHED }
                .collect {
                    if (!allowMediaPlayerOnLockScreen) {
                        updateHostVisibility()
                    }
                }
        }
    }

    @VisibleForTesting
    internal fun listenForLockscreenSettingChanges(scope: CoroutineScope): Job {
        return scope.launch {
            secureSettings
                .observerFlow(UserHandle.USER_ALL, Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN)
                // query to get initial value
                .onStart { emit(Unit) }
                .map { getMediaLockScreenSetting() }
                .distinctUntilChanged()
                .collectLatest {
                    allowMediaPlayerOnLockScreen = it
                    updateHostVisibility()
                }
        }
    }

    private suspend fun getMediaLockScreenSetting(): Boolean {
        return withContext(backgroundDispatcher) {
            secureSettings.getBoolForUser(
                Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN,
                true,
                UserHandle.USER_CURRENT
            )
        }
    }

@@ -600,6 +657,13 @@ constructor(
        updatePlayers(recreateMedia = true)
    }

    /** Return true if the carousel should be hidden because lockscreen is currently visible */
    fun isLockedAndHidden(): Boolean {
        val keyguardState = keyguardTransitionInteractor.getFinishedState()
        return !allowMediaPlayerOnLockScreen &&
            KeyguardState.lockscreenVisibleInState(keyguardState)
    }

    private fun reorderAllPlayers(
        previousVisiblePlayerKey: MediaPlayerData.MediaSortKey?,
        key: String? = null
+7 −4
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.view.View.OnAttachStateChangeListener
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
import com.android.systemui.media.controls.ui.controller.MediaCarouselController
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
import com.android.systemui.media.controls.ui.controller.MediaHostStatesManager
import com.android.systemui.media.controls.ui.controller.MediaLocation
@@ -33,12 +34,12 @@ import com.android.systemui.util.animation.UniqueObjectHostView
import java.util.Objects
import javax.inject.Inject

class MediaHost
constructor(
class MediaHost(
    private val state: MediaHostStateHolder,
    private val mediaHierarchyManager: MediaHierarchyManager,
    private val mediaDataManager: MediaDataManager,
    private val mediaHostStatesManager: MediaHostStatesManager
    private val mediaHostStatesManager: MediaHostStatesManager,
    private val mediaCarouselController: MediaCarouselController,
) : MediaHostState by state {
    lateinit var hostView: UniqueObjectHostView
    var location: Int = -1
@@ -202,7 +203,9 @@ constructor(
     */
    fun updateViewVisibility() {
        state.visible =
            if (showsOnlyActiveMedia) {
            if (mediaCarouselController.isLockedAndHidden()) {
                false
            } else if (showsOnlyActiveMedia) {
                mediaDataManager.hasActiveMediaOrRecommendation()
            } else {
                mediaDataManager.hasAnyMediaOrRecommendation()
+16 −10
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.LogBufferFactory;
import com.android.systemui.media.controls.domain.MediaDomainModule;
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager;
import com.android.systemui.media.controls.ui.controller.MediaCarouselController;
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager;
import com.android.systemui.media.controls.ui.controller.MediaHostStatesManager;
import com.android.systemui.media.controls.ui.view.MediaHost;
@@ -59,8 +60,9 @@ public interface MediaModule {
    @Named(QS_PANEL)
    static MediaHost providesQSMediaHost(MediaHost.MediaHostStateHolder stateHolder,
            MediaHierarchyManager hierarchyManager, MediaDataManager dataManager,
            MediaHostStatesManager statesManager) {
        return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager);
            MediaHostStatesManager statesManager, MediaCarouselController carouselController) {
        return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager,
                carouselController);
    }

    /** */
@@ -69,8 +71,9 @@ public interface MediaModule {
    @Named(QUICK_QS_PANEL)
    static MediaHost providesQuickQSMediaHost(MediaHost.MediaHostStateHolder stateHolder,
            MediaHierarchyManager hierarchyManager, MediaDataManager dataManager,
            MediaHostStatesManager statesManager) {
        return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager);
            MediaHostStatesManager statesManager, MediaCarouselController carouselController) {
        return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager,
                carouselController);
    }

    /** */
@@ -79,8 +82,9 @@ public interface MediaModule {
    @Named(KEYGUARD)
    static MediaHost providesKeyguardMediaHost(MediaHost.MediaHostStateHolder stateHolder,
            MediaHierarchyManager hierarchyManager, MediaDataManager dataManager,
            MediaHostStatesManager statesManager) {
        return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager);
            MediaHostStatesManager statesManager, MediaCarouselController carouselController) {
        return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager,
                carouselController);
    }

    /** */
@@ -89,8 +93,9 @@ public interface MediaModule {
    @Named(DREAM)
    static MediaHost providesDreamMediaHost(MediaHost.MediaHostStateHolder stateHolder,
            MediaHierarchyManager hierarchyManager, MediaDataManager dataManager,
            MediaHostStatesManager statesManager) {
        return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager);
            MediaHostStatesManager statesManager, MediaCarouselController carouselController) {
        return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager,
                carouselController);
    }

    /** */
@@ -99,8 +104,9 @@ public interface MediaModule {
    @Named(COMMUNAL_HUB)
    static MediaHost providesCommunalMediaHost(MediaHost.MediaHostStateHolder stateHolder,
            MediaHierarchyManager hierarchyManager, MediaDataManager dataManager,
            MediaHostStatesManager statesManager) {
        return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager);
            MediaHostStatesManager statesManager, MediaCarouselController carouselController) {
        return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager,
                carouselController);
    }

    /** Provides a logging buffer related to the media tap-to-transfer chip on the sender device. */
Loading