Merge "Disable unfold animation when animations disabled" into sc-v2-dev am: b6815ae344 am: d07dc67f9e
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16378723 Change-Id: I8cf3166e123aefa2a7741b9586288caaca9c1308
This commit is contained in:
@@ -26,6 +26,7 @@ import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig
|
||||
import com.android.systemui.unfold.config.UnfoldTransitionConfig
|
||||
import com.android.systemui.unfold.progress.FixedTimingTransitionProgressProvider
|
||||
import com.android.systemui.unfold.progress.PhysicsBasedUnfoldTransitionProgressProvider
|
||||
import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider
|
||||
import com.android.systemui.unfold.updates.DeviceFoldStateProvider
|
||||
import com.android.systemui.unfold.updates.hinge.EmptyHingeAngleProvider
|
||||
import com.android.systemui.unfold.updates.hinge.HingeSensorAngleProvider
|
||||
@@ -62,7 +63,7 @@ fun createUnfoldTransitionProgressProvider(
|
||||
mainExecutor
|
||||
)
|
||||
|
||||
return if (config.isHingeAngleEnabled) {
|
||||
val unfoldTransitionProgressProvider = if (config.isHingeAngleEnabled) {
|
||||
PhysicsBasedUnfoldTransitionProgressProvider(
|
||||
mainHandler,
|
||||
foldStateProvider
|
||||
@@ -70,6 +71,10 @@ fun createUnfoldTransitionProgressProvider(
|
||||
} else {
|
||||
FixedTimingTransitionProgressProvider(foldStateProvider)
|
||||
}
|
||||
return ScaleAwareTransitionProgressProvider(
|
||||
unfoldTransitionProgressProvider,
|
||||
context.contentResolver
|
||||
)
|
||||
}
|
||||
|
||||
fun createConfig(context: Context): UnfoldTransitionConfig =
|
||||
|
||||
@@ -2,7 +2,6 @@ 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
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.android.systemui.unfold.util
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.ContentResolver
|
||||
import android.database.ContentObserver
|
||||
import android.provider.Settings
|
||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
|
||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
|
||||
|
||||
/** Wraps [UnfoldTransitionProgressProvider] to disable transitions when animations are disabled. */
|
||||
class ScaleAwareTransitionProgressProvider(
|
||||
unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider,
|
||||
private val contentResolver: ContentResolver
|
||||
) : UnfoldTransitionProgressProvider {
|
||||
|
||||
private val scopedUnfoldTransitionProgressProvider =
|
||||
ScopedUnfoldTransitionProgressProvider(unfoldTransitionProgressProvider)
|
||||
|
||||
private val animatorDurationScaleObserver = object : ContentObserver(null) {
|
||||
override fun onChange(selfChange: Boolean) {
|
||||
onAnimatorScaleChanged()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
contentResolver.registerContentObserver(
|
||||
Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),
|
||||
/* notifyForDescendants= */ false,
|
||||
animatorDurationScaleObserver)
|
||||
onAnimatorScaleChanged()
|
||||
}
|
||||
|
||||
private fun onAnimatorScaleChanged() {
|
||||
val animationsEnabled = ValueAnimator.areAnimatorsEnabled()
|
||||
scopedUnfoldTransitionProgressProvider.setReadyToHandleTransition(animationsEnabled)
|
||||
}
|
||||
|
||||
override fun addCallback(listener: TransitionProgressListener) {
|
||||
scopedUnfoldTransitionProgressProvider.addCallback(listener)
|
||||
}
|
||||
|
||||
override fun removeCallback(listener: TransitionProgressListener) {
|
||||
scopedUnfoldTransitionProgressProvider.removeCallback(listener)
|
||||
}
|
||||
|
||||
override fun destroy() {
|
||||
contentResolver.unregisterContentObserver(animatorDurationScaleObserver)
|
||||
scopedUnfoldTransitionProgressProvider.destroy()
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.systemui.unfold
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.graphics.PixelFormat
|
||||
import android.hardware.devicestate.DeviceStateManager
|
||||
@@ -111,7 +112,7 @@ class UnfoldLightRevealOverlayAnimation @Inject constructor(
|
||||
Trace.beginSection("UnfoldLightRevealOverlayAnimation#onScreenTurningOn")
|
||||
try {
|
||||
// Add the view only if we are unfolding and this is the first screen on
|
||||
if (!isFolded && !isUnfoldHandled) {
|
||||
if (!isFolded && !isUnfoldHandled && ValueAnimator.areAnimatorsEnabled()) {
|
||||
addView(onOverlayReady)
|
||||
isUnfoldHandled = true
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.animation.ValueAnimator
|
||||
import android.content.ContentResolver
|
||||
import android.database.ContentObserver
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
|
||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
|
||||
import com.android.systemui.util.mockito.any
|
||||
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.verifyNoMoreInteractions
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@SmallTest
|
||||
class ScaleAwareUnfoldProgressProviderTest : SysuiTestCase() {
|
||||
|
||||
@Mock
|
||||
lateinit var contentResolver: ContentResolver
|
||||
|
||||
@Mock
|
||||
lateinit var sourceProvider: UnfoldTransitionProgressProvider
|
||||
|
||||
@Mock
|
||||
lateinit var sinkProvider: TransitionProgressListener
|
||||
|
||||
lateinit var progressProvider: ScaleAwareTransitionProgressProvider
|
||||
|
||||
private val sourceProviderListenerCaptor =
|
||||
ArgumentCaptor.forClass(TransitionProgressListener::class.java)
|
||||
|
||||
private val animatorDurationScaleListenerCaptor =
|
||||
ArgumentCaptor.forClass(ContentObserver::class.java)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
progressProvider = ScaleAwareTransitionProgressProvider(
|
||||
sourceProvider,
|
||||
contentResolver
|
||||
)
|
||||
|
||||
verify(sourceProvider).addCallback(sourceProviderListenerCaptor.capture())
|
||||
verify(contentResolver).registerContentObserver(any(), any(),
|
||||
animatorDurationScaleListenerCaptor.capture())
|
||||
|
||||
progressProvider.addCallback(sinkProvider)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onTransitionStarted_animationsEnabled_eventReceived() {
|
||||
setAnimationsEnabled(true)
|
||||
|
||||
source.onTransitionStarted()
|
||||
|
||||
verify(sinkProvider).onTransitionStarted()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onTransitionStarted_animationsNotEnabled_eventNotReceived() {
|
||||
setAnimationsEnabled(false)
|
||||
|
||||
source.onTransitionStarted()
|
||||
|
||||
verifyNoMoreInteractions(sinkProvider)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onTransitionEnd_animationsEnabled_eventReceived() {
|
||||
setAnimationsEnabled(true)
|
||||
|
||||
source.onTransitionFinished()
|
||||
|
||||
verify(sinkProvider).onTransitionFinished()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onTransitionEnd_animationsNotEnabled_eventNotReceived() {
|
||||
setAnimationsEnabled(false)
|
||||
|
||||
source.onTransitionFinished()
|
||||
|
||||
verifyNoMoreInteractions(sinkProvider)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onTransitionProgress_animationsEnabled_eventReceived() {
|
||||
setAnimationsEnabled(true)
|
||||
|
||||
source.onTransitionProgress(42f)
|
||||
|
||||
verify(sinkProvider).onTransitionProgress(42f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onTransitionProgress_animationsNotEnabled_eventNotReceived() {
|
||||
setAnimationsEnabled(false)
|
||||
|
||||
source.onTransitionProgress(42f)
|
||||
|
||||
verifyNoMoreInteractions(sinkProvider)
|
||||
}
|
||||
|
||||
private fun setAnimationsEnabled(enabled: Boolean) {
|
||||
val durationScale = if (enabled) {
|
||||
1f
|
||||
} else {
|
||||
0f
|
||||
}
|
||||
ValueAnimator.setDurationScale(durationScale)
|
||||
animatorDurationScaleListenerCaptor.value.dispatchChange(/* selfChange= */false)
|
||||
}
|
||||
|
||||
private val source: TransitionProgressListener
|
||||
get() = sourceProviderListenerCaptor.value
|
||||
}
|
||||
Reference in New Issue
Block a user