Merge "Drive Launcher unfold animation from System UI" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a8719c31a8
@@ -43,6 +43,7 @@ public class QuickStepContract {
|
||||
public static final String KEY_EXTRA_SYSUI_PROXY = "extra_sysui_proxy";
|
||||
public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius";
|
||||
public static final String KEY_EXTRA_SUPPORTS_WINDOW_CORNERS = "extra_supports_window_corners";
|
||||
public static final String KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER = "extra_unfold_animation";
|
||||
// See ISysuiUnlockAnimationController.aidl
|
||||
public static final String KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER = "unlock_animation";
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ import com.android.systemui.unfold.FoldStateLogger;
|
||||
import com.android.systemui.unfold.FoldStateLoggingProvider;
|
||||
import com.android.systemui.unfold.SysUIUnfoldComponent;
|
||||
import com.android.systemui.unfold.UnfoldLatencyTracker;
|
||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
|
||||
import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder;
|
||||
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
|
||||
import com.android.wm.shell.TaskViewFactory;
|
||||
import com.android.wm.shell.back.BackAnimation;
|
||||
@@ -137,6 +139,10 @@ public interface SysUIComponent {
|
||||
getUnfoldLatencyTracker().init();
|
||||
getFoldStateLoggingProvider().ifPresent(FoldStateLoggingProvider::init);
|
||||
getFoldStateLogger().ifPresent(FoldStateLogger::init);
|
||||
getUnfoldTransitionProgressProvider().ifPresent((progressProvider) ->
|
||||
getUnfoldTransitionProgressForwarder().ifPresent((forwarder) ->
|
||||
progressProvider.addCallback(forwarder)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,6 +169,18 @@ public interface SysUIComponent {
|
||||
@SysUISingleton
|
||||
UnfoldLatencyTracker getUnfoldLatencyTracker();
|
||||
|
||||
/**
|
||||
* Creates a UnfoldTransitionProgressProvider.
|
||||
*/
|
||||
@SysUISingleton
|
||||
Optional<UnfoldTransitionProgressProvider> getUnfoldTransitionProgressProvider();
|
||||
|
||||
/**
|
||||
* Creates a UnfoldTransitionProgressForwarder.
|
||||
*/
|
||||
@SysUISingleton
|
||||
Optional<UnfoldTransitionProgressForwarder> getUnfoldTransitionProgressForwarder();
|
||||
|
||||
/**
|
||||
* Creates a FoldStateLoggingProvider.
|
||||
*/
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
|
||||
import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SUPPORTS_WINDOW_CORNERS;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_WINDOW_CORNER_RADIUS;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
|
||||
@@ -99,6 +100,7 @@ import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
import com.android.systemui.statusbar.phone.CentralSurfaces;
|
||||
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
|
||||
import com.android.systemui.statusbar.policy.CallbackController;
|
||||
import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder;
|
||||
import com.android.wm.shell.sysui.ShellInterface;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -144,6 +146,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
|
||||
private final CommandQueue mCommandQueue;
|
||||
private final UserTracker mUserTracker;
|
||||
private final KeyguardUnlockAnimationController mSysuiUnlockAnimationController;
|
||||
private final Optional<UnfoldTransitionProgressForwarder> mUnfoldTransitionProgressForwarder;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private final DisplayTracker mDisplayTracker;
|
||||
|
||||
@@ -415,6 +418,10 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
|
||||
params.putBoolean(KEY_EXTRA_SUPPORTS_WINDOW_CORNERS, mSupportsRoundedCornersOnWindows);
|
||||
params.putBinder(KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER,
|
||||
mSysuiUnlockAnimationController.asBinder());
|
||||
mUnfoldTransitionProgressForwarder.ifPresent(
|
||||
unfoldProgressForwarder -> params.putBinder(
|
||||
KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER,
|
||||
unfoldProgressForwarder.asBinder()));
|
||||
// Add all the interfaces exposed by the shell
|
||||
mShellInterface.createExternalInterfaces(params);
|
||||
|
||||
@@ -512,7 +519,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
|
||||
DisplayTracker displayTracker,
|
||||
KeyguardUnlockAnimationController sysuiUnlockAnimationController,
|
||||
AssistUtils assistUtils,
|
||||
DumpManager dumpManager) {
|
||||
DumpManager dumpManager,
|
||||
Optional<UnfoldTransitionProgressForwarder> unfoldTransitionProgressForwarder
|
||||
) {
|
||||
// b/241601880: This component shouldn't be running for a non-primary user
|
||||
if (!Process.myUserHandle().equals(UserHandle.SYSTEM)) {
|
||||
Log.e(TAG_OPS, "Unexpected initialization for non-primary user", new Throwable());
|
||||
@@ -538,6 +547,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
|
||||
mSysUiState.addCallback(this::notifySystemUiStateFlags);
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mDisplayTracker = displayTracker;
|
||||
mUnfoldTransitionProgressForwarder = unfoldTransitionProgressForwarder;
|
||||
|
||||
dumpManager.registerDumpable(getClass().getSimpleName(), this);
|
||||
|
||||
|
||||
@@ -20,17 +20,13 @@ import androidx.test.filters.SmallTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
|
||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
|
||||
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
|
||||
import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
|
||||
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
|
||||
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
|
||||
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
|
||||
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
|
||||
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
|
||||
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
|
||||
import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
|
||||
import com.android.systemui.unfold.util.TestFoldStateProvider
|
||||
import com.android.systemui.util.leak.ReferenceTestUtils.waitForCondition
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.google.common.truth.Truth.assertWithMessage
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -45,9 +41,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
progressProvider = PhysicsBasedUnfoldTransitionProgressProvider(
|
||||
foldStateProvider
|
||||
)
|
||||
progressProvider = PhysicsBasedUnfoldTransitionProgressProvider(foldStateProvider)
|
||||
progressProvider.addCallback(listener)
|
||||
}
|
||||
|
||||
@@ -79,9 +73,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
|
||||
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
|
||||
)
|
||||
|
||||
with(listener.ensureTransitionFinished()) {
|
||||
assertHasSingleFinishingEvent()
|
||||
}
|
||||
with(listener.ensureTransitionFinished()) { assertHasSingleFinishingEvent() }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -150,106 +142,12 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
|
||||
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_CLOSED) },
|
||||
)
|
||||
|
||||
with(listener.ensureTransitionFinished()) {
|
||||
assertHasFoldAnimationAtTheEnd()
|
||||
}
|
||||
}
|
||||
|
||||
private class TestUnfoldProgressListener : TransitionProgressListener {
|
||||
|
||||
private val recordings: MutableList<UnfoldTransitionRecording> = arrayListOf()
|
||||
private var currentRecording: UnfoldTransitionRecording? = null
|
||||
|
||||
override fun onTransitionStarted() {
|
||||
assertWithMessage("Trying to start a transition when it is already in progress")
|
||||
.that(currentRecording).isNull()
|
||||
|
||||
currentRecording = UnfoldTransitionRecording()
|
||||
}
|
||||
|
||||
override fun onTransitionProgress(progress: Float) {
|
||||
assertWithMessage("Received transition progress event when it's not started")
|
||||
.that(currentRecording).isNotNull()
|
||||
currentRecording!!.addProgress(progress)
|
||||
}
|
||||
|
||||
override fun onTransitionFinishing() {
|
||||
assertWithMessage("Received transition finishing event when it's not started")
|
||||
.that(currentRecording).isNotNull()
|
||||
currentRecording!!.onFinishing()
|
||||
}
|
||||
|
||||
override fun onTransitionFinished() {
|
||||
assertWithMessage("Received transition finish event when it's not started")
|
||||
.that(currentRecording).isNotNull()
|
||||
recordings += currentRecording!!
|
||||
currentRecording = null
|
||||
}
|
||||
|
||||
fun ensureTransitionFinished(): UnfoldTransitionRecording {
|
||||
waitForCondition { recordings.size == 1 }
|
||||
return recordings.first()
|
||||
}
|
||||
|
||||
class UnfoldTransitionRecording {
|
||||
private val progressHistory: MutableList<Float> = arrayListOf()
|
||||
private var finishingInvocations: Int = 0
|
||||
|
||||
fun addProgress(progress: Float) {
|
||||
assertThat(progress).isAtMost(1.0f)
|
||||
assertThat(progress).isAtLeast(0.0f)
|
||||
|
||||
progressHistory += progress
|
||||
}
|
||||
|
||||
fun onFinishing() {
|
||||
finishingInvocations++
|
||||
}
|
||||
|
||||
fun assertIncreasingProgress() {
|
||||
assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS)
|
||||
assertThat(progressHistory).isInOrder()
|
||||
}
|
||||
|
||||
fun assertDecreasingProgress() {
|
||||
assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS)
|
||||
assertThat(progressHistory).isInOrder(Comparator.reverseOrder<Float>())
|
||||
}
|
||||
|
||||
fun assertFinishedWithUnfold() {
|
||||
assertThat(progressHistory).isNotEmpty()
|
||||
assertThat(progressHistory.last()).isEqualTo(1.0f)
|
||||
}
|
||||
|
||||
fun assertFinishedWithFold() {
|
||||
assertThat(progressHistory).isNotEmpty()
|
||||
assertThat(progressHistory.last()).isEqualTo(0.0f)
|
||||
}
|
||||
|
||||
fun assertHasFoldAnimationAtTheEnd() {
|
||||
// Check that there are at least a few decreasing events at the end
|
||||
assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS)
|
||||
assertThat(progressHistory.takeLast(MIN_ANIMATION_EVENTS))
|
||||
.isInOrder(Comparator.reverseOrder<Float>())
|
||||
assertThat(progressHistory.last()).isEqualTo(0.0f)
|
||||
}
|
||||
|
||||
fun assertHasSingleFinishingEvent() {
|
||||
assertWithMessage("onTransitionFinishing callback should be invoked exactly " +
|
||||
"one time").that(finishingInvocations).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val MIN_ANIMATION_EVENTS = 5
|
||||
}
|
||||
with(listener.ensureTransitionFinished()) { assertHasFoldAnimationAtTheEnd() }
|
||||
}
|
||||
|
||||
private fun runOnMainThreadWithInterval(vararg blocks: () -> Unit, intervalMillis: Long = 60) {
|
||||
blocks.forEach {
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync {
|
||||
it()
|
||||
}
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync { it() }
|
||||
Thread.sleep(intervalMillis)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.progress
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@SmallTest
|
||||
class RemoteUnfoldTransitionReceiverTest : SysuiTestCase() {
|
||||
|
||||
private val progressProvider = RemoteUnfoldTransitionReceiver { it.run() }
|
||||
private val listener = TestUnfoldProgressListener()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
progressProvider.addCallback(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onTransitionStarted_propagated() {
|
||||
progressProvider.onTransitionStarted()
|
||||
|
||||
listener.assertStarted()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onTransitionProgress_propagated() {
|
||||
progressProvider.onTransitionStarted()
|
||||
|
||||
progressProvider.onTransitionProgress(0.5f)
|
||||
|
||||
listener.assertLastProgress(0.5f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onTransitionEnded_propagated() {
|
||||
progressProvider.onTransitionStarted()
|
||||
progressProvider.onTransitionProgress(0.5f)
|
||||
|
||||
progressProvider.onTransitionFinished()
|
||||
|
||||
listener.ensureTransitionFinished()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onTransitionStarted_afterCallbackRemoved_notPropagated() {
|
||||
progressProvider.removeCallback(listener)
|
||||
|
||||
progressProvider.onTransitionStarted()
|
||||
|
||||
listener.assertNotStarted()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.progress
|
||||
|
||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
|
||||
import com.android.systemui.util.leak.ReferenceTestUtils.waitForCondition
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.google.common.truth.Truth.assertWithMessage
|
||||
|
||||
/** Listener usable by tests with some handy assertions. */
|
||||
class TestUnfoldProgressListener : UnfoldTransitionProgressProvider.TransitionProgressListener {
|
||||
|
||||
private val recordings: MutableList<UnfoldTransitionRecording> = arrayListOf()
|
||||
private var currentRecording: UnfoldTransitionRecording? = null
|
||||
|
||||
override fun onTransitionStarted() {
|
||||
assertWithMessage("Trying to start a transition when it is already in progress")
|
||||
.that(currentRecording)
|
||||
.isNull()
|
||||
|
||||
currentRecording = UnfoldTransitionRecording()
|
||||
}
|
||||
|
||||
override fun onTransitionProgress(progress: Float) {
|
||||
assertWithMessage("Received transition progress event when it's not started")
|
||||
.that(currentRecording)
|
||||
.isNotNull()
|
||||
currentRecording!!.addProgress(progress)
|
||||
}
|
||||
|
||||
override fun onTransitionFinishing() {
|
||||
assertWithMessage("Received transition finishing event when it's not started")
|
||||
.that(currentRecording)
|
||||
.isNotNull()
|
||||
currentRecording!!.onFinishing()
|
||||
}
|
||||
|
||||
override fun onTransitionFinished() {
|
||||
assertWithMessage("Received transition finish event when it's not started")
|
||||
.that(currentRecording)
|
||||
.isNotNull()
|
||||
recordings += currentRecording!!
|
||||
currentRecording = null
|
||||
}
|
||||
|
||||
fun ensureTransitionFinished(): UnfoldTransitionRecording {
|
||||
waitForCondition { recordings.size == 1 }
|
||||
return recordings.first()
|
||||
}
|
||||
|
||||
fun assertStarted() {
|
||||
assertWithMessage("Transition didn't start").that(currentRecording).isNotNull()
|
||||
}
|
||||
|
||||
fun assertNotStarted() {
|
||||
assertWithMessage("Transition started").that(currentRecording).isNull()
|
||||
}
|
||||
|
||||
fun assertLastProgress(progress: Float) {
|
||||
currentRecording?.assertLastProgress(progress) ?: error("unfold not in progress.")
|
||||
}
|
||||
|
||||
class UnfoldTransitionRecording {
|
||||
private val progressHistory: MutableList<Float> = arrayListOf()
|
||||
private var finishingInvocations: Int = 0
|
||||
|
||||
fun addProgress(progress: Float) {
|
||||
assertThat(progress).isAtMost(1.0f)
|
||||
assertThat(progress).isAtLeast(0.0f)
|
||||
|
||||
progressHistory += progress
|
||||
}
|
||||
|
||||
fun onFinishing() {
|
||||
finishingInvocations++
|
||||
}
|
||||
|
||||
fun assertIncreasingProgress() {
|
||||
assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS)
|
||||
assertThat(progressHistory).isInOrder()
|
||||
}
|
||||
|
||||
fun assertDecreasingProgress() {
|
||||
assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS)
|
||||
assertThat(progressHistory).isInOrder(Comparator.reverseOrder<Float>())
|
||||
}
|
||||
|
||||
fun assertFinishedWithUnfold() {
|
||||
assertThat(progressHistory).isNotEmpty()
|
||||
assertThat(progressHistory.last()).isEqualTo(1.0f)
|
||||
}
|
||||
|
||||
fun assertFinishedWithFold() {
|
||||
assertThat(progressHistory).isNotEmpty()
|
||||
assertThat(progressHistory.last()).isEqualTo(0.0f)
|
||||
}
|
||||
|
||||
fun assertHasFoldAnimationAtTheEnd() {
|
||||
// Check that there are at least a few decreasing events at the end
|
||||
assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS)
|
||||
assertThat(progressHistory.takeLast(MIN_ANIMATION_EVENTS))
|
||||
.isInOrder(Comparator.reverseOrder<Float>())
|
||||
assertThat(progressHistory.last()).isEqualTo(0.0f)
|
||||
}
|
||||
|
||||
fun assertHasSingleFinishingEvent() {
|
||||
assertWithMessage(
|
||||
"onTransitionFinishing callback should be invoked exactly " + "one time"
|
||||
)
|
||||
.that(finishingInvocations)
|
||||
.isEqualTo(1)
|
||||
}
|
||||
|
||||
fun assertLastProgress(progress: Float) {
|
||||
assertThat(progressHistory.last()).isEqualTo(progress)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val MIN_ANIMATION_EVENTS = 5
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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
|
||||
|
||||
import com.android.systemui.unfold.config.UnfoldTransitionConfig
|
||||
import com.android.systemui.unfold.progress.RemoteUnfoldTransitionReceiver
|
||||
import com.android.systemui.unfold.util.ATraceLoggerTransitionProgressListener
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import java.util.Optional
|
||||
import javax.inject.Provider
|
||||
import javax.inject.Singleton
|
||||
|
||||
/** Binds classes needed to provide unfold transition progresses to another process. */
|
||||
@Module
|
||||
class UnfoldRemoteModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideTransitionProvider(
|
||||
config: UnfoldTransitionConfig,
|
||||
traceListener: ATraceLoggerTransitionProgressListener,
|
||||
remoteReceiverProvider: Provider<RemoteUnfoldTransitionReceiver>,
|
||||
): Optional<RemoteUnfoldTransitionReceiver> {
|
||||
if (!config.isEnabled) {
|
||||
return Optional.empty()
|
||||
}
|
||||
val remoteReceiver = remoteReceiverProvider.get()
|
||||
remoteReceiver.addCallback(traceListener)
|
||||
return Optional.of(remoteReceiver)
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import android.view.IWindowManager
|
||||
import com.android.systemui.unfold.config.UnfoldTransitionConfig
|
||||
import com.android.systemui.unfold.dagger.UnfoldMain
|
||||
import com.android.systemui.unfold.dagger.UnfoldSingleThreadBg
|
||||
import com.android.systemui.unfold.progress.RemoteUnfoldTransitionReceiver
|
||||
import com.android.systemui.unfold.updates.FoldProvider
|
||||
import com.android.systemui.unfold.updates.RotationChangeProvider
|
||||
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
|
||||
@@ -68,3 +69,38 @@ interface UnfoldSharedComponent {
|
||||
val unfoldTransitionProvider: Optional<UnfoldTransitionProgressProvider>
|
||||
val rotationChangeProvider: RotationChangeProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a [RemoteTransitionProgress] usable to receive unfold transition progress from another
|
||||
* process.
|
||||
*/
|
||||
@Singleton
|
||||
@Component(modules = [UnfoldRemoteModule::class])
|
||||
interface RemoteUnfoldSharedComponent {
|
||||
|
||||
@Component.Factory
|
||||
interface Factory {
|
||||
fun create(
|
||||
@BindsInstance context: Context,
|
||||
@BindsInstance config: UnfoldTransitionConfig,
|
||||
@BindsInstance @UnfoldMain executor: Executor,
|
||||
@BindsInstance @UnfoldSingleThreadBg singleThreadBgExecutor: Executor,
|
||||
@BindsInstance windowManager: IWindowManager,
|
||||
@BindsInstance @UnfoldTransitionATracePrefix tracingTagPrefix: String,
|
||||
): RemoteUnfoldSharedComponent
|
||||
}
|
||||
|
||||
val remoteTransitionProgress: Optional<RemoteUnfoldTransitionReceiver>
|
||||
val rotationChangeProvider: RotationChangeProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Usable to receive and propagate unfold transition progresses
|
||||
*
|
||||
* All unfold events received by [remoteReceiver] will be propagated to [localProvider].
|
||||
* [remoteReceiver] is meant to receive events from a remote process (E.g. from a binder service).
|
||||
*/
|
||||
data class RemoteTransitionProgress(
|
||||
val localProvider: UnfoldTransitionProgressProvider,
|
||||
val remoteReceiver: UnfoldTransitionProgressProvider.TransitionProgressListener
|
||||
)
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.systemui.unfold
|
||||
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.progress.UnfoldTransitionProgressForwarder
|
||||
import com.android.systemui.unfold.updates.DeviceFoldStateProvider
|
||||
import com.android.systemui.unfold.updates.FoldStateProvider
|
||||
import com.android.systemui.unfold.updates.hinge.EmptyHingeAngleProvider
|
||||
@@ -102,4 +103,16 @@ internal class UnfoldSharedInternalModule {
|
||||
EmptyHingeAngleProvider
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideProgressForwarder(
|
||||
config: UnfoldTransitionConfig,
|
||||
progressForwarder: Provider<UnfoldTransitionProgressForwarder>
|
||||
): Optional<UnfoldTransitionProgressForwarder> {
|
||||
if (!config.isEnabled) {
|
||||
return Optional.empty()
|
||||
}
|
||||
return Optional.of(progressForwarder.get())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,3 +63,26 @@ fun createUnfoldSharedComponent(
|
||||
tracingTagPrefix,
|
||||
windowManager,
|
||||
)
|
||||
|
||||
/**
|
||||
* Factory for [RemoteUnfoldSharedComponent].
|
||||
*
|
||||
* Wraps [DaggerRemoteUnfoldSharedComponent] (that is autogenerated), for better discoverability.
|
||||
*/
|
||||
fun createRemoteUnfoldSharedComponent(
|
||||
context: Context,
|
||||
config: UnfoldTransitionConfig,
|
||||
mainExecutor: Executor,
|
||||
singleThreadBgExecutor: Executor,
|
||||
tracingTagPrefix: String,
|
||||
windowManager: IWindowManager,
|
||||
): RemoteUnfoldSharedComponent =
|
||||
DaggerRemoteUnfoldSharedComponent.factory()
|
||||
.create(
|
||||
context,
|
||||
config,
|
||||
mainExecutor,
|
||||
singleThreadBgExecutor,
|
||||
windowManager,
|
||||
tracingTagPrefix,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.progress;
|
||||
|
||||
|
||||
import com.android.systemui.unfold.progress.IUnfoldTransitionListener;
|
||||
|
||||
|
||||
/**
|
||||
* Interface exposed by System UI to allow remote process to register for unfold animation events.
|
||||
*/
|
||||
oneway interface IUnfoldAnimation {
|
||||
|
||||
/**
|
||||
* Sets a listener for the animation.
|
||||
*
|
||||
* Only one listener is supported. If there are multiple, the earlier one will be overridden.
|
||||
*/
|
||||
void setListener(in IUnfoldTransitionListener listener);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.progress;
|
||||
|
||||
|
||||
/**
|
||||
* Implemented by remote processes to receive unfold animation events from System UI.
|
||||
*/
|
||||
oneway interface IUnfoldTransitionListener {
|
||||
/**
|
||||
* Sent when unfold animation started.
|
||||
*/
|
||||
void onTransitionStarted() = 1;
|
||||
|
||||
/**
|
||||
* Sent when unfold animation progress changes.
|
||||
*/
|
||||
void onTransitionProgress(float progress) = 2;
|
||||
|
||||
/**
|
||||
* Sent when unfold animation finished.
|
||||
*/
|
||||
void onTransitionFinished() = 3;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.progress
|
||||
|
||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
|
||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
|
||||
import com.android.systemui.unfold.dagger.UnfoldMain
|
||||
import java.util.concurrent.Executor
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Receives unfold events from remote senders (System UI).
|
||||
*
|
||||
* A binder to an instance to this class (created with [RemoteUnfoldTransitionReceiver.asBinder])
|
||||
* should be sent to the remote process providing events.
|
||||
*/
|
||||
class RemoteUnfoldTransitionReceiver
|
||||
@Inject
|
||||
constructor(@UnfoldMain private val executor: Executor) :
|
||||
UnfoldTransitionProgressProvider, IUnfoldTransitionListener.Stub() {
|
||||
|
||||
private val listeners: MutableSet<TransitionProgressListener> = mutableSetOf()
|
||||
|
||||
override fun onTransitionStarted() {
|
||||
executor.execute { listeners.forEach { it.onTransitionStarted() } }
|
||||
}
|
||||
|
||||
override fun onTransitionProgress(progress: Float) {
|
||||
executor.execute { listeners.forEach { it.onTransitionProgress(progress) } }
|
||||
}
|
||||
|
||||
override fun onTransitionFinished() {
|
||||
executor.execute { listeners.forEach { it.onTransitionFinished() } }
|
||||
}
|
||||
|
||||
override fun addCallback(listener: TransitionProgressListener) {
|
||||
listeners += listener
|
||||
}
|
||||
|
||||
override fun removeCallback(listener: TransitionProgressListener) {
|
||||
listeners -= listener
|
||||
}
|
||||
|
||||
override fun destroy() {
|
||||
listeners.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.progress
|
||||
|
||||
import android.os.RemoteException
|
||||
import android.util.Log
|
||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
|
||||
import javax.inject.Inject
|
||||
|
||||
/** Forwards received unfold events to [remoteListener], when present. */
|
||||
class UnfoldTransitionProgressForwarder @Inject constructor() :
|
||||
TransitionProgressListener, IUnfoldAnimation.Stub() {
|
||||
|
||||
private var remoteListener: IUnfoldTransitionListener? = null
|
||||
|
||||
override fun onTransitionStarted() {
|
||||
try {
|
||||
Log.d(TAG, "onTransitionStarted")
|
||||
remoteListener?.onTransitionStarted()
|
||||
} catch (e: RemoteException) {
|
||||
Log.e(TAG, "Failed call onTransitionStarted", e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTransitionFinished() {
|
||||
try {
|
||||
Log.d(TAG, "onTransitionFinished")
|
||||
remoteListener?.onTransitionFinished()
|
||||
} catch (e: RemoteException) {
|
||||
Log.e(TAG, "Failed call onTransitionFinished", e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTransitionProgress(progress: Float) {
|
||||
try {
|
||||
remoteListener?.onTransitionProgress(progress)
|
||||
} catch (e: RemoteException) {
|
||||
Log.e(TAG, "Failed call onTransitionProgress", e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setListener(listener: IUnfoldTransitionListener?) {
|
||||
remoteListener = listener
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = UnfoldTransitionProgressForwarder::class.java.simpleName
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user