Reduce unnecessary collecting for wallpaper with shell transition

The adjustWallpaperWindows is a heavy operation (including assigning
layer), and it has no direct relation with ensure visibility of task.
Especially if there are several tasks, it may increase overhead with
dozens milliseconds in a transition. The original problem should be
fixed by collecting wallpaper token instead of window state.
(Because Transition only recognizes wallpaper by token)

Also
 - Reduce re-assigning layer if visibility is not changed.
 - Collect wallpaper token only when the requested visibility is
   different, that reduces lots of checking transition participants.
 - Update wallpaper visibility before playing transition, which is
   similar to legacy adjustWallpaperWindowsForAppTransitionIfNeeded.

Bug: 206487939
Bug: 187461719
Test: WallpaperControllerTests#testWallpaperTokenVisibility
Test: adb shell setprop  persist.debug.shell_transit 1; reboot
      Check 3 cases:
      1. Rotate display -> latency reduced.
      2. Launch app in different orientation from home
         -> wallpaper is not rotated.
      3. Launch an opaque app from home and it launches a
         non-opaque app immediately -> wallpaper should not flash.
Change-Id: I1819f6aad23eb103f97c9d33bc2ad68db0e6c4ed
This commit is contained in:
Riddle Hsu
2021-11-19 20:28:17 +08:00
parent 07d5ae6a67
commit f649375c43
5 changed files with 57 additions and 45 deletions

View File

@@ -139,9 +139,6 @@ class EnsureActivitiesVisibleHelper {
setActivityVisibilityState(child.asActivityRecord(), starting, resumeTopActivity); setActivityVisibilityState(child.asActivityRecord(), starting, resumeTopActivity);
} }
} }
if (mTaskFragment.mTransitionController.isShellTransitionsEnabled()) {
mTaskFragment.getDisplayContent().mWallpaperController.adjustWallpaperWindows();
}
} }
private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting, private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,

View File

