Merge "Migrate unfold animation to Shell transitions [Part 1]" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a830367d97
@@ -67,6 +67,7 @@ public final class TransitionRequestInfo implements Parcelable {
|
|||||||
@Nullable private Rect mEndAbsBounds = null;
|
@Nullable private Rect mEndAbsBounds = null;
|
||||||
private int mStartRotation = WindowConfiguration.ROTATION_UNDEFINED;
|
private int mStartRotation = WindowConfiguration.ROTATION_UNDEFINED;
|
||||||
private int mEndRotation = WindowConfiguration.ROTATION_UNDEFINED;
|
private int mEndRotation = WindowConfiguration.ROTATION_UNDEFINED;
|
||||||
|
private boolean mPhysicalDisplayChanged = false;
|
||||||
|
|
||||||
/** Create empty display-change. */
|
/** Create empty display-change. */
|
||||||
public DisplayChange(int displayId) {
|
public DisplayChange(int displayId) {
|
||||||
@@ -120,6 +121,11 @@ public final class TransitionRequestInfo implements Parcelable {
|
|||||||
return mEndRotation;
|
return mEndRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DataClass.Generated.Member
|
||||||
|
public boolean isPhysicalDisplayChanged() {
|
||||||
|
return mPhysicalDisplayChanged;
|
||||||
|
}
|
||||||
|
|
||||||
@DataClass.Generated.Member
|
@DataClass.Generated.Member
|
||||||
public @android.annotation.NonNull DisplayChange setStartAbsBounds(@android.annotation.NonNull Rect value) {
|
public @android.annotation.NonNull DisplayChange setStartAbsBounds(@android.annotation.NonNull Rect value) {
|
||||||
mStartAbsBounds = value;
|
mStartAbsBounds = value;
|
||||||
@@ -144,6 +150,12 @@ public final class TransitionRequestInfo implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DataClass.Generated.Member
|
||||||
|
public @android.annotation.NonNull DisplayChange setPhysicalDisplayChanged( boolean value) {
|
||||||
|
mPhysicalDisplayChanged = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@DataClass.Generated.Member
|
@DataClass.Generated.Member
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@@ -155,7 +167,8 @@ public final class TransitionRequestInfo implements Parcelable {
|
|||||||
"startAbsBounds = " + mStartAbsBounds + ", " +
|
"startAbsBounds = " + mStartAbsBounds + ", " +
|
||||||
"endAbsBounds = " + mEndAbsBounds + ", " +
|
"endAbsBounds = " + mEndAbsBounds + ", " +
|
||||||
"startRotation = " + mStartRotation + ", " +
|
"startRotation = " + mStartRotation + ", " +
|
||||||
"endRotation = " + mEndRotation +
|
"endRotation = " + mEndRotation + ", " +
|
||||||
|
"physicalDisplayChanged = " + mPhysicalDisplayChanged +
|
||||||
" }";
|
" }";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,6 +179,7 @@ public final class TransitionRequestInfo implements Parcelable {
|
|||||||
// void parcelFieldName(Parcel dest, int flags) { ... }
|
// void parcelFieldName(Parcel dest, int flags) { ... }
|
||||||
|
|
||||||
byte flg = 0;
|
byte flg = 0;
|
||||||
|
if (mPhysicalDisplayChanged) flg |= 0x20;
|
||||||
if (mStartAbsBounds != null) flg |= 0x2;
|
if (mStartAbsBounds != null) flg |= 0x2;
|
||||||
if (mEndAbsBounds != null) flg |= 0x4;
|
if (mEndAbsBounds != null) flg |= 0x4;
|
||||||
dest.writeByte(flg);
|
dest.writeByte(flg);
|
||||||
@@ -188,6 +202,7 @@ public final class TransitionRequestInfo implements Parcelable {
|
|||||||
// static FieldType unparcelFieldName(Parcel in) { ... }
|
// static FieldType unparcelFieldName(Parcel in) { ... }
|
||||||
|
|
||||||
byte flg = in.readByte();
|
byte flg = in.readByte();
|
||||||
|
boolean physicalDisplayChanged = (flg & 0x20) != 0;
|
||||||
int displayId = in.readInt();
|
int displayId = in.readInt();
|
||||||
Rect startAbsBounds = (flg & 0x2) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR);
|
Rect startAbsBounds = (flg & 0x2) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR);
|
||||||
Rect endAbsBounds = (flg & 0x4) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR);
|
Rect endAbsBounds = (flg & 0x4) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR);
|
||||||
@@ -199,6 +214,7 @@ public final class TransitionRequestInfo implements Parcelable {
|
|||||||
this.mEndAbsBounds = endAbsBounds;
|
this.mEndAbsBounds = endAbsBounds;
|
||||||
this.mStartRotation = startRotation;
|
this.mStartRotation = startRotation;
|
||||||
this.mEndRotation = endRotation;
|
this.mEndRotation = endRotation;
|
||||||
|
this.mPhysicalDisplayChanged = physicalDisplayChanged;
|
||||||
|
|
||||||
// onConstructed(); // You can define this method to get a callback
|
// onConstructed(); // You can define this method to get a callback
|
||||||
}
|
}
|
||||||
@@ -218,10 +234,10 @@ public final class TransitionRequestInfo implements Parcelable {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@DataClass.Generated(
|
@DataClass.Generated(
|
||||||
time = 1639445520915L,
|
time = 1648141181315L,
|
||||||
codegenVersion = "1.0.23",
|
codegenVersion = "1.0.23",
|
||||||
sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java",
|
sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java",
|
||||||
inputSignatures = "private final int mDisplayId\nprivate @android.annotation.Nullable android.graphics.Rect mStartAbsBounds\nprivate @android.annotation.Nullable android.graphics.Rect mEndAbsBounds\nprivate int mStartRotation\nprivate int mEndRotation\nclass DisplayChange extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genBuilder=false, genConstructor=false)")
|
inputSignatures = "private final int mDisplayId\nprivate @android.annotation.Nullable android.graphics.Rect mStartAbsBounds\nprivate @android.annotation.Nullable android.graphics.Rect mEndAbsBounds\nprivate int mStartRotation\nprivate int mEndRotation\nprivate boolean mPhysicalDisplayChanged\nclass DisplayChange extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genBuilder=false, genConstructor=false)")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
private void __metadata() {}
|
private void __metadata() {}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import com.android.wm.shell.recents.RecentTasksController;
|
|||||||
import com.android.wm.shell.splitscreen.SplitScreenController;
|
import com.android.wm.shell.splitscreen.SplitScreenController;
|
||||||
import com.android.wm.shell.startingsurface.StartingWindowController;
|
import com.android.wm.shell.startingsurface.StartingWindowController;
|
||||||
import com.android.wm.shell.transition.Transitions;
|
import com.android.wm.shell.transition.Transitions;
|
||||||
|
import com.android.wm.shell.unfold.UnfoldTransitionHandler;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ public class ShellInitImpl {
|
|||||||
private final Optional<PipTouchHandler> mPipTouchHandlerOptional;
|
private final Optional<PipTouchHandler> mPipTouchHandlerOptional;
|
||||||
private final FullscreenTaskListener mFullscreenTaskListener;
|
private final FullscreenTaskListener mFullscreenTaskListener;
|
||||||
private final Optional<FullscreenUnfoldController> mFullscreenUnfoldController;
|
private final Optional<FullscreenUnfoldController> mFullscreenUnfoldController;
|
||||||
|
private final Optional<UnfoldTransitionHandler> mUnfoldTransitionHandler;
|
||||||
private final Optional<FreeformTaskListener> mFreeformTaskListenerOptional;
|
private final Optional<FreeformTaskListener> mFreeformTaskListenerOptional;
|
||||||
private final ShellExecutor mMainExecutor;
|
private final ShellExecutor mMainExecutor;
|
||||||
private final Transitions mTransitions;
|
private final Transitions mTransitions;
|
||||||
@@ -77,6 +79,7 @@ public class ShellInitImpl {
|
|||||||
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
||||||
FullscreenTaskListener fullscreenTaskListener,
|
FullscreenTaskListener fullscreenTaskListener,
|
||||||
Optional<FullscreenUnfoldController> fullscreenUnfoldTransitionController,
|
Optional<FullscreenUnfoldController> fullscreenUnfoldTransitionController,
|
||||||
|
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
|
||||||
Optional<FreeformTaskListener> freeformTaskListenerOptional,
|
Optional<FreeformTaskListener> freeformTaskListenerOptional,
|
||||||
Optional<RecentTasksController> recentTasks,
|
Optional<RecentTasksController> recentTasks,
|
||||||
Transitions transitions,
|
Transitions transitions,
|
||||||
@@ -94,6 +97,7 @@ public class ShellInitImpl {
|
|||||||
mFullscreenTaskListener = fullscreenTaskListener;
|
mFullscreenTaskListener = fullscreenTaskListener;
|
||||||
mPipTouchHandlerOptional = pipTouchHandlerOptional;
|
mPipTouchHandlerOptional = pipTouchHandlerOptional;
|
||||||
mFullscreenUnfoldController = fullscreenUnfoldTransitionController;
|
mFullscreenUnfoldController = fullscreenUnfoldTransitionController;
|
||||||
|
mUnfoldTransitionHandler = unfoldTransitionHandler;
|
||||||
mFreeformTaskListenerOptional = freeformTaskListenerOptional;
|
mFreeformTaskListenerOptional = freeformTaskListenerOptional;
|
||||||
mRecentTasks = recentTasks;
|
mRecentTasks = recentTasks;
|
||||||
mTransitions = transitions;
|
mTransitions = transitions;
|
||||||
@@ -126,6 +130,7 @@ public class ShellInitImpl {
|
|||||||
|
|
||||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||||
mTransitions.register(mShellTaskOrganizer);
|
mTransitions.register(mShellTaskOrganizer);
|
||||||
|
mUnfoldTransitionHandler.ifPresent(UnfoldTransitionHandler::init);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(b/181599115): This should really be the pip controller, but until we can provide the
|
// TODO(b/181599115): This should really be the pip controller, but until we can provide the
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelperController;
|
|||||||
import com.android.wm.shell.transition.ShellTransitions;
|
import com.android.wm.shell.transition.ShellTransitions;
|
||||||
import com.android.wm.shell.transition.Transitions;
|
import com.android.wm.shell.transition.Transitions;
|
||||||
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
|
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
|
||||||
|
import com.android.wm.shell.unfold.UnfoldTransitionHandler;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -327,6 +328,21 @@ public abstract class WMShellBaseModule {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WMSingleton
|
||||||
|
@Provides
|
||||||
|
static Optional<UnfoldTransitionHandler> provideUnfoldTransitionHandler(
|
||||||
|
Optional<ShellUnfoldProgressProvider> progressProvider,
|
||||||
|
TransactionPool transactionPool,
|
||||||
|
Transitions transitions,
|
||||||
|
@ShellMainThread ShellExecutor executor) {
|
||||||
|
if (progressProvider.isPresent()) {
|
||||||
|
return Optional.of(
|
||||||
|
new UnfoldTransitionHandler(progressProvider.get(), transactionPool, executor,
|
||||||
|
transitions));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Freeform (optional feature)
|
// Freeform (optional feature)
|
||||||
//
|
//
|
||||||
@@ -660,6 +676,7 @@ public abstract class WMShellBaseModule {
|
|||||||
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
||||||
FullscreenTaskListener fullscreenTaskListener,
|
FullscreenTaskListener fullscreenTaskListener,
|
||||||
Optional<FullscreenUnfoldController> appUnfoldTransitionController,
|
Optional<FullscreenUnfoldController> appUnfoldTransitionController,
|
||||||
|
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
|
||||||
Optional<FreeformTaskListener> freeformTaskListener,
|
Optional<FreeformTaskListener> freeformTaskListener,
|
||||||
Optional<RecentTasksController> recentTasksOptional,
|
Optional<RecentTasksController> recentTasksOptional,
|
||||||
Transitions transitions,
|
Transitions transitions,
|
||||||
@@ -677,6 +694,7 @@ public abstract class WMShellBaseModule {
|
|||||||
pipTouchHandlerOptional,
|
pipTouchHandlerOptional,
|
||||||
fullscreenTaskListener,
|
fullscreenTaskListener,
|
||||||
appUnfoldTransitionController,
|
appUnfoldTransitionController,
|
||||||
|
unfoldTransitionHandler,
|
||||||
freeformTaskListener,
|
freeformTaskListener,
|
||||||
recentTasksOptional,
|
recentTasksOptional,
|
||||||
transitions,
|
transitions,
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||||
|
import static android.view.WindowManager.TRANSIT_CHANGE;
|
||||||
|
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.view.SurfaceControl;
|
||||||
|
import android.window.TransitionInfo;
|
||||||
|
import android.window.TransitionRequestInfo;
|
||||||
|
import android.window.WindowContainerTransaction;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.wm.shell.common.TransactionPool;
|
||||||
|
import com.android.wm.shell.transition.Transitions;
|
||||||
|
import com.android.wm.shell.transition.Transitions.TransitionFinishCallback;
|
||||||
|
import com.android.wm.shell.transition.Transitions.TransitionHandler;
|
||||||
|
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider.UnfoldListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListener {
|
||||||
|
|
||||||
|
private final ShellUnfoldProgressProvider mUnfoldProgressProvider;
|
||||||
|
private final Transitions mTransitions;
|
||||||
|
private final Executor mExecutor;
|
||||||
|
private final TransactionPool mTransactionPool;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private TransitionFinishCallback mFinishCallback;
|
||||||
|
@Nullable
|
||||||
|
private IBinder mTransition;
|
||||||
|
|
||||||
|
private final List<TransitionInfo.Change> mAnimatedFullscreenTasks = new ArrayList<>();
|
||||||
|
|
||||||
|
public UnfoldTransitionHandler(ShellUnfoldProgressProvider unfoldProgressProvider,
|
||||||
|
TransactionPool transactionPool, Executor executor, Transitions transitions) {
|
||||||
|
mUnfoldProgressProvider = unfoldProgressProvider;
|
||||||
|
mTransactionPool = transactionPool;
|
||||||
|
mExecutor = executor;
|
||||||
|
mTransitions = transitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
mTransitions.addHandler(this);
|
||||||
|
mUnfoldProgressProvider.addListener(mExecutor, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
|
||||||
|
@NonNull SurfaceControl.Transaction startTransaction,
|
||||||
|
@NonNull SurfaceControl.Transaction finishTransaction,
|
||||||
|
@NonNull TransitionFinishCallback finishCallback) {
|
||||||
|
|
||||||
|
if (transition != mTransition) return false;
|
||||||
|
|
||||||
|
startTransaction.apply();
|
||||||
|
|
||||||
|
mAnimatedFullscreenTasks.clear();
|
||||||
|
info.getChanges().forEach(change -> {
|
||||||
|
final boolean allowedToAnimate = change.getTaskInfo() != null
|
||||||
|
&& change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_FULLSCREEN
|
||||||
|
&& change.getTaskInfo().getActivityType() != ACTIVITY_TYPE_HOME
|
||||||
|
&& change.getMode() == TRANSIT_CHANGE;
|
||||||
|
|
||||||
|
if (allowedToAnimate) {
|
||||||
|
mAnimatedFullscreenTasks.add(change);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mFinishCallback = finishCallback;
|
||||||
|
mTransition = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStateChangeProgress(float progress) {
|
||||||
|
mAnimatedFullscreenTasks.forEach(change -> {
|
||||||
|
final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
|
||||||
|
|
||||||
|
// TODO: this is a placeholder animation, replace with a spec version in the next CLs
|
||||||
|
final float testScale = 0.8f + 0.2f * progress;
|
||||||
|
transaction.setScale(change.getLeash(), testScale, testScale);
|
||||||
|
|
||||||
|
transaction.apply();
|
||||||
|
mTransactionPool.release(transaction);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStateChangeFinished() {
|
||||||
|
if (mFinishCallback != null) {
|
||||||
|
mFinishCallback.onTransitionFinished(null, null);
|
||||||
|
mFinishCallback = null;
|
||||||
|
mAnimatedFullscreenTasks.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
|
||||||
|
@NonNull TransitionRequestInfo request) {
|
||||||
|
if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null
|
||||||
|
&& request.getDisplayChange().isPhysicalDisplayChanged()) {
|
||||||
|
mTransition = transition;
|
||||||
|
return new WindowContainerTransaction();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -551,6 +551,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
final FixedRotationTransitionListener mFixedRotationTransitionListener =
|
final FixedRotationTransitionListener mFixedRotationTransitionListener =
|
||||||
new FixedRotationTransitionListener();
|
new FixedRotationTransitionListener();
|
||||||
|
|
||||||
|
private PhysicalDisplaySwitchTransitionLauncher mDisplaySwitchTransitionLauncher;
|
||||||
|
|
||||||
/** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
|
/** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
|
||||||
final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
|
final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
|
||||||
|
|
||||||
@@ -1043,6 +1045,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
mAppTransitionController = new AppTransitionController(mWmService, this);
|
mAppTransitionController = new AppTransitionController(mWmService, this);
|
||||||
mTransitionController.registerLegacyListener(mFixedRotationTransitionListener);
|
mTransitionController.registerLegacyListener(mFixedRotationTransitionListener);
|
||||||
mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this);
|
mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this);
|
||||||
|
mDisplaySwitchTransitionLauncher = new PhysicalDisplaySwitchTransitionLauncher(this,
|
||||||
|
mTransitionController);
|
||||||
|
|
||||||
final InputChannel inputChannel = mWmService.mInputManager.monitorInput(
|
final InputChannel inputChannel = mWmService.mInputManager.monitorInput(
|
||||||
"PointerEventDispatcher" + mDisplayId, mDisplayId);
|
"PointerEventDispatcher" + mDisplayId, mDisplayId);
|
||||||
@@ -2751,6 +2755,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
// metrics are updated as rotation settings might depend on them
|
// metrics are updated as rotation settings might depend on them
|
||||||
mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this,
|
mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this,
|
||||||
/* includeRotationSettings */ false);
|
/* includeRotationSettings */ false);
|
||||||
|
mDisplaySwitchTransitionLauncher.requestDisplaySwitchTransitionIfNeeded(mDisplayId,
|
||||||
|
mInitialDisplayWidth, mInitialDisplayHeight, newWidth, newHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is an override set for base values - use it, otherwise use new values.
|
// If there is an override set for base values - use it, otherwise use new values.
|
||||||
@@ -2779,6 +2785,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
mInitialRoundedCorners = newRoundedCorners;
|
mInitialRoundedCorners = newRoundedCorners;
|
||||||
mCurrentUniqueDisplayId = newUniqueId;
|
mCurrentUniqueDisplayId = newUniqueId;
|
||||||
reconfigureDisplayLocked();
|
reconfigureDisplayLocked();
|
||||||
|
|
||||||
|
if (physicalDisplayChanged) {
|
||||||
|
mDisplaySwitchTransitionLauncher.onDisplayUpdated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3105,6 +3115,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
mTransitionController.unregisterLegacyListener(mFixedRotationTransitionListener);
|
mTransitionController.unregisterLegacyListener(mFixedRotationTransitionListener);
|
||||||
handleAnimatingStoppedAndTransition();
|
handleAnimatingStoppedAndTransition();
|
||||||
mWmService.stopFreezingDisplayLocked();
|
mWmService.stopFreezingDisplayLocked();
|
||||||
|
mDisplaySwitchTransitionLauncher.destroy();
|
||||||
super.removeImmediately();
|
super.removeImmediately();
|
||||||
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
|
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
|
||||||
mPointerEventDispatcher.dispose();
|
mPointerEventDispatcher.dispose();
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.server.wm;
|
||||||
|
|
||||||
|
import static android.view.WindowManager.TRANSIT_CHANGE;
|
||||||
|
|
||||||
|
import static com.android.internal.R.bool.config_unfoldTransitionEnabled;
|
||||||
|
import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;
|
||||||
|
|
||||||
|
import android.animation.ValueAnimator;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.hardware.devicestate.DeviceStateManager;
|
||||||
|
import android.os.HandlerExecutor;
|
||||||
|
import android.window.TransitionRequestInfo;
|
||||||
|
|
||||||
|
public class PhysicalDisplaySwitchTransitionLauncher {
|
||||||
|
|
||||||
|
private final DisplayContent mDisplayContent;
|
||||||
|
private final DeviceStateManager mDeviceStateManager;
|
||||||
|
private final Context mContext;
|
||||||
|
private final TransitionController mTransitionController;
|
||||||
|
|
||||||
|
private DeviceStateListener mDeviceStateListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If on a foldable device represents whether the device is folded or not
|
||||||
|
*/
|
||||||
|
private boolean mIsFolded;
|
||||||
|
private Transition mTransition;
|
||||||
|
|
||||||
|
public PhysicalDisplaySwitchTransitionLauncher(DisplayContent displayContent,
|
||||||
|
TransitionController transitionController) {
|
||||||
|
mDisplayContent = displayContent;
|
||||||
|
mContext = mDisplayContent.mWmService.mContext;
|
||||||
|
mTransitionController = transitionController;
|
||||||
|
|
||||||
|
mDeviceStateManager = mContext.getSystemService(DeviceStateManager.class);
|
||||||
|
|
||||||
|
if (mDeviceStateManager != null) {
|
||||||
|
mDeviceStateListener = new DeviceStateListener(mContext);
|
||||||
|
mDeviceStateManager
|
||||||
|
.registerCallback(new HandlerExecutor(mDisplayContent.mWmService.mH),
|
||||||
|
mDeviceStateListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
if (mDeviceStateManager != null) {
|
||||||
|
mDeviceStateManager.unregisterCallback(mDeviceStateListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests to start a transition for the physical display switch
|
||||||
|
*/
|
||||||
|
public void requestDisplaySwitchTransitionIfNeeded(int displayId, int oldDisplayWidth,
|
||||||
|
int oldDisplayHeight, int newDisplayWidth, int newDisplayHeight) {
|
||||||
|
if (!mTransitionController.isShellTransitionsEnabled()) return;
|
||||||
|
if (!mDisplayContent.getLastHasContent()) return;
|
||||||
|
|
||||||
|
boolean shouldRequestUnfoldTransition = !mIsFolded
|
||||||
|
&& mContext.getResources().getBoolean(config_unfoldTransitionEnabled)
|
||||||
|
&& ValueAnimator.areAnimatorsEnabled();
|
||||||
|
|
||||||
|
if (!shouldRequestUnfoldTransition) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final TransitionRequestInfo.DisplayChange displayChange =
|
||||||
|
new TransitionRequestInfo.DisplayChange(displayId);
|
||||||
|
|
||||||
|
final Rect startAbsBounds = new Rect(0, 0, oldDisplayWidth, oldDisplayHeight);
|
||||||
|
displayChange.setStartAbsBounds(startAbsBounds);
|
||||||
|
final Rect endAbsBounds = new Rect(0, 0, newDisplayWidth, newDisplayHeight);
|
||||||
|
displayChange.setEndAbsBounds(endAbsBounds);
|
||||||
|
displayChange.setPhysicalDisplayChanged(true);
|
||||||
|
|
||||||
|
final Transition t = mTransitionController.requestTransitionIfNeeded(TRANSIT_CHANGE,
|
||||||
|
0 /* flags */,
|
||||||
|
mDisplayContent, mDisplayContent, null /* remoteTransition */,
|
||||||
|
displayChange);
|
||||||
|
|
||||||
|
if (t != null) {
|
||||||
|
mDisplayContent.mAtmService.startLaunchPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY);
|
||||||
|
mTransitionController.collectForDisplayChange(mDisplayContent, t);
|
||||||
|
mTransition = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDisplayUpdated() {
|
||||||
|
if (mTransition != null) {
|
||||||
|
mTransition.setAllReady();
|
||||||
|
mTransition = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeviceStateListener extends DeviceStateManager.FoldStateListener {
|
||||||
|
|
||||||
|
DeviceStateListener(Context context) {
|
||||||
|
super(context, newIsFolded -> mIsFolded = newIsFolded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,6 +52,7 @@ import android.content.IntentFilter;
|
|||||||
import android.content.pm.IPackageManager;
|
import android.content.pm.IPackageManager;
|
||||||
import android.content.pm.PackageManagerInternal;
|
import android.content.pm.PackageManagerInternal;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
|
import android.hardware.devicestate.DeviceStateManager;
|
||||||
import android.hardware.display.DisplayManager;
|
import android.hardware.display.DisplayManager;
|
||||||
import android.hardware.display.DisplayManagerInternal;
|
import android.hardware.display.DisplayManagerInternal;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@@ -229,6 +230,10 @@ public class SystemServicesTestRule implements TestRule {
|
|||||||
final AppOpsManager aom = mock(AppOpsManager.class);
|
final AppOpsManager aom = mock(AppOpsManager.class);
|
||||||
doReturn(aom).when(mContext).getSystemService(eq(Context.APP_OPS_SERVICE));
|
doReturn(aom).when(mContext).getSystemService(eq(Context.APP_OPS_SERVICE));
|
||||||
|
|
||||||
|
// DeviceStateManager
|
||||||
|
final DeviceStateManager dsm = mock(DeviceStateManager.class);
|
||||||
|
doReturn(dsm).when(mContext).getSystemService(eq(Context.DEVICE_STATE_SERVICE));
|
||||||
|
|
||||||
// Prevent "WakeLock finalized while still held: SCREEN_FROZEN".
|
// Prevent "WakeLock finalized while still held: SCREEN_FROZEN".
|
||||||
final PowerManager pm = mock(PowerManager.class);
|
final PowerManager pm = mock(PowerManager.class);
|
||||||
doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE));
|
doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE));
|
||||||
|
|||||||
Reference in New Issue
Block a user