Merge "Add media on lock screen setting" into tm-qpr-dev am: c24db189bf

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

Change-Id: I2bb99a98c7c683f86157e00553ecc47cf276f4f5
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Michael Mikhail
2022-08-22 15:04:04 +00:00
committed by Automerger Merge Worker
7 changed files with 153 additions and 65 deletions

View File

@@ -10590,6 +10590,13 @@ public final class Settings {
@Readable @Readable
public static final String MEDIA_CONTROLS_RESUME = "qs_media_resumption"; public static final String MEDIA_CONTROLS_RESUME = "qs_media_resumption";
/**
* Whether to enable media controls on lock screen.
* When enabled, media controls will appear on lock screen.
* @hide
*/
public static final String MEDIA_CONTROLS_LOCK_SCREEN = "media_controls_lock_screen";
/** /**
* Controls whether contextual suggestions can be shown in the media controls. * Controls whether contextual suggestions can be shown in the media controls.
* @hide * @hide

View File

@@ -182,6 +182,7 @@ public class SecureSettings {
Settings.Secure.PEOPLE_STRIP, Settings.Secure.PEOPLE_STRIP,
Settings.Secure.MEDIA_CONTROLS_RESUME, Settings.Secure.MEDIA_CONTROLS_RESUME,
Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION, Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY,

View File

@@ -277,6 +277,7 @@ public class SecureSettingsValidators {
VALIDATORS.put(Secure.PEOPLE_STRIP, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.PEOPLE_STRIP, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.MEDIA_CONTROLS_RESUME, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.MEDIA_CONTROLS_RESUME, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.MEDIA_CONTROLS_RECOMMENDATION, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.MEDIA_CONTROLS_RECOMMENDATION, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.MEDIA_CONTROLS_LOCK_SCREEN, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_MODE, VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
new InclusiveIntegerRangeValidator( new InclusiveIntegerRangeValidator(
Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN, Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,

View File

@@ -18,19 +18,25 @@ package com.android.systemui.media
import android.content.Context import android.content.Context
import android.content.res.Configuration 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.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.dagger.MediaModule.KEYGUARD import com.android.systemui.media.dagger.MediaModule.KEYGUARD
import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.MediaContainerView import com.android.systemui.statusbar.notification.stack.MediaContainerView
import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.LargeScreenUtils import com.android.systemui.util.LargeScreenUtils
import com.android.systemui.util.settings.SecureSettings
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Named import javax.inject.Named
@@ -43,9 +49,10 @@ class KeyguardMediaController @Inject constructor(
@param:Named(KEYGUARD) private val mediaHost: MediaHost, @param:Named(KEYGUARD) private val mediaHost: MediaHost,
private val bypassController: KeyguardBypassController, private val bypassController: KeyguardBypassController,
private val statusBarStateController: SysuiStatusBarStateController, private val statusBarStateController: SysuiStatusBarStateController,
private val notifLockscreenUserManager: NotificationLockscreenUserManager,
private val context: Context, private val context: Context,
configurationController: ConfigurationController private val secureSettings: SecureSettings,
@Main private val handler: Handler,
configurationController: ConfigurationController,
) { ) {
init { init {
@@ -60,6 +67,24 @@ class KeyguardMediaController @Inject 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()
}
}
}
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 // First let's set the desired state that we want for this host
mediaHost.expansion = MediaHostState.EXPANDED mediaHost.expansion = MediaHostState.EXPANDED
mediaHost.showsOnlyActiveMedia = true mediaHost.showsOnlyActiveMedia = true
@@ -100,6 +125,13 @@ class KeyguardMediaController @Inject constructor(
private set private set
private var splitShadeContainer: ViewGroup? = null private var splitShadeContainer: ViewGroup? = null
/**
* Track the media player setting status on lock screen.
*/
private var allowMediaPlayerOnLockScreen: Boolean = true
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 * Attaches media container in single pane mode, situated at the top of the notifications list
*/ */
@@ -164,7 +196,7 @@ class KeyguardMediaController @Inject constructor(
visible = mediaHost.visible && visible = mediaHost.visible &&
!bypassController.bypassEnabled && !bypassController.bypassEnabled &&
keyguardOrUserSwitcher && keyguardOrUserSwitcher &&
notifLockscreenUserManager.shouldShowLockscreenNotifications() allowMediaPlayerOnLockScreen
if (visible) { if (visible) {
showMediaPlayer() showMediaPlayer()
} else { } else {

View File

@@ -22,7 +22,12 @@ import android.animation.ValueAnimator
import android.annotation.IntDef import android.annotation.IntDef
import android.content.Context import android.content.Context
import android.content.res.Configuration import android.content.res.Configuration
import android.database.ContentObserver
import android.graphics.Rect import android.graphics.Rect
import android.net.Uri
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
import android.util.Log import android.util.Log
import android.util.MathUtils import android.util.MathUtils
import android.view.View import android.view.View
@@ -33,12 +38,12 @@ import com.android.keyguard.KeyguardViewController
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.animation.Interpolators import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dreams.DreamOverlayStateController import com.android.systemui.dreams.DreamOverlayStateController
import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.NotifPanelEvents import com.android.systemui.shade.NotifPanelEvents
import com.android.systemui.statusbar.CrossFadeHelper import com.android.systemui.statusbar.CrossFadeHelper
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.StackStateAnimator import com.android.systemui.statusbar.notification.stack.StackStateAnimator
@@ -47,6 +52,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.LargeScreenUtils import com.android.systemui.util.LargeScreenUtils
import com.android.systemui.util.animation.UniqueObjectHostView import com.android.systemui.util.animation.UniqueObjectHostView
import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.traceSection import com.android.systemui.util.traceSection
import javax.inject.Inject import javax.inject.Inject
@@ -85,14 +91,22 @@ class MediaHierarchyManager @Inject constructor(
private val keyguardStateController: KeyguardStateController, private val keyguardStateController: KeyguardStateController,
private val bypassController: KeyguardBypassController, private val bypassController: KeyguardBypassController,
private val mediaCarouselController: MediaCarouselController, private val mediaCarouselController: MediaCarouselController,
private val notifLockscreenUserManager: NotificationLockscreenUserManager,
private val keyguardViewController: KeyguardViewController, private val keyguardViewController: KeyguardViewController,
private val dreamOverlayStateController: DreamOverlayStateController, private val dreamOverlayStateController: DreamOverlayStateController,
configurationController: ConfigurationController, configurationController: ConfigurationController,
wakefulnessLifecycle: WakefulnessLifecycle, wakefulnessLifecycle: WakefulnessLifecycle,
panelEventsEvents: NotifPanelEvents, panelEventsEvents: NotifPanelEvents,
private val secureSettings: SecureSettings,
@Main private val handler: Handler,
) { ) {
/**
* Track the media player setting status on lock screen.
*/
private var allowMediaPlayerOnLockScreen: Boolean = true
private val lockScreenMediaPlayerUri =
secureSettings.getUriFor(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN)
/** /**
* Whether we "skip" QQS during panel expansion. * Whether we "skip" QQS during panel expansion.
* *
@@ -521,6 +535,23 @@ class MediaHierarchyManager @Inject constructor(
updateDesiredLocation() updateDesiredLocation()
} }
}) })
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
)
}
}
}
secureSettings.registerContentObserverForUser(
Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN,
settingsObserver,
UserHandle.USER_ALL)
} }
private fun updateConfiguration() { private fun updateConfiguration() {
@@ -1036,7 +1067,6 @@ class MediaHierarchyManager @Inject constructor(
} }
val onLockscreen = (!bypassController.bypassEnabled && val onLockscreen = (!bypassController.bypassEnabled &&
(statusbarState == StatusBarState.KEYGUARD)) (statusbarState == StatusBarState.KEYGUARD))
val allowedOnLockscreen = notifLockscreenUserManager.shouldShowLockscreenNotifications()
val location = when { val location = when {
dreamOverlayActive -> LOCATION_DREAM_OVERLAY dreamOverlayActive -> LOCATION_DREAM_OVERLAY
(qsExpansion > 0.0f || inSplitShade) && !onLockscreen -> LOCATION_QS (qsExpansion > 0.0f || inSplitShade) && !onLockscreen -> LOCATION_QS
@@ -1044,7 +1074,7 @@ class MediaHierarchyManager @Inject constructor(
!hasActiveMedia -> LOCATION_QS !hasActiveMedia -> LOCATION_QS
onLockscreen && isSplitShadeExpanding() -> LOCATION_QS onLockscreen && isSplitShadeExpanding() -> LOCATION_QS
onLockscreen && isTransformingToFullShadeAndInQQS() -> LOCATION_QQS onLockscreen && isTransformingToFullShadeAndInQQS() -> LOCATION_QQS
onLockscreen && allowedOnLockscreen -> LOCATION_LOCKSCREEN onLockscreen && allowMediaPlayerOnLockScreen -> LOCATION_LOCKSCREEN
else -> LOCATION_QQS else -> LOCATION_QQS
} }
// When we're on lock screen and the player is not active, we should keep it in QS. // When we're on lock screen and the player is not active, we should keep it in QS.
@@ -1116,7 +1146,7 @@ class MediaHierarchyManager @Inject constructor(
return !statusBarStateController.isDozing && return !statusBarStateController.isDozing &&
!keyguardViewController.isBouncerShowing && !keyguardViewController.isBouncerShowing &&
statusBarStateController.state == StatusBarState.KEYGUARD && statusBarStateController.state == StatusBarState.KEYGUARD &&
notifLockscreenUserManager.shouldShowLockscreenNotifications() && allowMediaPlayerOnLockScreen &&
statusBarStateController.isExpanded && statusBarStateController.isExpanded &&
!qsExpanded !qsExpanded
} }

View File

@@ -16,19 +16,22 @@
package com.android.systemui.media package com.android.systemui.media
import android.provider.Settings
import android.test.suitebuilder.annotation.SmallTest import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.View.GONE import android.view.View.GONE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import android.widget.FrameLayout import android.widget.FrameLayout
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.MediaContainerView import com.android.systemui.statusbar.notification.stack.MediaContainerView
import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.animation.UniqueObjectHostView import com.android.systemui.util.animation.UniqueObjectHostView
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.utils.os.FakeHandler
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertTrue import junit.framework.Assert.assertTrue
import org.junit.Before import org.junit.Before
@@ -37,11 +40,12 @@ import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
@SmallTest @SmallTest
@RunWith(AndroidTestingRunner::class) @RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
class KeyguardMediaControllerTest : SysuiTestCase() { class KeyguardMediaControllerTest : SysuiTestCase() {
@Mock @Mock
@@ -53,31 +57,33 @@ class KeyguardMediaControllerTest : SysuiTestCase() {
@Mock @Mock
private lateinit var configurationController: ConfigurationController private lateinit var configurationController: ConfigurationController
@Mock
private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager
@JvmField @Rule @JvmField @Rule
val mockito = MockitoJUnit.rule() val mockito = MockitoJUnit.rule()
private val mediaContainerView: MediaContainerView = MediaContainerView(context, null) private val mediaContainerView: MediaContainerView = MediaContainerView(context, null)
private val hostView = UniqueObjectHostView(context) private val hostView = UniqueObjectHostView(context)
private val settings = FakeSettings()
private lateinit var keyguardMediaController: KeyguardMediaController private lateinit var keyguardMediaController: KeyguardMediaController
private lateinit var testableLooper: TestableLooper
private lateinit var fakeHandler: FakeHandler
@Before @Before
fun setup() { fun setup() {
// default state is positive, media should show up // default state is positive, media should show up
whenever(mediaHost.visible).thenReturn(true) whenever(mediaHost.visible).thenReturn(true)
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
whenever(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
.thenReturn(true)
whenever(mediaHost.hostView).thenReturn(hostView) whenever(mediaHost.hostView).thenReturn(hostView)
hostView.layoutParams = FrameLayout.LayoutParams(100, 100) hostView.layoutParams = FrameLayout.LayoutParams(100, 100)
testableLooper = TestableLooper.get(this)
fakeHandler = FakeHandler(testableLooper.looper)
keyguardMediaController = KeyguardMediaController( keyguardMediaController = KeyguardMediaController(
mediaHost, mediaHost,
bypassController, bypassController,
statusBarStateController, statusBarStateController,
notificationLockscreenUserManager,
context, context,
configurationController settings,
fakeHandler,
configurationController,
) )
keyguardMediaController.attachSinglePaneContainer(mediaContainerView) keyguardMediaController.attachSinglePaneContainer(mediaContainerView)
keyguardMediaController.useSplitShade = false keyguardMediaController.useSplitShade = false
@@ -106,15 +112,23 @@ class KeyguardMediaControllerTest : SysuiTestCase() {
} }
@Test @Test
fun testHiddenOnKeyguard_whenNotificationsAreHidden() { fun testHiddenOnKeyguard_whenMediaOnLockScreenDisabled() {
whenever(notificationLockscreenUserManager.shouldShowLockscreenNotifications()) settings.putInt(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, 0)
.thenReturn(false)
keyguardMediaController.refreshMediaPosition() keyguardMediaController.refreshMediaPosition()
assertThat(mediaContainerView.visibility).isEqualTo(GONE) assertThat(mediaContainerView.visibility).isEqualTo(GONE)
} }
@Test
fun testAvailableOnKeyguard_whenMediaOnLockScreenEnabled() {
settings.putInt(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, 1)
keyguardMediaController.refreshMediaPosition()
assertThat(mediaContainerView.visibility).isEqualTo(VISIBLE)
}
@Test @Test
fun testActivatesSplitShadeContainerInSplitShadeMode() { fun testActivatesSplitShadeContainerInSplitShadeMode() {
val splitShadeContainer = FrameLayout(context) val splitShadeContainer = FrameLayout(context)

View File

@@ -17,6 +17,7 @@
package com.android.systemui.media package com.android.systemui.media
import android.graphics.Rect import android.graphics.Rect
import android.provider.Settings
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import android.testing.TestableLooper import android.testing.TestableLooper
import android.view.ViewGroup import android.view.ViewGroup
@@ -30,7 +31,6 @@ import com.android.systemui.dreams.DreamOverlayStateController
import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.testing.FakeNotifPanelEvents import com.android.systemui.shade.testing.FakeNotifPanelEvents
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.KeyguardBypassController
@@ -38,6 +38,8 @@ import com.android.systemui.statusbar.policy.FakeConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.animation.UniqueObjectHostView import com.android.systemui.util.animation.UniqueObjectHostView
import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.any
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.utils.os.FakeHandler
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import org.junit.Assert.assertNotNull import org.junit.Assert.assertNotNull
import org.junit.Before import org.junit.Before
@@ -53,7 +55,6 @@ import org.mockito.Mock
import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.times import org.mockito.Mockito.times
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.Mockito.`when` as whenever import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoJUnit
@@ -68,7 +69,6 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
@Mock private lateinit var bypassController: KeyguardBypassController @Mock private lateinit var bypassController: KeyguardBypassController
@Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
@Mock private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager
@Mock private lateinit var mediaCarouselController: MediaCarouselController @Mock private lateinit var mediaCarouselController: MediaCarouselController
@Mock private lateinit var mediaCarouselScrollHandler: MediaCarouselScrollHandler @Mock private lateinit var mediaCarouselScrollHandler: MediaCarouselScrollHandler
@Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@@ -82,37 +82,42 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
@JvmField @JvmField
@Rule @Rule
val mockito = MockitoJUnit.rule() val mockito = MockitoJUnit.rule()
private lateinit var mediaHiearchyManager: MediaHierarchyManager private lateinit var mediaHierarchyManager: MediaHierarchyManager
private lateinit var mediaFrame: ViewGroup private lateinit var mediaFrame: ViewGroup
private val configurationController = FakeConfigurationController() private val configurationController = FakeConfigurationController()
private val notifPanelEvents = FakeNotifPanelEvents() private val notifPanelEvents = FakeNotifPanelEvents()
private val settings = FakeSettings()
private lateinit var testableLooper: TestableLooper
private lateinit var fakeHandler: FakeHandler
@Before @Before
fun setup() { fun setup() {
context.getOrCreateTestableResources().addOverride( context.getOrCreateTestableResources().addOverride(
R.bool.config_use_split_notification_shade, false) R.bool.config_use_split_notification_shade, false)
mediaFrame = FrameLayout(context) mediaFrame = FrameLayout(context)
`when`(mediaCarouselController.mediaFrame).thenReturn(mediaFrame) testableLooper = TestableLooper.get(this)
mediaHiearchyManager = MediaHierarchyManager( fakeHandler = FakeHandler(testableLooper.looper)
whenever(mediaCarouselController.mediaFrame).thenReturn(mediaFrame)
mediaHierarchyManager = MediaHierarchyManager(
context, context,
statusBarStateController, statusBarStateController,
keyguardStateController, keyguardStateController,
bypassController, bypassController,
mediaCarouselController, mediaCarouselController,
notificationLockscreenUserManager,
keyguardViewController, keyguardViewController,
dreamOverlayStateController, dreamOverlayStateController,
configurationController, configurationController,
wakefulnessLifecycle, wakefulnessLifecycle,
notifPanelEvents, notifPanelEvents,
) settings,
fakeHandler,)
verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture()) verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture())
verify(statusBarStateController).addCallback(statusBarCallback.capture()) verify(statusBarStateController).addCallback(statusBarCallback.capture())
setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN, LOCKSCREEN_TOP) setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN, LOCKSCREEN_TOP)
setupHost(qsHost, MediaHierarchyManager.LOCATION_QS, QS_TOP) setupHost(qsHost, MediaHierarchyManager.LOCATION_QS, QS_TOP)
setupHost(qqsHost, MediaHierarchyManager.LOCATION_QQS, QQS_TOP) setupHost(qqsHost, MediaHierarchyManager.LOCATION_QQS, QQS_TOP)
`when`(statusBarStateController.state).thenReturn(StatusBarState.SHADE) whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
`when`(mediaCarouselController.mediaCarouselScrollHandler) whenever(mediaCarouselController.mediaCarouselScrollHandler)
.thenReturn(mediaCarouselScrollHandler) .thenReturn(mediaCarouselScrollHandler)
val observer = wakefullnessObserver.value val observer = wakefullnessObserver.value
assertNotNull("lifecycle observer wasn't registered", observer) assertNotNull("lifecycle observer wasn't registered", observer)
@@ -122,30 +127,30 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
} }
private fun setupHost(host: MediaHost, location: Int, top: Int) { private fun setupHost(host: MediaHost, location: Int, top: Int) {
`when`(host.location).thenReturn(location) whenever(host.location).thenReturn(location)
`when`(host.currentBounds).thenReturn(Rect(0, top, 0, top)) whenever(host.currentBounds).thenReturn(Rect(0, top, 0, top))
`when`(host.hostView).thenReturn(uniqueObjectHostView) whenever(host.hostView).thenReturn(uniqueObjectHostView)
`when`(host.visible).thenReturn(true) whenever(host.visible).thenReturn(true)
mediaHiearchyManager.register(host) mediaHierarchyManager.register(host)
} }
@Test @Test
fun testHostViewSetOnRegister() { fun testHostViewSetOnRegister() {
val host = mediaHiearchyManager.register(lockHost) val host = mediaHierarchyManager.register(lockHost)
verify(lockHost).hostView = eq(host) verify(lockHost).hostView = eq(host)
} }
@Test @Test
fun testBlockedWhenScreenTurningOff() { fun testBlockedWhenScreenTurningOff() {
// Let's set it onto QS: // Let's set it onto QS:
mediaHiearchyManager.qsExpansion = 1.0f mediaHierarchyManager.qsExpansion = 1.0f
verify(mediaCarouselController).onDesiredLocationChanged(ArgumentMatchers.anyInt(), verify(mediaCarouselController).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong()) any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
val observer = wakefullnessObserver.value val observer = wakefullnessObserver.value
assertNotNull("lifecycle observer wasn't registered", observer) assertNotNull("lifecycle observer wasn't registered", observer)
observer.onStartedGoingToSleep() observer.onStartedGoingToSleep()
clearInvocations(mediaCarouselController) clearInvocations(mediaCarouselController)
mediaHiearchyManager.qsExpansion = 0.0f mediaHierarchyManager.qsExpansion = 0.0f
verify(mediaCarouselController, times(0)) verify(mediaCarouselController, times(0))
.onDesiredLocationChanged(ArgumentMatchers.anyInt(), .onDesiredLocationChanged(ArgumentMatchers.anyInt(),
any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong()) any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
@@ -154,13 +159,13 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
@Test @Test
fun testAllowedWhenNotTurningOff() { fun testAllowedWhenNotTurningOff() {
// Let's set it onto QS: // Let's set it onto QS:
mediaHiearchyManager.qsExpansion = 1.0f mediaHierarchyManager.qsExpansion = 1.0f
verify(mediaCarouselController).onDesiredLocationChanged(ArgumentMatchers.anyInt(), verify(mediaCarouselController).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong()) any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
val observer = wakefullnessObserver.value val observer = wakefullnessObserver.value
assertNotNull("lifecycle observer wasn't registered", observer) assertNotNull("lifecycle observer wasn't registered", observer)
clearInvocations(mediaCarouselController) clearInvocations(mediaCarouselController)
mediaHiearchyManager.qsExpansion = 0.0f mediaHierarchyManager.qsExpansion = 0.0f
verify(mediaCarouselController).onDesiredLocationChanged(ArgumentMatchers.anyInt(), verify(mediaCarouselController).onDesiredLocationChanged(ArgumentMatchers.anyInt(),
any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong()) any(MediaHostState::class.java), anyBoolean(), anyLong(), anyLong())
} }
@@ -170,7 +175,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
goToLockscreen() goToLockscreen()
// Let's transition all the way to full shade // Let's transition all the way to full shade
mediaHiearchyManager.setTransitionToFullShadeAmount(100000f) mediaHierarchyManager.setTransitionToFullShadeAmount(100000f)
verify(mediaCarouselController).onDesiredLocationChanged( verify(mediaCarouselController).onDesiredLocationChanged(
eq(MediaHierarchyManager.LOCATION_QQS), eq(MediaHierarchyManager.LOCATION_QQS),
any(MediaHostState::class.java), any(MediaHostState::class.java),
@@ -180,7 +185,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
clearInvocations(mediaCarouselController) clearInvocations(mediaCarouselController)
// Let's go back to the lock screen // Let's go back to the lock screen
mediaHiearchyManager.setTransitionToFullShadeAmount(0.0f) mediaHierarchyManager.setTransitionToFullShadeAmount(0.0f)
verify(mediaCarouselController).onDesiredLocationChanged( verify(mediaCarouselController).onDesiredLocationChanged(
eq(MediaHierarchyManager.LOCATION_LOCKSCREEN), eq(MediaHierarchyManager.LOCATION_LOCKSCREEN),
any(MediaHostState::class.java), any(MediaHostState::class.java),
@@ -189,7 +194,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
anyLong()) anyLong())
// Let's make sure alpha is set // Let's make sure alpha is set
mediaHiearchyManager.setTransitionToFullShadeAmount(2.0f) mediaHierarchyManager.setTransitionToFullShadeAmount(2.0f)
assertThat(mediaFrame.alpha).isNotEqualTo(1.0f) assertThat(mediaFrame.alpha).isNotEqualTo(1.0f)
} }
@@ -198,7 +203,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
goToLockscreen() goToLockscreen()
expandQS() expandQS()
val transformType = mediaHiearchyManager.calculateTransformationType() val transformType = mediaHierarchyManager.calculateTransformationType()
assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE) assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE)
} }
@@ -206,7 +211,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
fun calculateTransformationType_notOnLockscreen_returnsTransition() { fun calculateTransformationType_notOnLockscreen_returnsTransition() {
expandQS() expandQS()
val transformType = mediaHiearchyManager.calculateTransformationType() val transformType = mediaHierarchyManager.calculateTransformationType()
assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_TRANSITION) assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_TRANSITION)
} }
@@ -216,7 +221,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
goToLockscreen() goToLockscreen()
expandQS() expandQS()
val transformType = mediaHiearchyManager.calculateTransformationType() val transformType = mediaHierarchyManager.calculateTransformationType()
assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE) assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE)
} }
@@ -226,9 +231,9 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
enableSplitShade() enableSplitShade()
goToLockscreen() goToLockscreen()
expandQS() expandQS()
mediaHiearchyManager.setTransitionToFullShadeAmount(10000f) mediaHierarchyManager.setTransitionToFullShadeAmount(10000f)
val transformType = mediaHiearchyManager.calculateTransformationType() val transformType = mediaHierarchyManager.calculateTransformationType()
assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_TRANSITION) assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_TRANSITION)
} }
@@ -238,9 +243,9 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
goToLockscreen() goToLockscreen()
expandQS() expandQS()
whenever(lockHost.visible).thenReturn(false) whenever(lockHost.visible).thenReturn(false)
mediaHiearchyManager.setTransitionToFullShadeAmount(10000f) mediaHierarchyManager.setTransitionToFullShadeAmount(10000f)
val transformType = mediaHiearchyManager.calculateTransformationType() val transformType = mediaHierarchyManager.calculateTransformationType()
assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE) assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE)
} }
@@ -250,9 +255,9 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
goToLockscreen() goToLockscreen()
goToLockedShade() goToLockedShade()
expandQS() expandQS()
mediaHiearchyManager.setTransitionToFullShadeAmount(0f) mediaHierarchyManager.setTransitionToFullShadeAmount(0f)
val transformType = mediaHiearchyManager.calculateTransformationType() val transformType = mediaHierarchyManager.calculateTransformationType()
assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE) assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE)
} }
@@ -261,13 +266,13 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
goToLockscreen() goToLockscreen()
goToLockedShade() goToLockedShade()
val transformType = mediaHiearchyManager.calculateTransformationType() val transformType = mediaHierarchyManager.calculateTransformationType()
assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE) assertThat(transformType).isEqualTo(MediaHierarchyManager.TRANSFORMATION_TYPE_FADE)
} }
@Test @Test
fun testCloseGutsRelayToCarousel() { fun testCloseGutsRelayToCarousel() {
mediaHiearchyManager.closeGuts() mediaHierarchyManager.closeGuts()
verify(mediaCarouselController).closeGuts() verify(mediaCarouselController).closeGuts()
} }
@@ -281,7 +286,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
@Test @Test
fun getGuidedTransformationTranslationY_notInGuidedTransformation_returnsNegativeNumber() { fun getGuidedTransformationTranslationY_notInGuidedTransformation_returnsNegativeNumber() {
assertThat(mediaHiearchyManager.getGuidedTransformationTranslationY()).isLessThan(0) assertThat(mediaHierarchyManager.getGuidedTransformationTranslationY()).isLessThan(0)
} }
@Test @Test
@@ -289,7 +294,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
enterGuidedTransformation() enterGuidedTransformation()
val expectedTranslation = LOCKSCREEN_TOP - QS_TOP val expectedTranslation = LOCKSCREEN_TOP - QS_TOP
assertThat(mediaHiearchyManager.getGuidedTransformationTranslationY()) assertThat(mediaHierarchyManager.getGuidedTransformationTranslationY())
.isEqualTo(expectedTranslation) .isEqualTo(expectedTranslation)
} }
@@ -301,7 +306,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
whenever(qsHost.visible).thenReturn(true) whenever(qsHost.visible).thenReturn(true)
whenever(qqsHost.visible).thenReturn(true) whenever(qqsHost.visible).thenReturn(true)
assertThat(mediaHiearchyManager.isCurrentlyInGuidedTransformation()).isTrue() assertThat(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).isTrue()
} }
@Test @Test
@@ -313,7 +318,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
whenever(qsHost.visible).thenReturn(true) whenever(qsHost.visible).thenReturn(true)
whenever(qqsHost.visible).thenReturn(true) whenever(qqsHost.visible).thenReturn(true)
assertThat(mediaHiearchyManager.isCurrentlyInGuidedTransformation()).isFalse() assertThat(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).isFalse()
} }
@Test @Test
@@ -324,7 +329,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
whenever(qsHost.visible).thenReturn(true) whenever(qsHost.visible).thenReturn(true)
whenever(qqsHost.visible).thenReturn(true) whenever(qqsHost.visible).thenReturn(true)
assertThat(mediaHiearchyManager.isCurrentlyInGuidedTransformation()).isFalse() assertThat(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).isFalse()
} }
private fun enableSplitShade() { private fun enableSplitShade() {
@@ -336,9 +341,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
private fun goToLockscreen() { private fun goToLockscreen() {
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
whenever(notificationLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn( settings.putInt(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, 1)
true
)
statusBarCallback.value.onStatePreChange(StatusBarState.SHADE, StatusBarState.KEYGUARD) statusBarCallback.value.onStatePreChange(StatusBarState.SHADE, StatusBarState.KEYGUARD)
clearInvocations(mediaCarouselController) clearInvocations(mediaCarouselController)
} }
@@ -352,13 +355,13 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
} }
private fun expandQS() { private fun expandQS() {
mediaHiearchyManager.qsExpansion = 1.0f mediaHierarchyManager.qsExpansion = 1.0f
} }
private fun enterGuidedTransformation() { private fun enterGuidedTransformation() {
mediaHiearchyManager.qsExpansion = 1.0f mediaHierarchyManager.qsExpansion = 1.0f
goToLockscreen() goToLockscreen()
mediaHiearchyManager.setTransitionToFullShadeAmount(123f) mediaHierarchyManager.setTransitionToFullShadeAmount(123f)
} }
companion object { companion object {