@@ -244,11 +244,11 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
} }
mParticipants.add(wc); mParticipants.add(wc);
if (info.mShowWallpaper) { if (info.mShowWallpaper) {
// Collect the wallpaper so it is part of the sync set. // Collect the wallpaper token (for isWallpaper(wc)) so it is part of the sync set.
final WindowContainer wallpaper = final WindowState wallpaper =
wc.getDisplayContent().mWallpaperController.getTopVisibleWallpaper(); wc.getDisplayContent().mWallpaperController.getTopVisibleWallpaper();
if (wallpaper != null) { if (wallpaper != null) {
collect(wallpaper); collect(wallpaper.mToken);
} }
} }
} }
@@ -495,25 +495,35 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
Slog.e(TAG, "Unexpected Sync ID " + syncId + ". Expected " + mSyncId); Slog.e(TAG, "Unexpected Sync ID " + syncId + ". Expected " + mSyncId);
return; return;
} }
int displayId = DEFAULT_DISPLAY; boolean hasWallpaper = false;
for (WindowContainer container : mParticipants) { DisplayContent dc = null;
if (container.mDisplayContent == null) continue; for (int i = mParticipants.size() - 1; i >= 0; --i) {
displayId = container.mDisplayContent.getDisplayId(); final WindowContainer<?> wc = mParticipants.valueAt(i);
if (dc == null && wc.mDisplayContent != null) {
dc = wc.mDisplayContent;
} }
if (!hasWallpaper && isWallpaper(wc)) {
hasWallpaper = true;
}
}
if (dc == null) dc = mController.mAtm.mRootWindowContainer.getDefaultDisplay();
if (mState == STATE_ABORT) { if (mState == STATE_ABORT) {
mController.abort(this); mController.abort(this);
mController.mAtm.mRootWindowContainer.getDisplayContent(displayId) dc.getPendingTransaction().merge(transaction);
.getPendingTransaction().merge(transaction);
mSyncId = -1; mSyncId = -1;
mOverrideOptions = null; mOverrideOptions = null;
return; return;
} }
// Ensure that wallpaper visibility is updated with the latest wallpaper target.
if (hasWallpaper) {
dc.mWallpaperController.adjustWallpaperWindows();
}
mState = STATE_PLAYING; mState = STATE_PLAYING;
mController.moveToPlaying(this); mController.moveToPlaying(this);
if (mController.mAtm.mTaskSupervisor.getKeyguardController().isKeyguardLocked(displayId)) { if (dc.isKeyguardLocked()) {
mFlags |= TRANSIT_FLAG_KEYGUARD_LOCKED; mFlags |= TRANSIT_FLAG_KEYGUARD_LOCKED;
} }
@@ -523,9 +533,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
info.setAnimationOptions(mOverrideOptions); info.setAnimationOptions(mOverrideOptions);
// TODO(b/188669821): Move to animation impl in shell. // TODO(b/188669821): Move to animation impl in shell.
handleLegacyRecentsStartBehavior(displayId, info); handleLegacyRecentsStartBehavior(dc, info);
handleNonAppWindowsInTransition(displayId, mType, mFlags); handleNonAppWindowsInTransition(dc, mType, mFlags);
reportStartReasonsToLogger(); reportStartReasonsToLogger();
@@ -627,14 +637,11 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
} }
/** @see RecentsAnimationController#attachNavigationBarToApp */ /** @see RecentsAnimationController#attachNavigationBarToApp */
private void handleLegacyRecentsStartBehavior(int displayId, TransitionInfo info) { private void handleLegacyRecentsStartBehavior(DisplayContent dc, TransitionInfo info) {
if ((mFlags & TRANSIT_FLAG_IS_RECENTS) == 0) { if ((mFlags & TRANSIT_FLAG_IS_RECENTS) == 0) {
return; return;
} }
final DisplayContent dc = mRecentsDisplayId = dc.mDisplayId;
mController.mAtm.mRootWindowContainer.getDisplayContent(displayId);
if (dc == null) return;
mRecentsDisplayId = displayId;
// Recents has an input-consumer to grab input from the "live tile" app. Set that up here // Recents has an input-consumer to grab input from the "live tile" app. Set that up here
final InputConsumerImpl recentsAnimationInputConsumer = final InputConsumerImpl recentsAnimationInputConsumer =
@@ -679,7 +686,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
// Find the top-most non-home, closing app. // Find the top-most non-home, closing app.
for (int i = 0; i < info.getChanges().size(); ++i) { for (int i = 0; i < info.getChanges().size(); ++i) {
final TransitionInfo.Change c = info.getChanges().get(i); final TransitionInfo.Change c = info.getChanges().get(i);
if (c.getTaskInfo() == null || c.getTaskInfo().displayId != displayId if (c.getTaskInfo() == null || c.getTaskInfo().displayId != mRecentsDisplayId
|| c.getTaskInfo().getActivityType() != ACTIVITY_TYPE_STANDARD || c.getTaskInfo().getActivityType() != ACTIVITY_TYPE_STANDARD
|| !(c.getMode() == TRANSIT_CLOSE || c.getMode() == TRANSIT_TO_BACK)) { || !(c.getMode() == TRANSIT_CLOSE || c.getMode() == TRANSIT_TO_BACK)) {
continue; continue;
@@ -710,7 +717,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
t.setLayer(navSurfaceControl, Integer.MAX_VALUE); t.setLayer(navSurfaceControl, Integer.MAX_VALUE);
} }
if (mController.mStatusBar != null) { if (mController.mStatusBar != null) {
mController.mStatusBar.setNavigationBarLumaSamplingEnabled(displayId, false); mController.mStatusBar.setNavigationBarLumaSamplingEnabled(mRecentsDisplayId, false);
} }
} }
@@ -760,13 +767,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
} }
} }
private void handleNonAppWindowsInTransition(int displayId, private void handleNonAppWindowsInTransition(@NonNull DisplayContent dc,
@TransitionType int transit, @TransitionFlags int flags) { @TransitionType int transit, @TransitionFlags int flags) {
final DisplayContent dc =
mController.mAtm.mRootWindowContainer.getDisplayContent(displayId);
if (dc == null) {
return;
}
if ((transit == TRANSIT_KEYGUARD_GOING_AWAY if ((transit == TRANSIT_KEYGUARD_GOING_AWAY
|| (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) || (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0)
&& !WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation) { && !WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation) {

View File

@@ -611,8 +611,9 @@ class WallpaperController {
private void updateWallpaperTokens(boolean visible) { private void updateWallpaperTokens(boolean visible) {
for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) { for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx); final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
token.updateWallpaperWindows(visible); if (token.updateWallpaperWindows(visible)) {
token.getDisplayContent().assignWindowLayers(false); token.mDisplayContent.assignWindowLayers(false /* setLayoutNeeded */);
}
} }
} }

View File

@@ -104,18 +104,21 @@ class WallpaperWindowToken extends WindowToken {
} }
} }
void updateWallpaperWindows(boolean visible) { /** Returns {@code true} if visibility is changed. */
boolean updateWallpaperWindows(boolean visible) {
boolean changed = false;
if (isVisible() != visible) { if (isVisible() != visible) {
ProtoLog.d(WM_DEBUG_WALLPAPER, "Wallpaper token %s visible=%b", ProtoLog.d(WM_DEBUG_WALLPAPER, "Wallpaper token %s visible=%b",
token, visible); token, visible);
setVisibility(visible); setVisibility(visible);
changed = true;
} }
final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
if (mTransitionController.isShellTransitionsEnabled()) { if (mTransitionController.isShellTransitionsEnabled()) {
return; return changed;
} }
final WindowState wallpaperTarget = wallpaperController.getWallpaperTarget(); final WindowState wallpaperTarget =
mDisplayContent.mWallpaperController.getWallpaperTarget();
if (visible && wallpaperTarget != null) { if (visible && wallpaperTarget != null) {
final RecentsAnimationController recentsAnimationController = final RecentsAnimationController recentsAnimationController =
@@ -137,6 +140,7 @@ class WallpaperWindowToken extends WindowToken {
} }
setVisible(visible); setVisible(visible);
return changed;
} }
private void setVisible(boolean visible) { private void setVisible(boolean visible) {
@@ -155,10 +159,12 @@ class WallpaperWindowToken extends WindowToken {
* transition. In that situation, make sure to call {@link #commitVisibility} when done. * transition. In that situation, make sure to call {@link #commitVisibility} when done.
*/ */
void setVisibility(boolean visible) { void setVisibility(boolean visible) {
if (mVisibleRequested != visible) {
// Before setting mVisibleRequested so we can track changes. // Before setting mVisibleRequested so we can track changes.
mTransitionController.collect(this); mTransitionController.collect(this);
setVisibleRequested(visible); setVisibleRequested(visible);
}
// If in a transition, defer commits for activities that are going invisible // If in a transition, defer commits for activities that are going invisible
if (!visible && (mTransitionController.inTransition() if (!visible && (mTransitionController.inTransition()

View File

@@ -54,7 +54,6 @@ import android.view.RoundedCorners;
import android.view.Surface; import android.view.Surface;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import android.view.WindowManager; import android.view.WindowManager;
import android.window.ITransitionPlayer;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -313,11 +312,7 @@ public class WallpaperControllerTests extends WindowTestsBase {
wallpaperWindow.setHasSurface(true); wallpaperWindow.setHasSurface(true);
// Set-up mock shell transitions // Set-up mock shell transitions
final IBinder mockBinder = mock(IBinder.class); registerTestTransitionPlayer();
final ITransitionPlayer mockPlayer = mock(ITransitionPlayer.class);
doReturn(mockBinder).when(mockPlayer).asBinder();
mWm.mAtmService.getTransitionController().registerTransitionPlayer(mockPlayer,
null /* appThread */);
Transition transit = Transition transit =
mWm.mAtmService.getTransitionController().createTransition(TRANSIT_OPEN); mWm.mAtmService.getTransitionController().createTransition(TRANSIT_OPEN);
@@ -338,10 +333,21 @@ public class WallpaperControllerTests extends WindowTestsBase {
assertFalse(token.isVisibleRequested()); assertFalse(token.isVisibleRequested());
assertTrue(token.isVisible()); assertTrue(token.isVisible());
transit.onTransactionReady(transit.getSyncId(), mock(SurfaceControl.Transaction.class)); final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
transit.finishTransition(); token.finishSync(t, false /* cancel */);
transit.onTransactionReady(transit.getSyncId(), t);
dc.mTransitionController.finishTransition(transit);
assertFalse(wallpaperWindow.isVisible()); assertFalse(wallpaperWindow.isVisible());
assertFalse(token.isVisible()); assertFalse(token.isVisible());
// Assume wallpaper was visible. When transaction is ready without wallpaper target,
// wallpaper should be requested to be invisible.
token.setVisibility(true);
transit = dc.mTransitionController.createTransition(TRANSIT_CLOSE);
dc.mTransitionController.collect(token);
transit.onTransactionReady(transit.getSyncId(), t);
assertFalse(token.isVisibleRequested());
assertTrue(token.isVisible());
} }
private WindowState createWallpaperTargetWindow(DisplayContent dc) { private WindowState createWallpaperTargetWindow(DisplayContent dc) {