Skip to content
Snippets Groups Projects
Commit 5dfd76ff authored by Nick Chameyev's avatar Nick Chameyev Committed by Automerger Merge Worker
Browse files

Merge "Do not animate statusbar unfold when in portrait orientation" into sc-v2-dev am: 8264da57

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

Change-Id: Ifa9dcf89f79beedc82a4813b807ebabf515ad0a2
parents 4183637e 8264da57
No related branches found
No related tags found
No related merge requests found
Showing
with 523 additions and 60 deletions
package com.android.systemui.unfold.util
import android.content.Context
import android.os.RemoteException
import android.util.Log
import android.view.IRotationWatcher
import android.view.IWindowManager
import android.view.Surface
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
/**
* [UnfoldTransitionProgressProvider] that emits transition progress only when the display has
* default rotation or 180 degrees opposite rotation (ROTATION_0 or ROTATION_180).
* It could be helpful to run the animation only when the display's rotation is perpendicular
* to the fold.
*/
class NaturalRotationUnfoldProgressProvider(
private val context: Context,
private val windowManagerInterface: IWindowManager,
unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider
) : UnfoldTransitionProgressProvider {
private val scopedUnfoldTransitionProgressProvider =
ScopedUnfoldTransitionProgressProvider(unfoldTransitionProgressProvider)
private val rotationWatcher = RotationWatcher()
private var isNaturalRotation: Boolean = false
fun init() {
try {
windowManagerInterface.watchRotation(rotationWatcher, context.display.displayId)
} catch (e: RemoteException) {
throw e.rethrowFromSystemServer()
}
onRotationChanged(context.display.rotation)
}
private fun onRotationChanged(rotation: Int) {
val isNewRotationNatural = rotation == Surface.ROTATION_0 ||
rotation == Surface.ROTATION_180
if (isNaturalRotation != isNewRotationNatural) {
isNaturalRotation = isNewRotationNatural
scopedUnfoldTransitionProgressProvider.setReadyToHandleTransition(isNewRotationNatural)
}
}
override fun destroy() {
try {
windowManagerInterface.removeRotationWatcher(rotationWatcher)
} catch (e: RemoteException) {
e.rethrowFromSystemServer()
}
scopedUnfoldTransitionProgressProvider.destroy()
}
override fun addCallback(listener: TransitionProgressListener) {
scopedUnfoldTransitionProgressProvider.addCallback(listener)
}
override fun removeCallback(listener: TransitionProgressListener) {
scopedUnfoldTransitionProgressProvider.removeCallback(listener)
}
private inner class RotationWatcher : IRotationWatcher.Stub() {
override fun onRotationChanged(rotation: Int) {
this@NaturalRotationUnfoldProgressProvider.onRotationChanged(rotation)
}
}
}
/*
* 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.unfold.util;
import android.annotation.NonNull;
import android.annotation.Nullable;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
import java.util.ArrayList;
import java.util.List;
/**
* Manages progress listeners that can have smaller lifespan than the unfold animation.
* Allows to limit getting transition updates to only when
* {@link ScopedUnfoldTransitionProgressProvider#setReadyToHandleTransition} is called
* with readyToHandleTransition = true
*
* If the transition has already started by the moment when the clients are ready to play
* the transition then it will report transition started callback and current animation progress.
*/
public final class ScopedUnfoldTransitionProgressProvider implements
UnfoldTransitionProgressProvider, TransitionProgressListener {
private static final float PROGRESS_UNSET = -1f;
@Nullable
private UnfoldTransitionProgressProvider mSource;
private final List<TransitionProgressListener> mListeners = new ArrayList<>();
private boolean mIsReadyToHandleTransition;
private boolean mIsTransitionRunning;
private float mLastTransitionProgress = PROGRESS_UNSET;
public ScopedUnfoldTransitionProgressProvider() {
this(null);
}
public ScopedUnfoldTransitionProgressProvider(
@Nullable UnfoldTransitionProgressProvider source) {
setSourceProvider(source);
}
/**
* Sets the source for the unfold transition progress updates,
* it replaces current provider if it is already set
* @param provider transition provider that emits transition progress updates
*/
public void setSourceProvider(@Nullable UnfoldTransitionProgressProvider provider) {
if (mSource != null) {
mSource.removeCallback(this);
}
if (provider != null) {
mSource = provider;
mSource.addCallback(this);
} else {
mSource = null;
}
}
/**
* Allows to notify this provide whether the listeners can play the transition or not.
* Call this method with readyToHandleTransition = true when all listeners
* are ready to consume the transition progress events.
* Call it with readyToHandleTransition = false when listeners can't process the events.
*/
public void setReadyToHandleTransition(boolean isReadyToHandleTransition) {
if (mIsTransitionRunning) {
if (isReadyToHandleTransition) {
mListeners.forEach(TransitionProgressListener::onTransitionStarted);
if (mLastTransitionProgress != PROGRESS_UNSET) {
mListeners.forEach(listener ->
listener.onTransitionProgress(mLastTransitionProgress));
}
} else {
mIsTransitionRunning = false;
mListeners.forEach(TransitionProgressListener::onTransitionFinished);
}
}
mIsReadyToHandleTransition = isReadyToHandleTransition;
}
@Override
public void addCallback(@NonNull TransitionProgressListener listener) {
mListeners.add(listener);
}
@Override
public void removeCallback(@NonNull TransitionProgressListener listener) {
mListeners.remove(listener);
}
@Override
public void destroy() {
mSource.removeCallback(this);
}
@Override
public void onTransitionStarted() {
this.mIsTransitionRunning = true;
if (mIsReadyToHandleTransition) {
mListeners.forEach(TransitionProgressListener::onTransitionStarted);
}
}
@Override
public void onTransitionProgress(float progress) {
if (mIsReadyToHandleTransition) {
mListeners.forEach(listener -> listener.onTransitionProgress(progress));
}
mLastTransitionProgress = progress;
}
@Override
public void onTransitionFinished() {
if (mIsReadyToHandleTransition) {
mListeners.forEach(TransitionProgressListener::onTransitionFinished);
}
mIsTransitionRunning = false;
mLastTransitionProgress = PROGRESS_UNSET;
}
}
......@@ -18,25 +18,28 @@ package com.android.systemui.statusbar.phone
import android.graphics.Point
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.android.systemui.R
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.unfold.UNFOLD_STATUS_BAR
import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
import com.android.systemui.util.ViewController
import javax.inject.Inject
import javax.inject.Named
import dagger.Lazy
/** Controller for [PhoneStatusBarView]. */
class PhoneStatusBarViewController(
class PhoneStatusBarViewController private constructor(
view: PhoneStatusBarView,
statusBarMoveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
@Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?,
private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
touchEventHandler: PhoneStatusBarView.TouchEventHandler,
) : ViewController<PhoneStatusBarView>(view) {
override fun onViewAttached() {}
override fun onViewDetached() {}
init {
mView.setTouchEventHandler(touchEventHandler)
statusBarMoveFromCenterAnimationController?.let { animationController ->
override fun onViewAttached() {
moveFromCenterAnimationController?.let { animationController ->
val statusBarLeftSide: View = mView.findViewById(R.id.status_bar_left_side)
val systemIconArea: ViewGroup = mView.findViewById(R.id.system_icon_area)
......@@ -46,15 +49,33 @@ class PhoneStatusBarViewController(
systemIconArea
)
animationController.init(viewsToAnimate, viewCenterProvider)
mView.viewTreeObserver.addOnPreDrawListener(object :
ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
animationController.onViewsReady(viewsToAnimate, viewCenterProvider)
mView.viewTreeObserver.removeOnPreDrawListener(this)
return true
}
})
mView.addOnLayoutChangeListener { _, left, _, right, _, oldLeft, _, oldRight, _ ->
val widthChanged = right - left != oldRight - oldLeft
if (widthChanged) {
statusBarMoveFromCenterAnimationController.onStatusBarWidthChanged()
moveFromCenterAnimationController.onStatusBarWidthChanged()
}
}
}
progressProvider?.setReadyToHandleTransition(true)
}
override fun onViewDetached() {
progressProvider?.setReadyToHandleTransition(false)
moveFromCenterAnimationController?.onViewDetached()
}
init {
mView.setTouchEventHandler(touchEventHandler)
}
fun setImportantForAccessibility(mode: Int) {
......@@ -92,4 +113,23 @@ class PhoneStatusBarViewController(
outPoint.y = viewY + view.height / 2
}
}
class Factory @Inject constructor(
@Named(UNFOLD_STATUS_BAR)
private val progressProvider: Lazy<ScopedUnfoldTransitionProgressProvider>,
private val moveFromCenterController: Lazy<StatusBarMoveFromCenterAnimationController>,
private val unfoldConfig: UnfoldTransitionConfig,
) {
fun create(
view: PhoneStatusBarView,
touchEventHandler: PhoneStatusBarView.TouchEventHandler
): PhoneStatusBarViewController {
return PhoneStatusBarViewController(
view,
if (unfoldConfig.isEnabled) progressProvider.get() else null,
if (unfoldConfig.isEnabled) moveFromCenterController.get() else null,
touchEventHandler
)
}
}
}
......@@ -233,6 +233,7 @@ import com.android.systemui.tuner.TunerService;
import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
import com.android.systemui.unfold.UnfoldTransitionWallpaperController;
import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
import com.android.systemui.util.WallpaperController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.MessageRouter;
......@@ -525,6 +526,7 @@ public class StatusBar extends SystemUI implements
private QSPanelController mQSPanelController;
private final OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
private final PhoneStatusBarViewController.Factory mPhoneStatusBarViewControllerFactory;
KeyguardIndicationController mKeyguardIndicationController;
private View mReportRejectedTouch;
......@@ -543,8 +545,8 @@ public class StatusBar extends SystemUI implements
private final FeatureFlags mFeatureFlags;
private final UnfoldTransitionConfig mUnfoldTransitionConfig;
private final Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimation;
private final Lazy<NaturalRotationUnfoldProgressProvider> mNaturalUnfoldProgressProvider;
private final Lazy<UnfoldTransitionWallpaperController> mUnfoldWallpaperController;
private final Lazy<StatusBarMoveFromCenterAnimationController> mMoveFromCenterAnimation;
private final WallpaperController mWallpaperController;
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private final MessageRouter mMessageRouter;
......@@ -772,6 +774,7 @@ public class StatusBar extends SystemUI implements
ExtensionController extensionController,
UserInfoControllerImpl userInfoControllerImpl,
OperatorNameViewController.Factory operatorNameViewControllerFactory,
PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory,
PhoneStatusBarPolicy phoneStatusBarPolicy,
KeyguardIndicationController keyguardIndicationController,
DemoModeController demoModeController,
......@@ -782,7 +785,7 @@ public class StatusBar extends SystemUI implements
UnfoldTransitionConfig unfoldTransitionConfig,
Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
Lazy<UnfoldTransitionWallpaperController> unfoldTransitionWallpaperController,
Lazy<StatusBarMoveFromCenterAnimationController> statusBarUnfoldAnimationController,
Lazy<NaturalRotationUnfoldProgressProvider> naturalRotationUnfoldProgressProvider,
WallpaperController wallpaperController,
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
......@@ -812,6 +815,7 @@ public class StatusBar extends SystemUI implements
mKeyguardStateController = keyguardStateController;
mHeadsUpManager = headsUpManagerPhone;
mOperatorNameViewControllerFactory = operatorNameViewControllerFactory;
mPhoneStatusBarViewControllerFactory = phoneStatusBarViewControllerFactory;
mKeyguardIndicationController = keyguardIndicationController;
mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
mDynamicPrivacyController = dynamicPrivacyController;
......@@ -879,9 +883,9 @@ public class StatusBar extends SystemUI implements
mBrightnessSliderFactory = brightnessSliderFactory;
mUnfoldTransitionConfig = unfoldTransitionConfig;
mUnfoldLightRevealOverlayAnimation = unfoldLightRevealOverlayAnimation;
mNaturalUnfoldProgressProvider = naturalRotationUnfoldProgressProvider;
mUnfoldWallpaperController = unfoldTransitionWallpaperController;
mWallpaperController = wallpaperController;
mMoveFromCenterAnimation = statusBarUnfoldAnimationController;
mOngoingCallController = ongoingCallController;
mAnimationScheduler = animationScheduler;
mStatusBarLocationPublisher = locationPublisher;
......@@ -1077,6 +1081,7 @@ public class StatusBar extends SystemUI implements
if (mUnfoldTransitionConfig.isEnabled()) {
mUnfoldLightRevealOverlayAnimation.get().init();
mUnfoldWallpaperController.get().init();
mNaturalUnfoldProgressProvider.get().init();
}
mPluginManager.addPluginListener(
......@@ -1178,16 +1183,9 @@ public class StatusBar extends SystemUI implements
mNotificationPanelViewController.setBar(mStatusBarView);
StatusBarMoveFromCenterAnimationController moveFromCenterAnimation = null;
if (mUnfoldTransitionConfig.isEnabled()) {
moveFromCenterAnimation = mMoveFromCenterAnimation.get();
}
mPhoneStatusBarViewController =
new PhoneStatusBarViewController(
mStatusBarView,
moveFromCenterAnimation,
mNotificationPanelViewController.getStatusBarTouchEventHandler()
);
mPhoneStatusBarViewController = mPhoneStatusBarViewControllerFactory
.create(mStatusBarView, mNotificationPanelViewController
.getStatusBarTouchEventHandler());
mPhoneStatusBarViewController.init();
mBatteryMeterViewController = new BatteryMeterViewController(
......
......@@ -20,43 +20,48 @@ import android.view.WindowManager
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator.ViewCenterProvider
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
import com.android.systemui.unfold.UNFOLD_STATUS_BAR
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
import javax.inject.Inject
import javax.inject.Named
@SysUISingleton
class StatusBarMoveFromCenterAnimationController @Inject constructor(
private val unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider,
private val windowManager: WindowManager
@Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider,
private val windowManager: WindowManager,
) {
private lateinit var moveFromCenterAnimator: UnfoldMoveFromCenterAnimator
private val transitionListener = TransitionListener()
private var moveFromCenterAnimator: UnfoldMoveFromCenterAnimator? = null
fun init(viewsToAnimate: Array<View>, viewCenterProvider: ViewCenterProvider) {
fun onViewsReady(viewsToAnimate: Array<View>, viewCenterProvider: ViewCenterProvider) {
moveFromCenterAnimator = UnfoldMoveFromCenterAnimator(windowManager,
viewCenterProvider = viewCenterProvider)
unfoldTransitionProgressProvider.addCallback(object : TransitionProgressListener {
override fun onTransitionStarted() {
moveFromCenterAnimator.updateDisplayProperties()
moveFromCenterAnimator?.updateDisplayProperties()
viewsToAnimate.forEach {
moveFromCenterAnimator.registerViewForAnimation(it)
}
}
viewsToAnimate.forEach {
moveFromCenterAnimator?.registerViewForAnimation(it)
}
override fun onTransitionFinished() {
moveFromCenterAnimator.onTransitionFinished()
moveFromCenterAnimator.clearRegisteredViews()
}
progressProvider.addCallback(transitionListener)
}
override fun onTransitionProgress(progress: Float) {
moveFromCenterAnimator.onTransitionProgress(progress)
}
})
fun onViewDetached() {
progressProvider.removeCallback(transitionListener)
moveFromCenterAnimator?.clearRegisteredViews()
moveFromCenterAnimator = null
}
fun onStatusBarWidthChanged() {
moveFromCenterAnimator.updateViewPositions()
moveFromCenterAnimator?.updateDisplayProperties()
moveFromCenterAnimator?.updateViewPositions()
}
private inner class TransitionListener : TransitionProgressListener {
override fun onTransitionProgress(progress: Float) {
moveFromCenterAnimator?.onTransitionProgress(progress)
}
}
}
......@@ -88,6 +88,7 @@ import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
......@@ -111,6 +112,7 @@ import com.android.systemui.tuner.TunerService;
import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
import com.android.systemui.unfold.UnfoldTransitionWallpaperController;
import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
import com.android.systemui.util.WallpaperController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.MessageRouter;
......@@ -211,6 +213,7 @@ public interface StatusBarPhoneModule {
ExtensionController extensionController,
UserInfoControllerImpl userInfoControllerImpl,
OperatorNameViewController.Factory operatorNameViewControllerFactory,
PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory,
PhoneStatusBarPolicy phoneStatusBarPolicy,
KeyguardIndicationController keyguardIndicationController,
DemoModeController demoModeController,
......@@ -220,6 +223,7 @@ public interface StatusBarPhoneModule {
BrightnessSlider.Factory brightnessSliderFactory,
UnfoldTransitionConfig unfoldTransitionConfig,
Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
Lazy<NaturalRotationUnfoldProgressProvider> naturalRotationUnfoldProgressProvider,
Lazy<UnfoldTransitionWallpaperController> unfoldTransitionWallpaperController,
Lazy<StatusBarMoveFromCenterAnimationController> statusBarMoveFromCenterAnimation,
WallpaperController wallpaperController,
......@@ -311,6 +315,7 @@ public interface StatusBarPhoneModule {
extensionController,
userInfoControllerImpl,
operatorNameViewControllerFactory,
phoneStatusBarViewControllerFactory,
phoneStatusBarPolicy,
keyguardIndicationController,
demoModeController,
......@@ -321,7 +326,7 @@ public interface StatusBarPhoneModule {
unfoldTransitionConfig,
unfoldLightRevealOverlayAnimation,
unfoldTransitionWallpaperController,
statusBarMoveFromCenterAnimation,
naturalRotationUnfoldProgressProvider,
wallpaperController,
ongoingCallController,
animationScheduler,
......
......@@ -20,15 +20,19 @@ import android.content.Context
import android.hardware.SensorManager
import android.hardware.devicestate.DeviceStateManager
import android.os.Handler
import android.view.IWindowManager
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.LifecycleScreenStatusProvider
import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider
import dagger.Lazy
import dagger.Module
import dagger.Provides
import java.util.Optional
import java.util.concurrent.Executor
import javax.inject.Named
import javax.inject.Singleton
@Module
......@@ -60,6 +64,27 @@ class UnfoldTransitionModule {
fun provideUnfoldTransitionConfig(context: Context): UnfoldTransitionConfig =
createConfig(context)
@Provides
@Singleton
fun provideNaturalRotationProgressProvider(
context: Context,
windowManager: IWindowManager,
unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider
): NaturalRotationUnfoldProgressProvider =
NaturalRotationUnfoldProgressProvider(
context,
windowManager,
unfoldTransitionProgressProvider
)
@Provides
@Named(UNFOLD_STATUS_BAR)
@Singleton
fun provideStatusBarScopedTransitionProvider(
source: NaturalRotationUnfoldProgressProvider
): ScopedUnfoldTransitionProgressProvider =
ScopedUnfoldTransitionProgressProvider(source)
@Provides
@Singleton
fun provideShellProgressProvider(
......@@ -72,3 +97,5 @@ class UnfoldTransitionModule {
Optional.empty()
}
}
const val UNFOLD_STATUS_BAR = "unfold_status_bar"
\ No newline at end of file
......@@ -19,19 +19,25 @@ package com.android.systemui.statusbar.phone
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.view.ViewTreeObserver.OnPreDrawListener
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
import com.android.systemui.util.mockito.any
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.spy
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.verify
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
@SmallTest
......@@ -48,10 +54,14 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@Mock
private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
@Mock
private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider
private lateinit var view: PhoneStatusBarView
private lateinit var controller: PhoneStatusBarViewController
private val unfoldConfig = UnfoldConfig()
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
......@@ -66,11 +76,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
view.setBar(mock(StatusBar::class.java))
}
controller = PhoneStatusBarViewController(
view,
null,
touchEventHandler,
)
controller = createController(view)
}
@Test
......@@ -83,12 +89,38 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
}
@Test
fun constructor_moveFromCenterAnimationIsNotNull_moveFromCenterAnimationInitialized() {
controller = PhoneStatusBarViewController(
view, moveFromCenterAnimation, touchEventHandler
)
fun onViewAttachedAndDrawn_moveFromCenterAnimationEnabled_moveFromCenterAnimationInitialized() {
val view = createViewMock()
val argumentCaptor = ArgumentCaptor.forClass(OnPreDrawListener::class.java)
unfoldConfig.isEnabled = true
controller = createController(view)
controller.init()
verify(view.viewTreeObserver).addOnPreDrawListener(argumentCaptor.capture())
argumentCaptor.value.onPreDraw()
verify(moveFromCenterAnimation).onViewsReady(any(), any())
}
private fun createViewMock(): PhoneStatusBarView {
val view = spy(view)
val viewTreeObserver = mock(ViewTreeObserver::class.java)
`when`(view.viewTreeObserver).thenReturn(viewTreeObserver)
`when`(view.isAttachedToWindow).thenReturn(true)
return view
}
verify(moveFromCenterAnimation).init(any(), any())
private fun createController(view: PhoneStatusBarView): PhoneStatusBarViewController {
return PhoneStatusBarViewController.Factory(
{ progressProvider },
{ moveFromCenterAnimation },
unfoldConfig
).create(view, touchEventHandler)
}
private class UnfoldConfig : UnfoldTransitionConfig {
override var isEnabled: Boolean = false
override var isHingeAngleEnabled: Boolean = false
}
private class TestTouchEventHandler : PhoneStatusBarView.TouchEventHandler {
......@@ -97,6 +129,5 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
lastEvent = event
return false
}
}
}
......@@ -144,6 +144,7 @@ import com.android.systemui.tuner.TunerService;
import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
import com.android.systemui.unfold.UnfoldTransitionWallpaperController;
import com.android.systemui.unfold.config.UnfoldTransitionConfig;
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
import com.android.systemui.util.WallpaperController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.concurrency.MessageRouterImpl;
......@@ -259,7 +260,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private BrightnessSlider.Factory mBrightnessSliderFactory;
@Mock private UnfoldTransitionConfig mUnfoldTransitionConfig;
@Mock private Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimationLazy;
@Mock private Lazy<StatusBarMoveFromCenterAnimationController> mMoveFromCenterAnimationLazy;
@Mock private Lazy<NaturalRotationUnfoldProgressProvider> mNaturalRotationProgressProvider;
@Mock private Lazy<UnfoldTransitionWallpaperController> mUnfoldWallpaperController;
@Mock private WallpaperController mWallpaperController;
@Mock private OngoingCallController mOngoingCallController;
......@@ -276,6 +277,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private StartingSurface mStartingSurface;
@Mock private OperatorNameViewController mOperatorNameViewController;
@Mock private OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
@Mock private PhoneStatusBarViewController.Factory mPhoneStatusBarViewControllerFactory;
@Mock private ActivityLaunchAnimator mActivityLaunchAnimator;
@Mock private DialogLaunchAnimator mDialogLaunchAnimator;
private ShadeController mShadeController;
......@@ -429,6 +431,7 @@ public class StatusBarTest extends SysuiTestCase {
mExtensionController,
mUserInfoControllerImpl,
mOperatorNameViewControllerFactory,
mPhoneStatusBarViewControllerFactory,
mPhoneStatusBarPolicy,
mKeyguardIndicationController,
mDemoModeController,
......@@ -439,7 +442,7 @@ public class StatusBarTest extends SysuiTestCase {
mUnfoldTransitionConfig,
mUnfoldLightRevealOverlayAnimationLazy,
mUnfoldWallpaperController,
mMoveFromCenterAnimationLazy,
mNaturalRotationProgressProvider,
mWallpaperController,
mOngoingCallController,
mAnimationScheduler,
......
/*
* 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.unfold.util
import android.testing.AndroidTestingRunner
import android.view.IRotationWatcher
import android.view.IWindowManager
import android.view.Surface
import androidx.test.filters.SmallTest
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import com.android.systemui.util.mockito.any
import com.android.systemui.SysuiTestCase
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@SmallTest
class NaturalRotationUnfoldProgressProviderTest : SysuiTestCase() {
@Mock
lateinit var windowManager: IWindowManager
@Mock
lateinit var sourceProvider: UnfoldTransitionProgressProvider
@Mock
lateinit var transitionListener: TransitionProgressListener
lateinit var progressProvider: NaturalRotationUnfoldProgressProvider
private val sourceProviderListenerCaptor =
ArgumentCaptor.forClass(TransitionProgressListener::class.java)
private val rotationWatcherCaptor =
ArgumentCaptor.forClass(IRotationWatcher.Stub::class.java)
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
progressProvider = NaturalRotationUnfoldProgressProvider(
context,
windowManager,
sourceProvider
)
progressProvider.init()
verify(sourceProvider).addCallback(sourceProviderListenerCaptor.capture())
verify(windowManager).watchRotation(rotationWatcherCaptor.capture(), any())
progressProvider.addCallback(transitionListener)
}
@Test
fun testNaturalRotation0_sendTransitionStartedEvent_eventReceived() {
onRotationChanged(Surface.ROTATION_0)
source.onTransitionStarted()
verify(transitionListener).onTransitionStarted()
}
@Test
fun testNaturalRotation0_sendTransitionProgressEvent_eventReceived() {
onRotationChanged(Surface.ROTATION_0)
source.onTransitionProgress(0.5f)
verify(transitionListener).onTransitionProgress(0.5f)
}
@Test
fun testNotNaturalRotation90_sendTransitionStartedEvent_eventNotReceived() {
onRotationChanged(Surface.ROTATION_90)
source.onTransitionStarted()
verify(transitionListener, never()).onTransitionStarted()
}
@Test
fun testNaturalRotation90_sendTransitionProgressEvent_eventNotReceived() {
onRotationChanged(Surface.ROTATION_90)
source.onTransitionProgress(0.5f)
verify(transitionListener, never()).onTransitionProgress(0.5f)
}
@Test
fun testRotationBecameUnnaturalDuringTransition_sendsTransitionFinishedEvent() {
onRotationChanged(Surface.ROTATION_0)
source.onTransitionStarted()
clearInvocations(transitionListener)
onRotationChanged(Surface.ROTATION_90)
verify(transitionListener).onTransitionFinished()
}
@Test
fun testRotationBecameNaturalDuringTransition_sendsTransitionStartedEvent() {
onRotationChanged(Surface.ROTATION_90)
source.onTransitionStarted()
clearInvocations(transitionListener)
onRotationChanged(Surface.ROTATION_0)
verify(transitionListener).onTransitionStarted()
}
private fun onRotationChanged(rotation: Int) {
rotationWatcherCaptor.value.onRotationChanged(rotation)
}
private val source: TransitionProgressListener
get() = sourceProviderListenerCaptor.value
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment