Merge "Hide player on keyguard when notif are hidden" into rvc-dev

This commit is contained in:
Lucas Dupin
2020-05-20 16:52:28 +00:00
committed by Android (Google) Code Review
3 changed files with 135 additions and 29 deletions

View File

@@ -18,6 +18,7 @@ package com.android.systemui.media
import android.view.View
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.MediaHeaderView
@@ -33,7 +34,8 @@ import javax.inject.Singleton
class KeyguardMediaController @Inject constructor(
private val mediaHost: MediaHost,
private val bypassController: KeyguardBypassController,
private val statusBarStateController: SysuiStatusBarStateController
private val statusBarStateController: SysuiStatusBarStateController,
private val notifLockscreenUserManager: NotificationLockscreenUserManager
) {
init {
@@ -61,10 +63,12 @@ class KeyguardMediaController @Inject constructor(
}
private fun updateVisibility() {
val shouldBeVisible = mediaHost.visible
&& !bypassController.bypassEnabled
&& (statusBarStateController.state == StatusBarState.KEYGUARD ||
statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER)
val keyguardOrUserSwitcher = (statusBarStateController.state == StatusBarState.KEYGUARD ||
statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER)
val shouldBeVisible = mediaHost.visible &&
!bypassController.bypassEnabled &&
keyguardOrUserSwitcher &&
notifLockscreenUserManager.shouldShowLockscreenNotifications()
view?.visibility = if (shouldBeVisible) View.VISIBLE else View.GONE
}
}

View File

@@ -26,6 +26,7 @@ import android.view.ViewGroup
import android.view.ViewGroupOverlay
import com.android.systemui.Interpolators
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
@@ -46,7 +47,8 @@ class MediaHierarchyManager @Inject constructor(
private val keyguardStateController: KeyguardStateController,
private val bypassController: KeyguardBypassController,
private val mediaViewManager: MediaViewManager,
private val mediaMeasurementProvider: MediaMeasurementManager
private val mediaMeasurementProvider: MediaMeasurementManager,
private val notifLockscreenUserManager: NotificationLockscreenUserManager
) {
/**
* The root overlay of the hierarchy. This is where the media notification is attached to
@@ -56,7 +58,7 @@ class MediaHierarchyManager @Inject constructor(
private var rootOverlay: ViewGroupOverlay? = null
private lateinit var currentState: MediaState
private val mediaCarousel
get() = mediaViewManager.mediaCarousel
get() = mediaViewManager.mediaCarousel
private var animationStartState: MediaState? = null
private var statusbarState: Int = statusBarStateController.state
private var animator = ValueAnimator.ofFloat(0.0f, 1.0f).apply {
@@ -136,9 +138,9 @@ class MediaHierarchyManager @Inject constructor(
*
* @return the hostView associated with this location
*/
fun register(mediaObject: MediaHost) : ViewGroup {
fun register(mediaObject: MediaHost): ViewGroup {
val viewHost = createUniqueObjectHost(mediaObject)
mediaObject.hostView = viewHost;
mediaObject.hostView = viewHost
mediaHosts[mediaObject.location] = mediaObject
if (mediaObject.location == desiredLocation) {
// In case we are overriding a view that is already visible, make sure we attach it
@@ -155,7 +157,7 @@ class MediaHierarchyManager @Inject constructor(
private fun createUniqueObjectHost(host: MediaHost): UniqueObjectHostView {
val viewHost = UniqueObjectHostView(context)
viewHost.measurementCache = mediaMeasurementProvider.obtainCache(host)
viewHost.onMeasureListener = { input ->
viewHost.onMeasureListener = { input ->
if (host.location == desiredLocation) {
// Measurement of the currently active player is happening, Let's make
// sure the player width is up to date
@@ -215,8 +217,8 @@ class MediaHierarchyManager @Inject constructor(
applyTargetStateIfNotAnimating()
} else if (animate) {
animator.cancel()
if (currentAttachmentLocation == IN_OVERLAY
|| !previousHost.hostView.isAttachedToWindow) {
if (currentAttachmentLocation == IN_OVERLAY ||
!previousHost.hostView.isAttachedToWindow) {
// Let's animate to the new position, starting from the current position
// We also go in here in case the view was detached, since the bounds wouldn't
// be correct anymore
@@ -237,10 +239,10 @@ class MediaHierarchyManager @Inject constructor(
@MediaLocation currentLocation: Int,
@MediaLocation previousLocation: Int
): Boolean {
if (currentLocation == LOCATION_QQS
&& previousLocation == LOCATION_LOCKSCREEN
&& (statusBarStateController.leaveOpenOnKeyguardHide()
|| statusbarState == StatusBarState.SHADE_LOCKED)) {
if (currentLocation == LOCATION_QQS &&
previousLocation == LOCATION_LOCKSCREEN &&
(statusBarStateController.leaveOpenOnKeyguardHide() ||
statusbarState == StatusBarState.SHADE_LOCKED)) {
// Usually listening to the isShown is enough to determine this, but there is some
// non-trivial reattaching logic happening that will make the view not-shown earlier
return true
@@ -251,10 +253,9 @@ class MediaHierarchyManager @Inject constructor(
private fun adjustAnimatorForTransition(desiredLocation: Int, previousLocation: Int) {
val (animDuration, delay) = getAnimationParams(previousLocation, desiredLocation)
animator.apply {
duration = animDuration
duration = animDuration
startDelay = delay
}
}
private fun getAnimationParams(previousLocation: Int, desiredLocation: Int): Pair<Long, Long> {
@@ -262,8 +263,8 @@ class MediaHierarchyManager @Inject constructor(
var delay = 0L
if (previousLocation == LOCATION_LOCKSCREEN && desiredLocation == LOCATION_QQS) {
// Going to the full shade, let's adjust the animation duration
if (statusbarState == StatusBarState.SHADE
&& keyguardStateController.isKeyguardFadingAway) {
if (statusbarState == StatusBarState.SHADE &&
keyguardStateController.isKeyguardFadingAway) {
delay = keyguardStateController.keyguardFadingAwayDelay
}
animDuration = StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE.toLong()
@@ -301,12 +302,12 @@ class MediaHierarchyManager @Inject constructor(
/**
* @return true if this transformation is guided by an external progress like a finger
*/
private fun isCurrentlyInGuidedTransformation() : Boolean {
private fun isCurrentlyInGuidedTransformation(): Boolean {
return getTransformationProgress() >= 0
}
/**
* @return the current transformation progress if we're in a guided transformation and -1
* @return the current transformation progress if we're in a guided transformation and -1
* otherwise
*/
private fun getTransformationProgress(): Float {
@@ -377,19 +378,20 @@ class MediaHierarchyManager @Inject constructor(
}
private fun isTransitionRunning(): Boolean {
return isCurrentlyInGuidedTransformation() && getTransformationProgress() != 1.0f
|| animator.isRunning
return isCurrentlyInGuidedTransformation() && getTransformationProgress() != 1.0f ||
animator.isRunning
}
@MediaLocation
private fun calculateLocation() : Int {
val onLockscreen = (!bypassController.bypassEnabled
&& (statusbarState == StatusBarState.KEYGUARD
|| statusbarState == StatusBarState.FULLSCREEN_USER_SWITCHER))
private fun calculateLocation(): Int {
val onLockscreen = (!bypassController.bypassEnabled &&
(statusbarState == StatusBarState.KEYGUARD ||
statusbarState == StatusBarState.FULLSCREEN_USER_SWITCHER))
val allowedOnLockscreen = notifLockscreenUserManager.shouldShowLockscreenNotifications()
return when {
qsExpansion > 0.0f && !onLockscreen -> LOCATION_QS
qsExpansion > 0.4f && onLockscreen -> LOCATION_QS
onLockscreen -> LOCATION_LOCKSCREEN
onLockscreen && allowedOnLockscreen -> LOCATION_LOCKSCREEN
else -> LOCATION_QQS
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2020 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
import android.testing.AndroidTestingRunner
import android.view.View.GONE
import android.view.View.VISIBLE
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.MediaHeaderView
import com.android.systemui.statusbar.phone.KeyguardBypassController
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
@SmallTest
@RunWith(AndroidTestingRunner::class)
class KeyguardMediaControllerTest : SysuiTestCase() {
@Mock
private lateinit var mediaHost: MediaHost
@Mock
private lateinit var bypassController: KeyguardBypassController
@Mock
private lateinit var statusBarStateController: SysuiStatusBarStateController
@Mock
private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager
@Mock
private lateinit var mediaHeaderView: MediaHeaderView
@Captor
private lateinit var visibilityListener: ArgumentCaptor<((Boolean) -> Unit)>
@JvmField @Rule
val mockito = MockitoJUnit.rule()
private lateinit var keyguardMediaController: KeyguardMediaController
@Before
fun setup() {
keyguardMediaController = KeyguardMediaController(mediaHost, bypassController,
statusBarStateController, notificationLockscreenUserManager)
}
@Test
fun testAttach_hiddenWhenHostIsHidden() {
`when`(mediaHost.visible).thenReturn(false)
triggerVisibilityListener()
verify(mediaHeaderView).visibility = eq(GONE)
}
@Test
fun testAttach_visibleOnKeyguard() {
`when`(mediaHost.visible).thenReturn(true)
`when`(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
`when`(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
.thenReturn(true)
triggerVisibilityListener()
verify(mediaHeaderView).visibility = eq(VISIBLE)
}
@Test
fun testAttach_hiddenOnKeyguard_whenNotificationsAreHidden() {
`when`(mediaHost.visible).thenReturn(true)
`when`(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
`when`(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
.thenReturn(false)
triggerVisibilityListener()
verify(mediaHeaderView).visibility = eq(GONE)
}
private fun triggerVisibilityListener() {
keyguardMediaController.attach(mediaHeaderView)
verify(mediaHost).visibleChangedListener = visibilityListener.capture()
visibilityListener.value.invoke(true)
}
}