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_SYSUI_PROXY = "extra_sysui_proxy";
|
||||||
public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius";
|
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_SUPPORTS_WINDOW_CORNERS = "extra_supports_window_corners";
|
||||||
|
public static final String KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER = "extra_unfold_animation";
|
||||||
// See ISysuiUnlockAnimationController.aidl
|
// See ISysuiUnlockAnimationController.aidl
|
||||||
public static final String KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER = "unlock_animation";
|
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.FoldStateLoggingProvider;
|
||||||
import com.android.systemui.unfold.SysUIUnfoldComponent;
|
import com.android.systemui.unfold.SysUIUnfoldComponent;
|
||||||
import com.android.systemui.unfold.UnfoldLatencyTracker;
|
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.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
|
||||||
import com.android.wm.shell.TaskViewFactory;
|
import com.android.wm.shell.TaskViewFactory;
|
||||||
import com.android.wm.shell.back.BackAnimation;
|
import com.android.wm.shell.back.BackAnimation;
|
||||||
@@ -137,6 +139,10 @@ public interface SysUIComponent {
|
|||||||
getUnfoldLatencyTracker().init();
|
getUnfoldLatencyTracker().init();
|
||||||
getFoldStateLoggingProvider().ifPresent(FoldStateLoggingProvider::init);
|
getFoldStateLoggingProvider().ifPresent(FoldStateLoggingProvider::init);
|
||||||
getFoldStateLogger().ifPresent(FoldStateLogger::init);
|
getFoldStateLogger().ifPresent(FoldStateLogger::init);
|
||||||
|
getUnfoldTransitionProgressProvider().ifPresent((progressProvider) ->
|
||||||
|
getUnfoldTransitionProgressForwarder().ifPresent((forwarder) ->
|
||||||
|
progressProvider.addCallback(forwarder)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,6 +169,18 @@ public interface SysUIComponent {
|
|||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
UnfoldLatencyTracker getUnfoldLatencyTracker();
|
UnfoldLatencyTracker getUnfoldLatencyTracker();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a UnfoldTransitionProgressProvider.
|
||||||
|
*/
|
||||||
|
@SysUISingleton
|
||||||
|
Optional<UnfoldTransitionProgressProvider> getUnfoldTransitionProgressProvider();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a UnfoldTransitionProgressForwarder.
|
||||||
|
*/
|
||||||
|
@SysUISingleton
|
||||||
|
Optional<UnfoldTransitionProgressForwarder> getUnfoldTransitionProgressForwarder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a FoldStateLoggingProvider.
|
* 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.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_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_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_UNLOCK_ANIMATION_CONTROLLER;
|
||||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_WINDOW_CORNER_RADIUS;
|
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;
|
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.CentralSurfaces;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
|
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
|
||||||
import com.android.systemui.statusbar.policy.CallbackController;
|
import com.android.systemui.statusbar.policy.CallbackController;
|
||||||
|
import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder;
|
||||||
import com.android.wm.shell.sysui.ShellInterface;
|
import com.android.wm.shell.sysui.ShellInterface;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -144,6 +146,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
|
|||||||
private final CommandQueue mCommandQueue;
|
private final CommandQueue mCommandQueue;
|
||||||
private final UserTracker mUserTracker;
|
private final UserTracker mUserTracker;
|
||||||
private final KeyguardUnlockAnimationController mSysuiUnlockAnimationController;
|
private final KeyguardUnlockAnimationController mSysuiUnlockAnimationController;
|
||||||
|
private final Optional<UnfoldTransitionProgressForwarder> mUnfoldTransitionProgressForwarder;
|
||||||
private final UiEventLogger mUiEventLogger;
|
private final UiEventLogger mUiEventLogger;
|
||||||
private final DisplayTracker mDisplayTracker;
|
private final DisplayTracker mDisplayTracker;
|
||||||
|
|
||||||
@@ -415,6 +418,10 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
|
|||||||
params.putBoolean(KEY_EXTRA_SUPPORTS_WINDOW_CORNERS, mSupportsRoundedCornersOnWindows);
|
params.putBoolean(KEY_EXTRA_SUPPORTS_WINDOW_CORNERS, mSupportsRoundedCornersOnWindows);
|
||||||
params.putBinder(KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER,
|
params.putBinder(KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER,
|
||||||
mSysuiUnlockAnimationController.asBinder());
|
mSysuiUnlockAnimationController.asBinder());
|
||||||
|
mUnfoldTransitionProgressForwarder.ifPresent(
|
||||||
|
unfoldProgressForwarder -> params.putBinder(
|
||||||
|
KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER,
|
||||||
|
unfoldProgressForwarder.asBinder()));
|
||||||
// Add all the interfaces exposed by the shell
|
// Add all the interfaces exposed by the shell
|
||||||
mShellInterface.createExternalInterfaces(params);
|
mShellInterface.createExternalInterfaces(params);
|
||||||
|
|
||||||
@@ -512,7 +519,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
|
|||||||
DisplayTracker displayTracker,
|
DisplayTracker displayTracker,
|
||||||
KeyguardUnlockAnimationController sysuiUnlockAnimationController,
|
KeyguardUnlockAnimationController sysuiUnlockAnimationController,
|
||||||
AssistUtils assistUtils,
|
AssistUtils assistUtils,
|
||||||
DumpManager dumpManager) {
|
DumpManager dumpManager,
|
||||||
|
Optional<UnfoldTransitionProgressForwarder> unfoldTransitionProgressForwarder
|
||||||
|
) {
|
||||||
// b/241601880: This component shouldn't be running for a non-primary user
|
// b/241601880: This component shouldn't be running for a non-primary user
|
||||||
if (!Process.myUserHandle().equals(UserHandle.SYSTEM)) {
|
if (!Process.myUserHandle().equals(UserHandle.SYSTEM)) {
|
||||||
Log.e(TAG_OPS, "Unexpected initialization for non-primary user", new Throwable());
|
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);
|
mSysUiState.addCallback(this::notifySystemUiStateFlags);
|
||||||
mUiEventLogger = uiEventLogger;
|
mUiEventLogger = uiEventLogger;
|
||||||
mDisplayTracker = displayTracker;
|
mDisplayTracker = displayTracker;
|
||||||
|
mUnfoldTransitionProgressForwarder = unfoldTransitionProgressForwarder;
|
||||||
|
|
||||||
dumpManager.registerDumpable(getClass().getSimpleName(), this);
|
dumpManager.registerDumpable(getClass().getSimpleName(), this);
|
||||||
|
|
||||||
|
|||||||
@@ -20,17 +20,13 @@ import androidx.test.filters.SmallTest
|
|||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
|
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
|
||||||
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
|
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.updates.FOLD_UPDATE_FINISH_FULL_OPEN
|
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_FINISH_HALF_OPEN
|
||||||
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
|
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.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.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
@@ -45,9 +41,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
progressProvider = PhysicsBasedUnfoldTransitionProgressProvider(
|
progressProvider = PhysicsBasedUnfoldTransitionProgressProvider(foldStateProvider)
|
||||||
foldStateProvider
|
|
||||||
)
|
|
||||||
progressProvider.addCallback(listener)
|
progressProvider.addCallback(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,9 +73,7 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
|
|||||||
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
|
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
|
||||||
)
|
)
|
||||||
|
|
||||||
with(listener.ensureTransitionFinished()) {
|
with(listener.ensureTransitionFinished()) { assertHasSingleFinishingEvent() }
|
||||||
assertHasSingleFinishingEvent()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -150,106 +142,12 @@ class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
|
|||||||
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_CLOSED) },
|
{ foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_CLOSED) },
|
||||||
)
|
)
|
||||||
|
|
||||||
with(listener.ensureTransitionFinished()) {
|
with(listener.ensureTransitionFinished()) { assertHasFoldAnimationAtTheEnd() }
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runOnMainThreadWithInterval(vararg blocks: () -> Unit, intervalMillis: Long = 60) {
|
private fun runOnMainThreadWithInterval(vararg blocks: () -> Unit, intervalMillis: Long = 60) {
|
||||||
blocks.forEach {
|
blocks.forEach {
|
||||||
InstrumentationRegistry.getInstrumentation().runOnMainSync {
|
InstrumentationRegistry.getInstrumentation().runOnMainSync { it() }
|
||||||
it()
|
|
||||||
}
|
|
||||||
Thread.sleep(intervalMillis)
|
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.config.UnfoldTransitionConfig
|
||||||
import com.android.systemui.unfold.dagger.UnfoldMain
|
import com.android.systemui.unfold.dagger.UnfoldMain
|
||||||
import com.android.systemui.unfold.dagger.UnfoldSingleThreadBg
|
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.FoldProvider
|
||||||
import com.android.systemui.unfold.updates.RotationChangeProvider
|
import com.android.systemui.unfold.updates.RotationChangeProvider
|
||||||
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
|
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
|
||||||
@@ -68,3 +69,38 @@ interface UnfoldSharedComponent {
|
|||||||
val unfoldTransitionProvider: Optional<UnfoldTransitionProgressProvider>
|
val unfoldTransitionProvider: Optional<UnfoldTransitionProgressProvider>
|
||||||
val rotationChangeProvider: RotationChangeProvider
|
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.config.UnfoldTransitionConfig
|
||||||
import com.android.systemui.unfold.progress.FixedTimingTransitionProgressProvider
|
import com.android.systemui.unfold.progress.FixedTimingTransitionProgressProvider
|
||||||
import com.android.systemui.unfold.progress.PhysicsBasedUnfoldTransitionProgressProvider
|
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.DeviceFoldStateProvider
|
||||||
import com.android.systemui.unfold.updates.FoldStateProvider
|
import com.android.systemui.unfold.updates.FoldStateProvider
|
||||||
import com.android.systemui.unfold.updates.hinge.EmptyHingeAngleProvider
|
import com.android.systemui.unfold.updates.hinge.EmptyHingeAngleProvider
|
||||||
@@ -102,4 +103,16 @@ internal class UnfoldSharedInternalModule {
|
|||||||
EmptyHingeAngleProvider
|
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,
|
tracingTagPrefix,
|
||||||
windowManager,
|
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