From 9abc75079ce370cb3e36bb40e50107812ca29d65 Mon Sep 17 00:00:00 2001 From: Matt Pietal Date: Tue, 20 Dec 2022 16:18:36 +0000 Subject: [PATCH] Unfold transition - Apply based on state Two different files were applying transitions to the same views. Add a filter to each to make sure they only run when in the corresponding state. Fixes: 263016502 Test: atest KeyguardUnfoldTransitionTest NotificationPanelUnfoldAnimationControllerTest Change-Id: I38af0921ed9794f58566f796800d6212aeffc686 --- .../keyguard/KeyguardUnfoldTransition.kt | 22 +-- ...ificationPanelUnfoldAnimationController.kt | 22 ++- .../keyguard/KeyguardUnfoldTransitionTest.kt | 60 +++++++- ...ationPanelUnfoldAnimationControllerTest.kt | 141 ++++++++++++++++++ 4 files changed, 223 insertions(+), 22 deletions(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt index f974e27a99ec9..edd150c293f6e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt @@ -19,6 +19,8 @@ package com.android.keyguard import android.content.Context import android.view.ViewGroup import com.android.systemui.R +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.statusbar.StatusBarState.KEYGUARD import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction.END import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction.START @@ -36,27 +38,29 @@ class KeyguardUnfoldTransition @Inject constructor( private val context: Context, - unfoldProgressProvider: NaturalRotationUnfoldProgressProvider + statusBarStateController: StatusBarStateController, + unfoldProgressProvider: NaturalRotationUnfoldProgressProvider, ) { /** Certain views only need to move if they are not currently centered */ var statusViewCentered = false - private val filterSplitShadeOnly = { !statusViewCentered } - private val filterNever = { true } + private val filterKeyguardAndSplitShadeOnly: () -> Boolean = { + statusBarStateController.getState() == KEYGUARD && !statusViewCentered } + private val filterKeyguard: () -> Boolean = { statusBarStateController.getState() == KEYGUARD } private val translateAnimator by lazy { UnfoldConstantTranslateAnimator( viewsIdToTranslate = setOf( - ViewIdToTranslate(R.id.keyguard_status_area, START, filterNever), + ViewIdToTranslate(R.id.keyguard_status_area, START, filterKeyguard), ViewIdToTranslate( - R.id.lockscreen_clock_view_large, START, filterSplitShadeOnly), - ViewIdToTranslate(R.id.lockscreen_clock_view, START, filterNever), + R.id.lockscreen_clock_view_large, START, filterKeyguardAndSplitShadeOnly), + ViewIdToTranslate(R.id.lockscreen_clock_view, START, filterKeyguard), ViewIdToTranslate( - R.id.notification_stack_scroller, END, filterSplitShadeOnly), - ViewIdToTranslate(R.id.start_button, START, filterNever), - ViewIdToTranslate(R.id.end_button, END, filterNever)), + R.id.notification_stack_scroller, END, filterKeyguardAndSplitShadeOnly), + ViewIdToTranslate(R.id.start_button, START, filterKeyguard), + ViewIdToTranslate(R.id.end_button, END, filterKeyguard)), progressProvider = unfoldProgressProvider) } diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt index ba779c6233fb0..639172f9e37ab 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt @@ -19,6 +19,9 @@ package com.android.systemui.shade import android.content.Context import android.view.ViewGroup import com.android.systemui.R +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.statusbar.StatusBarState.SHADE +import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction.END import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction.START @@ -30,17 +33,24 @@ import javax.inject.Inject @SysUIUnfoldScope class NotificationPanelUnfoldAnimationController @Inject -constructor(private val context: Context, progressProvider: NaturalRotationUnfoldProgressProvider) { +constructor( + private val context: Context, + statusBarStateController: StatusBarStateController, + progressProvider: NaturalRotationUnfoldProgressProvider, +) { + + private val filterShade: () -> Boolean = { statusBarStateController.getState() == SHADE || + statusBarStateController.getState() == SHADE_LOCKED } private val translateAnimator by lazy { UnfoldConstantTranslateAnimator( viewsIdToTranslate = setOf( - ViewIdToTranslate(R.id.quick_settings_panel, START), - ViewIdToTranslate(R.id.notification_stack_scroller, END), - ViewIdToTranslate(R.id.rightLayout, END), - ViewIdToTranslate(R.id.clock, START), - ViewIdToTranslate(R.id.date, START)), + ViewIdToTranslate(R.id.quick_settings_panel, START, filterShade), + ViewIdToTranslate(R.id.notification_stack_scroller, END, filterShade), + ViewIdToTranslate(R.id.rightLayout, END, filterShade), + ViewIdToTranslate(R.id.clock, START, filterShade), + ViewIdToTranslate(R.id.date, START, filterShade)), progressProvider = progressProvider) } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUnfoldTransitionTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUnfoldTransitionTest.kt index 6c1f008e9337a..bb03f288147ea 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUnfoldTransitionTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUnfoldTransitionTest.kt @@ -22,9 +22,13 @@ import android.view.ViewGroup import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.statusbar.StatusBarState.KEYGUARD +import com.android.systemui.statusbar.StatusBarState.SHADE import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider import com.android.systemui.util.mockito.capture +import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -33,7 +37,6 @@ import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.verify -import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations /** @@ -50,7 +53,9 @@ class KeyguardUnfoldTransitionTest : SysuiTestCase() { @Mock private lateinit var parent: ViewGroup - private lateinit var keyguardUnfoldTransition: KeyguardUnfoldTransition + @Mock private lateinit var statusBarStateController: StatusBarStateController + + private lateinit var underTest: KeyguardUnfoldTransition private lateinit var progressListener: TransitionProgressListener private var xTranslationMax = 0f @@ -61,10 +66,10 @@ class KeyguardUnfoldTransitionTest : SysuiTestCase() { xTranslationMax = context.resources.getDimensionPixelSize(R.dimen.keyguard_unfold_translation_x).toFloat() - keyguardUnfoldTransition = KeyguardUnfoldTransition(context, progressProvider) + underTest = KeyguardUnfoldTransition(context, statusBarStateController, progressProvider) - keyguardUnfoldTransition.setup(parent) - keyguardUnfoldTransition.statusViewCentered = false + underTest.setup(parent) + underTest.statusViewCentered = false verify(progressProvider).addCallback(capture(progressListenerCaptor)) progressListener = progressListenerCaptor.value @@ -72,10 +77,11 @@ class KeyguardUnfoldTransitionTest : SysuiTestCase() { @Test fun onTransition_centeredViewDoesNotMove() { - keyguardUnfoldTransition.statusViewCentered = true + whenever(statusBarStateController.getState()).thenReturn(KEYGUARD) + underTest.statusViewCentered = true val view = View(context) - `when`(parent.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(view) + whenever(parent.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(view) progressListener.onTransitionStarted() assertThat(view.translationX).isZero() @@ -89,4 +95,44 @@ class KeyguardUnfoldTransitionTest : SysuiTestCase() { progressListener.onTransitionFinished() assertThat(view.translationX).isZero() } + + @Test + fun whenInShadeState_viewDoesNotMove() { + whenever(statusBarStateController.getState()).thenReturn(SHADE) + + val view = View(context) + whenever(parent.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(view) + + progressListener.onTransitionStarted() + assertThat(view.translationX).isZero() + + progressListener.onTransitionProgress(0f) + assertThat(view.translationX).isZero() + + progressListener.onTransitionProgress(0.5f) + assertThat(view.translationX).isZero() + + progressListener.onTransitionFinished() + assertThat(view.translationX).isZero() + } + + @Test + fun whenInKeyguardState_viewDoesMove() { + whenever(statusBarStateController.getState()).thenReturn(KEYGUARD) + + val view = View(context) + whenever(parent.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(view) + + progressListener.onTransitionStarted() + assertThat(view.translationX).isZero() + + progressListener.onTransitionProgress(0f) + assertThat(view.translationX).isEqualTo(xTranslationMax) + + progressListener.onTransitionProgress(0.5f) + assertThat(view.translationX).isEqualTo(0.5f * xTranslationMax) + + progressListener.onTransitionFinished() + assertThat(view.translationX).isZero() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt new file mode 100644 index 0000000000000..db6fc136e6510 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2021 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.shade + +import android.testing.AndroidTestingRunner +import android.view.View +import android.view.ViewGroup +import androidx.test.filters.SmallTest +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.statusbar.StatusBarState.KEYGUARD +import com.android.systemui.statusbar.StatusBarState.SHADE +import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED +import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener +import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider +import com.android.systemui.util.mockito.capture +import com.android.systemui.util.mockito.whenever +import com.google.common.truth.Truth.assertThat +import org.junit.Before +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.verify +import org.mockito.MockitoAnnotations + +/** + * Translates items away/towards the hinge when the device is opened/closed. This is controlled by + * the set of ids, which also dictact which direction to move and when, via a filter fn. + */ +@SmallTest +@RunWith(AndroidTestingRunner::class) +class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() { + + @Mock private lateinit var progressProvider: NaturalRotationUnfoldProgressProvider + + @Captor private lateinit var progressListenerCaptor: ArgumentCaptor + + @Mock private lateinit var parent: ViewGroup + + @Mock private lateinit var statusBarStateController: StatusBarStateController + + private lateinit var underTest: NotificationPanelUnfoldAnimationController + private lateinit var progressListener: TransitionProgressListener + private var xTranslationMax = 0f + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + + xTranslationMax = + context.resources.getDimensionPixelSize(R.dimen.notification_side_paddings).toFloat() + + underTest = + NotificationPanelUnfoldAnimationController( + context, + statusBarStateController, + progressProvider + ) + underTest.setup(parent) + + verify(progressProvider).addCallback(capture(progressListenerCaptor)) + progressListener = progressListenerCaptor.value + } + + @Test + fun whenInKeyguardState_viewDoesNotMove() { + whenever(statusBarStateController.getState()).thenReturn(KEYGUARD) + + val view = View(context) + whenever(parent.findViewById(R.id.quick_settings_panel)).thenReturn(view) + + progressListener.onTransitionStarted() + assertThat(view.translationX).isZero() + + progressListener.onTransitionProgress(0f) + assertThat(view.translationX).isZero() + + progressListener.onTransitionProgress(0.5f) + assertThat(view.translationX).isZero() + + progressListener.onTransitionFinished() + assertThat(view.translationX).isZero() + } + + @Test + fun whenInShadeState_viewDoesMove() { + whenever(statusBarStateController.getState()).thenReturn(SHADE) + + val view = View(context) + whenever(parent.findViewById(R.id.quick_settings_panel)).thenReturn(view) + + progressListener.onTransitionStarted() + assertThat(view.translationX).isZero() + + progressListener.onTransitionProgress(0f) + assertThat(view.translationX).isEqualTo(xTranslationMax) + + progressListener.onTransitionProgress(0.5f) + assertThat(view.translationX).isEqualTo(0.5f * xTranslationMax) + + progressListener.onTransitionFinished() + assertThat(view.translationX).isZero() + } + + @Test + fun whenInShadeLockedState_viewDoesMove() { + whenever(statusBarStateController.getState()).thenReturn(SHADE_LOCKED) + + val view = View(context) + whenever(parent.findViewById(R.id.quick_settings_panel)).thenReturn(view) + + progressListener.onTransitionStarted() + assertThat(view.translationX).isZero() + + progressListener.onTransitionProgress(0f) + assertThat(view.translationX).isEqualTo(xTranslationMax) + + progressListener.onTransitionProgress(0.5f) + assertThat(view.translationX).isEqualTo(0.5f * xTranslationMax) + + progressListener.onTransitionFinished() + assertThat(view.translationX).isZero() + } +}