Fix layer order of wallpaper with counter-rotator in default handler

The layer of wallpaper should always be at the bottom. Otherwise other
windows below it will be invisible during a transition animation.

Also put the same usages of CounterRotator to a new helper class.

Bug: 206094140
Test: adb shell setprop persist.debug.shell_transit 1; reboot
      atest com.android.server.wm.flicker.launch.OpenAppWarmTest
      Or use shell command "am start" to launch a landscape
      activity while wallpaper is visible in portrait.

Change-Id: Ia78450af45185782ce2268393e2a8b6bb8b4c794
This commit is contained in:
Riddle Hsu
2021-12-10 15:45:54 +08:00
parent 6ecdc3894b
commit 320dfd646e
3 changed files with 91 additions and 63 deletions

View File

@@ -28,7 +28,6 @@ import static android.view.WindowManager.TRANSIT_PIP;
import static android.view.WindowManager.transitTypeToString;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.isIndependent;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
@@ -48,7 +47,6 @@ import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
import android.util.ArrayMap;
import android.view.Surface;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
@@ -62,8 +60,8 @@ import androidx.annotation.Nullable;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.transition.CounterRotatorHelper;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.util.CounterRotator;
import java.util.Optional;
@@ -322,35 +320,11 @@ public class PipTransition extends PipTransitionController {
final int displayH = displayRotationChange.getEndAbsBounds().height();
// Counter-rotate all "going-away" things since they are still in the old orientation.
final ArrayMap<WindowContainerToken, CounterRotator> counterRotators = new ArrayMap<>();
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
if (!Transitions.isClosingType(change.getMode())
|| !isIndependent(change, info)
|| change.getParent() == null) {
continue;
}
CounterRotator crot = counterRotators.get(change.getParent());
if (crot == null) {
crot = new CounterRotator();
crot.setup(startTransaction,
info.getChange(change.getParent()).getLeash(),
rotateDelta, displayW, displayH);
if (crot.getSurface() != null) {
// Wallpaper should be placed at the bottom.
final int layer = (change.getFlags() & FLAG_IS_WALLPAPER) == 0
? info.getChanges().size() - i
: -1;
startTransaction.setLayer(crot.getSurface(), layer);
}
counterRotators.put(change.getParent(), crot);
}
crot.addChild(startTransaction, change.getLeash());
}
final CounterRotatorHelper rotator = new CounterRotatorHelper();
rotator.handleClosingChanges(info, startTransaction, rotateDelta, displayW, displayH);
mFinishCallback = (wct, wctCB) -> {
for (int i = 0; i < counterRotators.size(); ++i) {
counterRotators.valueAt(i).cleanUp(info.getRootLeash());
}
rotator.cleanUp();
mPipOrganizer.onExitPipFinished(pipChange.getTaskInfo());
finishCallback.onTransitionFinished(wct, wctCB);
};

View File

@@ -0,0 +1,81 @@
/*
* 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.transition;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import android.util.ArrayMap;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
import android.window.WindowContainerToken;
import androidx.annotation.NonNull;
import com.android.wm.shell.util.CounterRotator;
import java.util.List;
/**
* The helper class that performs counter-rotate for all "going-away" window containers if they are
* still in the old rotation in a transition.
*/
public class CounterRotatorHelper {
private final ArrayMap<WindowContainerToken, CounterRotator> mRotatorMap = new ArrayMap<>();
private SurfaceControl mRootLeash;
/** Puts the surface controls of closing changes to counter-rotated surfaces. */
public void handleClosingChanges(@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
int rotateDelta, int displayW, int displayH) {
mRootLeash = info.getRootLeash();
final List<TransitionInfo.Change> changes = info.getChanges();
final int numChanges = changes.size();
for (int i = numChanges - 1; i >= 0; --i) {
final TransitionInfo.Change change = changes.get(i);
final WindowContainerToken parent = change.getParent();
if (!Transitions.isClosingType(change.getMode())
|| !TransitionInfo.isIndependent(change, info) || parent == null) {
continue;
}
CounterRotator crot = mRotatorMap.get(parent);
if (crot == null) {
crot = new CounterRotator();
crot.setup(startTransaction, info.getChange(parent).getLeash(), rotateDelta,
displayW, displayH);
final SurfaceControl rotatorSc = crot.getSurface();
if (rotatorSc != null) {
// Wallpaper should be placed at the bottom.
final int layer = (change.getFlags() & FLAG_IS_WALLPAPER) == 0
? numChanges - i
: -1;
startTransaction.setLayer(rotatorSc, layer);
}
mRotatorMap.put(parent, crot);
}
crot.addChild(startTransaction, change.getLeash());
}
}
/** Restores to the original state, i.e. reparent back to transition root. */
public void cleanUp() {
for (int i = mRotatorMap.size() - 1; i >= 0; --i) {
mRotatorMap.valueAt(i).cleanUp(mRootLeash);
}
mRotatorMap.clear();
}
}

View File

@@ -43,7 +43,6 @@ import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
import static android.window.TransitionInfo.isIndependent;
import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_CLOSE;
import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_INTRA_CLOSE;
@@ -78,7 +77,6 @@ import android.view.animation.Transformation;
import android.window.TransitionInfo;
import android.window.TransitionMetrics;
import android.window.TransitionRequestInfo;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import com.android.internal.R;
@@ -92,7 +90,6 @@ import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.util.CounterRotator;
import java.util.ArrayList;
@@ -280,16 +277,12 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
final ArrayList<Animator> animations = new ArrayList<>();
mAnimations.put(transition, animations);
final ArrayMap<WindowContainerToken, CounterRotator> counterRotators = new ArrayMap<>();
final CounterRotatorHelper rotator = new CounterRotatorHelper();
final Runnable onAnimFinish = () -> {
if (!animations.isEmpty()) return;
for (int i = 0; i < counterRotators.size(); ++i) {
counterRotators.valueAt(i).cleanUp(info.getRootLeash());
}
counterRotators.clear();
rotator.cleanUp();
if (mRotationAnimation != null) {
mRotationAnimation.kill();
mRotationAnimation = null;
@@ -322,29 +315,9 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
continue;
}
} else {
// opening/closing an app into a new orientation. Counter-rotate all
// "going-away" things since they are still in the old orientation.
for (int j = info.getChanges().size() - 1; j >= 0; --j) {
final TransitionInfo.Change innerChange = info.getChanges().get(j);
if (!Transitions.isClosingType(innerChange.getMode())
|| !isIndependent(innerChange, info)
|| innerChange.getParent() == null) {
continue;
}
CounterRotator crot = counterRotators.get(innerChange.getParent());
if (crot == null) {
crot = new CounterRotator();
crot.setup(startTransaction,
info.getChange(innerChange.getParent()).getLeash(),
rotateDelta, displayW, displayH);
if (crot.getSurface() != null) {
int layer = info.getChanges().size() - j;
startTransaction.setLayer(crot.getSurface(), layer);
}
counterRotators.put(innerChange.getParent(), crot);
}
crot.addChild(startTransaction, innerChange.getLeash());
}
// Opening/closing an app into a new orientation.
rotator.handleClosingChanges(info, startTransaction, rotateDelta,
displayW, displayH);
}
}