Loading libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java +2 −0 Original line number Diff line number Diff line Loading @@ -46,5 +46,7 @@ public interface ShellUnfoldProgressProvider { default void onStateChangeProgress(@FloatRange(from = 0.0, to = 1.0) float progress) {} default void onStateChangeFinished() {} default void onFoldStateChanged(boolean isFolded) {} } } libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java +31 −11 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene @Nullable private IBinder mTransition; private boolean mAnimationFinished = false; private final List<UnfoldTaskAnimator> mAnimators = new ArrayList<>(); public UnfoldTransitionHandler(ShellInit shellInit, Loading Loading @@ -132,6 +133,13 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene startTransaction.apply(); mFinishCallback = finishCallback; // Shell transition started when unfold animation has already finished, // finish shell transition immediately if (mAnimationFinished) { finishTransitionIfNeeded(); } return true; } Loading Loading @@ -161,17 +169,8 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene @Override public void onStateChangeFinished() { if (mFinishCallback == null) return; for (int i = 0; i < mAnimators.size(); i++) { final UnfoldTaskAnimator animator = mAnimators.get(i); animator.clearTasks(); animator.stop(); } mFinishCallback.onTransitionFinished(null); mFinishCallback = null; mTransition = null; mAnimationFinished = true; finishTransitionIfNeeded(); } @Override Loading Loading @@ -218,4 +217,25 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene public boolean willHandleTransition() { return mTransition != null; } @Override public void onFoldStateChanged(boolean isFolded) { if (isFolded) { mAnimationFinished = false; } } private void finishTransitionIfNeeded() { if (mFinishCallback == null) return; for (int i = 0; i < mAnimators.size(); i++) { final UnfoldTaskAnimator animator = mAnimators.get(i); animator.clearTasks(); animator.stop(); } mFinishCallback.onTransitionFinished(null); mFinishCallback = null; mTransition = null; } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java 0 → 100644 +280 −0 Original line number Diff line number Diff line /* * 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.wm.shell.unfold; import static android.view.WindowManager.TRANSIT_CHANGE; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.os.Binder; import android.os.IBinder; import android.view.Display; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions.TransitionFinishCallback; import com.android.wm.shell.unfold.animation.FullscreenUnfoldTaskAnimator; import com.android.wm.shell.unfold.animation.SplitTaskUnfoldAnimator; import org.junit.Before; import org.junit.Test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; public class UnfoldTransitionHandlerTest { private UnfoldTransitionHandler mUnfoldTransitionHandler; private final TestShellUnfoldProgressProvider mShellUnfoldProgressProvider = new TestShellUnfoldProgressProvider(); private final TestTransactionPool mTransactionPool = new TestTransactionPool(); private FullscreenUnfoldTaskAnimator mFullscreenUnfoldTaskAnimator; private SplitTaskUnfoldAnimator mSplitTaskUnfoldAnimator; private Transitions mTransitions; private final IBinder mTransition = new Binder(); @Before public void before() { final ShellExecutor executor = new TestSyncExecutor(); final ShellInit shellInit = new ShellInit(executor); mFullscreenUnfoldTaskAnimator = mock(FullscreenUnfoldTaskAnimator.class); mSplitTaskUnfoldAnimator = mock(SplitTaskUnfoldAnimator.class); mTransitions = mock(Transitions.class); mUnfoldTransitionHandler = new UnfoldTransitionHandler( shellInit, mShellUnfoldProgressProvider, mFullscreenUnfoldTaskAnimator, mSplitTaskUnfoldAnimator, mTransactionPool, executor, mTransitions ); shellInit.init(); } @Test public void handleRequest_physicalDisplayChange_handlesTransition() { ActivityManager.RunningTaskInfo triggerTaskInfo = new ActivityManager.RunningTaskInfo(); TransitionRequestInfo.DisplayChange displayChange = new TransitionRequestInfo.DisplayChange( Display.DEFAULT_DISPLAY).setPhysicalDisplayChanged(true); TransitionRequestInfo requestInfo = new TransitionRequestInfo(TRANSIT_CHANGE, triggerTaskInfo, /* remoteTransition= */ null, displayChange); WindowContainerTransaction result = mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); assertThat(result).isNotNull(); } @Test public void handleRequest_noPhysicalDisplayChange_doesNotHandleTransition() { ActivityManager.RunningTaskInfo triggerTaskInfo = new ActivityManager.RunningTaskInfo(); TransitionRequestInfo.DisplayChange displayChange = new TransitionRequestInfo.DisplayChange( Display.DEFAULT_DISPLAY).setPhysicalDisplayChanged(false); TransitionRequestInfo requestInfo = new TransitionRequestInfo(TRANSIT_CHANGE, triggerTaskInfo, /* remoteTransition= */ null, displayChange); WindowContainerTransaction result = mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); assertThat(result).isNull(); } @Test public void startAnimation_animationHasNotFinishedYet_doesNotFinishTheTransition() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); verify(finishCallback, never()).onTransitionFinished(any()); } @Test public void startAnimation_animationFinishes_finishesTheTransition() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); mShellUnfoldProgressProvider.onStateChangeStarted(); mShellUnfoldProgressProvider.onStateChangeFinished(); verify(finishCallback).onTransitionFinished(any()); } @Test public void startAnimation_animationIsAlreadyFinished_finishesTheTransition() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); mShellUnfoldProgressProvider.onStateChangeStarted(); mShellUnfoldProgressProvider.onStateChangeFinished(); mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); verify(finishCallback).onTransitionFinished(any()); } @Test public void startAnimationSecondTimeAfterFold_animationAlreadyFinished_finishesTransition() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); // First unfold mShellUnfoldProgressProvider.onFoldStateChanged(/* isFolded= */ false); mShellUnfoldProgressProvider.onStateChangeStarted(); mShellUnfoldProgressProvider.onStateChangeFinished(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); clearInvocations(finishCallback); // Fold mShellUnfoldProgressProvider.onFoldStateChanged(/* isFolded= */ true); // Second unfold mShellUnfoldProgressProvider.onFoldStateChanged(/* isFolded= */ false); mShellUnfoldProgressProvider.onStateChangeStarted(); mShellUnfoldProgressProvider.onStateChangeFinished(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); verify(finishCallback).onTransitionFinished(any()); } private TransitionRequestInfo createUnfoldTransitionRequestInfo() { ActivityManager.RunningTaskInfo triggerTaskInfo = new ActivityManager.RunningTaskInfo(); TransitionRequestInfo.DisplayChange displayChange = new TransitionRequestInfo.DisplayChange( Display.DEFAULT_DISPLAY).setPhysicalDisplayChanged(true); return new TransitionRequestInfo(TRANSIT_CHANGE, triggerTaskInfo, /* remoteTransition= */ null, displayChange); } private static class TestShellUnfoldProgressProvider implements ShellUnfoldProgressProvider, ShellUnfoldProgressProvider.UnfoldListener { private final List<UnfoldListener> mListeners = new ArrayList<>(); @Override public void addListener(Executor executor, UnfoldListener listener) { mListeners.add(listener); } @Override public void onFoldStateChanged(boolean isFolded) { mListeners.forEach(unfoldListener -> unfoldListener.onFoldStateChanged(isFolded)); } @Override public void onStateChangeFinished() { mListeners.forEach(UnfoldListener::onStateChangeFinished); } @Override public void onStateChangeProgress(float progress) { mListeners.forEach(unfoldListener -> unfoldListener.onStateChangeProgress(progress)); } @Override public void onStateChangeStarted() { mListeners.forEach(UnfoldListener::onStateChangeStarted); } } private static class TestTransactionPool extends TransactionPool { @Override public SurfaceControl.Transaction acquire() { return mock(SurfaceControl.Transaction.class); } @Override public void release(SurfaceControl.Transaction t) { } } private static class TestSyncExecutor implements ShellExecutor { @Override public void execute(Runnable runnable) { runnable.run(); } @Override public void executeDelayed(Runnable runnable, long delayMillis) { runnable.run(); } @Override public void removeCallbacks(Runnable runnable) { } @Override public boolean hasCallback(Runnable runnable) { return false; } } } No newline at end of file packages/SystemUI/src/com/android/systemui/unfold/UnfoldProgressProvider.kt +9 −1 Original line number Diff line number Diff line Loading @@ -17,11 +17,13 @@ package com.android.systemui.unfold import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener import com.android.systemui.unfold.updates.FoldProvider import com.android.wm.shell.unfold.ShellUnfoldProgressProvider import com.android.wm.shell.unfold.ShellUnfoldProgressProvider.UnfoldListener import java.util.concurrent.Executor class UnfoldProgressProvider(private val unfoldProgressProvider: UnfoldTransitionProgressProvider) : class UnfoldProgressProvider(private val unfoldProgressProvider: UnfoldTransitionProgressProvider, private val foldProvider: FoldProvider) : ShellUnfoldProgressProvider { override fun addListener(executor: Executor, listener: UnfoldListener) { Loading @@ -39,5 +41,11 @@ class UnfoldProgressProvider(private val unfoldProgressProvider: UnfoldTransitio executor.execute { listener.onStateChangeFinished() } } }) foldProvider.registerCallback(object : FoldProvider.FoldCallback { override fun onFoldUpdated(isFolded: Boolean) { listener.onFoldStateChanged(isFolded) } }, executor) } } packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt +4 −2 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ class UnfoldTransitionModule { @Singleton fun provideShellProgressProvider( config: UnfoldTransitionConfig, foldProvider: FoldProvider, provider: Provider<Optional<UnfoldTransitionProgressProvider>>, @Named(UNFOLD_ONLY_PROVIDER) unfoldOnlyProvider: Provider<Optional<UnfoldTransitionProgressProvider>> Loading @@ -135,8 +136,9 @@ class UnfoldTransitionModule { null } return resultingProvider?.get()?.orElse(null)?.let(::UnfoldProgressProvider) ?: ShellUnfoldProgressProvider.NO_PROVIDER return resultingProvider?.get()?.orElse(null)?.let { unfoldProgressProvider -> UnfoldProgressProvider(unfoldProgressProvider, foldProvider) } ?: ShellUnfoldProgressProvider.NO_PROVIDER } @Provides Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java +2 −0 Original line number Diff line number Diff line Loading @@ -46,5 +46,7 @@ public interface ShellUnfoldProgressProvider { default void onStateChangeProgress(@FloatRange(from = 0.0, to = 1.0) float progress) {} default void onStateChangeFinished() {} default void onFoldStateChanged(boolean isFolded) {} } }
libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java +31 −11 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene @Nullable private IBinder mTransition; private boolean mAnimationFinished = false; private final List<UnfoldTaskAnimator> mAnimators = new ArrayList<>(); public UnfoldTransitionHandler(ShellInit shellInit, Loading Loading @@ -132,6 +133,13 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene startTransaction.apply(); mFinishCallback = finishCallback; // Shell transition started when unfold animation has already finished, // finish shell transition immediately if (mAnimationFinished) { finishTransitionIfNeeded(); } return true; } Loading Loading @@ -161,17 +169,8 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene @Override public void onStateChangeFinished() { if (mFinishCallback == null) return; for (int i = 0; i < mAnimators.size(); i++) { final UnfoldTaskAnimator animator = mAnimators.get(i); animator.clearTasks(); animator.stop(); } mFinishCallback.onTransitionFinished(null); mFinishCallback = null; mTransition = null; mAnimationFinished = true; finishTransitionIfNeeded(); } @Override Loading Loading @@ -218,4 +217,25 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene public boolean willHandleTransition() { return mTransition != null; } @Override public void onFoldStateChanged(boolean isFolded) { if (isFolded) { mAnimationFinished = false; } } private void finishTransitionIfNeeded() { if (mFinishCallback == null) return; for (int i = 0; i < mAnimators.size(); i++) { final UnfoldTaskAnimator animator = mAnimators.get(i); animator.clearTasks(); animator.stop(); } mFinishCallback.onTransitionFinished(null); mFinishCallback = null; mTransition = null; } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java 0 → 100644 +280 −0 Original line number Diff line number Diff line /* * 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.wm.shell.unfold; import static android.view.WindowManager.TRANSIT_CHANGE; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.os.Binder; import android.os.IBinder; import android.view.Display; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions.TransitionFinishCallback; import com.android.wm.shell.unfold.animation.FullscreenUnfoldTaskAnimator; import com.android.wm.shell.unfold.animation.SplitTaskUnfoldAnimator; import org.junit.Before; import org.junit.Test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; public class UnfoldTransitionHandlerTest { private UnfoldTransitionHandler mUnfoldTransitionHandler; private final TestShellUnfoldProgressProvider mShellUnfoldProgressProvider = new TestShellUnfoldProgressProvider(); private final TestTransactionPool mTransactionPool = new TestTransactionPool(); private FullscreenUnfoldTaskAnimator mFullscreenUnfoldTaskAnimator; private SplitTaskUnfoldAnimator mSplitTaskUnfoldAnimator; private Transitions mTransitions; private final IBinder mTransition = new Binder(); @Before public void before() { final ShellExecutor executor = new TestSyncExecutor(); final ShellInit shellInit = new ShellInit(executor); mFullscreenUnfoldTaskAnimator = mock(FullscreenUnfoldTaskAnimator.class); mSplitTaskUnfoldAnimator = mock(SplitTaskUnfoldAnimator.class); mTransitions = mock(Transitions.class); mUnfoldTransitionHandler = new UnfoldTransitionHandler( shellInit, mShellUnfoldProgressProvider, mFullscreenUnfoldTaskAnimator, mSplitTaskUnfoldAnimator, mTransactionPool, executor, mTransitions ); shellInit.init(); } @Test public void handleRequest_physicalDisplayChange_handlesTransition() { ActivityManager.RunningTaskInfo triggerTaskInfo = new ActivityManager.RunningTaskInfo(); TransitionRequestInfo.DisplayChange displayChange = new TransitionRequestInfo.DisplayChange( Display.DEFAULT_DISPLAY).setPhysicalDisplayChanged(true); TransitionRequestInfo requestInfo = new TransitionRequestInfo(TRANSIT_CHANGE, triggerTaskInfo, /* remoteTransition= */ null, displayChange); WindowContainerTransaction result = mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); assertThat(result).isNotNull(); } @Test public void handleRequest_noPhysicalDisplayChange_doesNotHandleTransition() { ActivityManager.RunningTaskInfo triggerTaskInfo = new ActivityManager.RunningTaskInfo(); TransitionRequestInfo.DisplayChange displayChange = new TransitionRequestInfo.DisplayChange( Display.DEFAULT_DISPLAY).setPhysicalDisplayChanged(false); TransitionRequestInfo requestInfo = new TransitionRequestInfo(TRANSIT_CHANGE, triggerTaskInfo, /* remoteTransition= */ null, displayChange); WindowContainerTransaction result = mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); assertThat(result).isNull(); } @Test public void startAnimation_animationHasNotFinishedYet_doesNotFinishTheTransition() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); verify(finishCallback, never()).onTransitionFinished(any()); } @Test public void startAnimation_animationFinishes_finishesTheTransition() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); mShellUnfoldProgressProvider.onStateChangeStarted(); mShellUnfoldProgressProvider.onStateChangeFinished(); verify(finishCallback).onTransitionFinished(any()); } @Test public void startAnimation_animationIsAlreadyFinished_finishesTheTransition() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); mShellUnfoldProgressProvider.onStateChangeStarted(); mShellUnfoldProgressProvider.onStateChangeFinished(); mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); verify(finishCallback).onTransitionFinished(any()); } @Test public void startAnimationSecondTimeAfterFold_animationAlreadyFinished_finishesTransition() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); // First unfold mShellUnfoldProgressProvider.onFoldStateChanged(/* isFolded= */ false); mShellUnfoldProgressProvider.onStateChangeStarted(); mShellUnfoldProgressProvider.onStateChangeFinished(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); clearInvocations(finishCallback); // Fold mShellUnfoldProgressProvider.onFoldStateChanged(/* isFolded= */ true); // Second unfold mShellUnfoldProgressProvider.onFoldStateChanged(/* isFolded= */ false); mShellUnfoldProgressProvider.onStateChangeStarted(); mShellUnfoldProgressProvider.onStateChangeFinished(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); verify(finishCallback).onTransitionFinished(any()); } private TransitionRequestInfo createUnfoldTransitionRequestInfo() { ActivityManager.RunningTaskInfo triggerTaskInfo = new ActivityManager.RunningTaskInfo(); TransitionRequestInfo.DisplayChange displayChange = new TransitionRequestInfo.DisplayChange( Display.DEFAULT_DISPLAY).setPhysicalDisplayChanged(true); return new TransitionRequestInfo(TRANSIT_CHANGE, triggerTaskInfo, /* remoteTransition= */ null, displayChange); } private static class TestShellUnfoldProgressProvider implements ShellUnfoldProgressProvider, ShellUnfoldProgressProvider.UnfoldListener { private final List<UnfoldListener> mListeners = new ArrayList<>(); @Override public void addListener(Executor executor, UnfoldListener listener) { mListeners.add(listener); } @Override public void onFoldStateChanged(boolean isFolded) { mListeners.forEach(unfoldListener -> unfoldListener.onFoldStateChanged(isFolded)); } @Override public void onStateChangeFinished() { mListeners.forEach(UnfoldListener::onStateChangeFinished); } @Override public void onStateChangeProgress(float progress) { mListeners.forEach(unfoldListener -> unfoldListener.onStateChangeProgress(progress)); } @Override public void onStateChangeStarted() { mListeners.forEach(UnfoldListener::onStateChangeStarted); } } private static class TestTransactionPool extends TransactionPool { @Override public SurfaceControl.Transaction acquire() { return mock(SurfaceControl.Transaction.class); } @Override public void release(SurfaceControl.Transaction t) { } } private static class TestSyncExecutor implements ShellExecutor { @Override public void execute(Runnable runnable) { runnable.run(); } @Override public void executeDelayed(Runnable runnable, long delayMillis) { runnable.run(); } @Override public void removeCallbacks(Runnable runnable) { } @Override public boolean hasCallback(Runnable runnable) { return false; } } } No newline at end of file
packages/SystemUI/src/com/android/systemui/unfold/UnfoldProgressProvider.kt +9 −1 Original line number Diff line number Diff line Loading @@ -17,11 +17,13 @@ package com.android.systemui.unfold import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener import com.android.systemui.unfold.updates.FoldProvider import com.android.wm.shell.unfold.ShellUnfoldProgressProvider import com.android.wm.shell.unfold.ShellUnfoldProgressProvider.UnfoldListener import java.util.concurrent.Executor class UnfoldProgressProvider(private val unfoldProgressProvider: UnfoldTransitionProgressProvider) : class UnfoldProgressProvider(private val unfoldProgressProvider: UnfoldTransitionProgressProvider, private val foldProvider: FoldProvider) : ShellUnfoldProgressProvider { override fun addListener(executor: Executor, listener: UnfoldListener) { Loading @@ -39,5 +41,11 @@ class UnfoldProgressProvider(private val unfoldProgressProvider: UnfoldTransitio executor.execute { listener.onStateChangeFinished() } } }) foldProvider.registerCallback(object : FoldProvider.FoldCallback { override fun onFoldUpdated(isFolded: Boolean) { listener.onFoldStateChanged(isFolded) } }, executor) } }
packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt +4 −2 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ class UnfoldTransitionModule { @Singleton fun provideShellProgressProvider( config: UnfoldTransitionConfig, foldProvider: FoldProvider, provider: Provider<Optional<UnfoldTransitionProgressProvider>>, @Named(UNFOLD_ONLY_PROVIDER) unfoldOnlyProvider: Provider<Optional<UnfoldTransitionProgressProvider>> Loading @@ -135,8 +136,9 @@ class UnfoldTransitionModule { null } return resultingProvider?.get()?.orElse(null)?.let(::UnfoldProgressProvider) ?: ShellUnfoldProgressProvider.NO_PROVIDER return resultingProvider?.get()?.orElse(null)?.let { unfoldProgressProvider -> UnfoldProgressProvider(unfoldProgressProvider, foldProvider) } ?: ShellUnfoldProgressProvider.NO_PROVIDER } @Provides Loading