diff options
| author | 2023-04-27 18:20:39 +0000 | |
|---|---|---|
| committer | 2023-04-27 18:20:39 +0000 | |
| commit | 966ee1fd122e0810270f4806eb1c50adb69d72b7 (patch) | |
| tree | ec1eb23f3f8f2db297f5534a3c110245537bf84f | |
| parent | 2238fdb8f7ce0048489575ebec1dc75faef93268 (diff) | |
| parent | b4963b6da5669dc62b37a0e7ed80091e43203b73 (diff) | |
Merge "Allow Recents transitions to collect in parallel" into udc-dev
5 files changed, 134 insertions, 11 deletions
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 61d6787b4f85..2ae721648656 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -403,8 +403,11 @@ public class ActivityOptions extends ComponentOptions { private static final String KEY_SPLASH_SCREEN_STYLE = "android.activity.splashScreenStyle"; - /** See {@link #setTransientLaunch()}. */ - private static final String KEY_TRANSIENT_LAUNCH = "android.activity.transientLaunch"; + /** + * See {@link #setTransientLaunch()}. + * @hide + */ + public static final String KEY_TRANSIENT_LAUNCH = "android.activity.transientLaunch"; /** see {@link #makeLaunchIntoPip(PictureInPictureParams)}. */ private static final String KEY_LAUNCH_INTO_PIP_PARAMS = diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 596f3515dda5..7c2759af156f 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -1183,6 +1183,12 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/AppTransitionController.java" }, + "-1005167552": { + "message": "Playing #%d in parallel on track #%d", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/TransitionController.java" + }, "-1003678883": { "message": "Cleaning splash screen token=%s", "level": "VERBOSE", @@ -1447,6 +1453,12 @@ "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, + "-774908272": { + "message": "Marking #%d animation as SYNC.", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/TransitionController.java" + }, "-771177730": { "message": "Removing focused app token:%s displayId=%d", "level": "VERBOSE", @@ -1495,12 +1507,6 @@ "group": "WM_DEBUG_CONFIGURATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-741766551": { - "message": "Content Recording: Ignoring session on invalid virtual display", - "level": "VERBOSE", - "group": "WM_DEBUG_CONTENT_RECORDING", - "at": "com\/android\/server\/wm\/ContentRecordingController.java" - }, "-732715767": { "message": "Unable to retrieve window container to start recording for display %d", "level": "VERBOSE", @@ -2017,6 +2023,12 @@ "group": "WM_DEBUG_WALLPAPER", "at": "com\/android\/server\/wm\/WallpaperController.java" }, + "-266707683": { + "message": "Moving #%d from collecting to waiting.", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN", + "at": "com\/android\/server\/wm\/TransitionController.java" + }, "-262984451": { "message": "Relaunch failed %s", "level": "INFO", @@ -2089,6 +2101,12 @@ "group": "WM_DEBUG_WINDOW_MOVEMENT", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "-186693085": { + "message": "Starting a Recents transition which can be parallel.", + "level": "VERBOSE", + "group": "WM_DEBUG_WINDOW_TRANSITIONS", + "at": "com\/android\/server\/wm\/Transition.java" + }, "-182877285": { "message": "Wallpaper layer changed: assigning layers + relayout", "level": "VERBOSE", diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index d531ad175f10..838536b03335 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -55,6 +55,7 @@ import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER; import static android.window.TransitionInfo.FLAG_TASK_LAUNCHING_BEHIND; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; import static android.window.TransitionInfo.FLAG_WILL_IME_SHOWN; +import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_PENDING_INTENT; import static com.android.server.wm.ActivityRecord.State.RESUMED; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM; @@ -65,12 +66,14 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.ActivityOptions; import android.app.IApplicationThread; import android.content.pm.ActivityInfo; import android.graphics.Point; import android.graphics.Rect; import android.hardware.HardwareBuffer; import android.os.Binder; +import android.os.Bundle; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.RemoteException; @@ -85,6 +88,7 @@ import android.view.SurfaceControl; import android.view.WindowManager; import android.window.ScreenCapture; import android.window.TransitionInfo; +import android.window.WindowContainerTransaction; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; @@ -185,7 +189,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { final ArraySet<WindowContainer> mParticipants = new ArraySet<>(); /** The final animation targets derived from participants after promotion. */ - private ArrayList<ChangeInfo> mTargets; + ArrayList<ChangeInfo> mTargets; /** The displays that this transition is running on. */ private final ArrayList<DisplayContent> mTargetDisplays = new ArrayList<>(); @@ -271,9 +275,14 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { /** Any 2 transitions of this type can run in parallel with each other. Used for testing. */ static final int PARALLEL_TYPE_MUTUAL = 1; + /** This is a recents transition. */ + static final int PARALLEL_TYPE_RECENTS = 2; + + @IntDef(prefix = { "PARALLEL_TYPE_" }, value = { PARALLEL_TYPE_NONE, - PARALLEL_TYPE_MUTUAL + PARALLEL_TYPE_MUTUAL, + PARALLEL_TYPE_RECENTS }) @Retention(RetentionPolicy.SOURCE) @interface ParallelType {} @@ -328,6 +337,21 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { mFlags |= flag; } + void calcParallelCollectType(WindowContainerTransaction wct) { + for (int i = 0; i < wct.getHierarchyOps().size(); ++i) { + final WindowContainerTransaction.HierarchyOp hop = wct.getHierarchyOps().get(i); + if (hop.getType() != HIERARCHY_OP_TYPE_PENDING_INTENT) continue; + final Bundle b = hop.getLaunchOptions(); + if (b == null || b.isEmpty()) continue; + final boolean transientLaunch = b.getBoolean(ActivityOptions.KEY_TRANSIENT_LAUNCH); + if (transientLaunch) { + ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, + "Starting a Recents transition which can be parallel."); + mParallelCollectType = PARALLEL_TYPE_RECENTS; + } + } + } + /** Records an activity as transient-launch. This activity must be already collected. */ void setTransientLaunch(@NonNull ActivityRecord activity, @Nullable Task restoreBelow) { if (mTransientLaunches == null) { @@ -380,6 +404,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { return false; } + boolean hasTransientLaunch() { + return mTransientLaunches != null && !mTransientLaunches.isEmpty(); + } + boolean isTransientLaunch(@NonNull ActivityRecord activity) { return mTransientLaunches != null && mTransientLaunches.containsKey(activity); } diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index 7950edaaa267..19ef40b61634 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -879,6 +879,8 @@ class TransitionController { // If it's a legacy sync, then it needs to wait until there is no collecting transition. if (queued.mTransition == null) return; if (!canStartCollectingNow(queued.mTransition)) return; + ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Moving #%d from collecting" + + " to waiting.", mCollectingTransition.getSyncId()); mWaitingTransitions.add(mCollectingTransition); mCollectingTransition = null; } else if (mSyncEngine.hasActiveSync()) { @@ -930,10 +932,37 @@ class TransitionController { * in {@link #getIsIndependent} later. */ boolean getCanBeIndependent(Transition collecting, Transition queued) { + // For tests if (queued.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL && collecting.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL) { return true; } + // For recents + if (queued.mParallelCollectType == Transition.PARALLEL_TYPE_RECENTS) { + if (collecting.mParallelCollectType == Transition.PARALLEL_TYPE_RECENTS) { + // Must serialize with itself. + return false; + } + // allow this if `collecting` only has activities + for (int i = 0; i < collecting.mParticipants.size(); ++i) { + final WindowContainer wc = collecting.mParticipants.valueAt(i); + final ActivityRecord ar = wc.asActivityRecord(); + if (ar == null && wc.asWindowState() == null && wc.asWindowToken() == null) { + // Is task or above, so can't be independent + return false; + } + if (ar != null && ar.isActivityTypeHomeOrRecents()) { + // It's a recents or home type, so it conflicts. + return false; + } + } + return true; + } else if (collecting.mParallelCollectType == Transition.PARALLEL_TYPE_RECENTS) { + // We can collect simultaneously with recents if it is populated. This is because + // we know that recents will not collect/trampoline any more stuff. If anything in the + // queued transition overlaps, it will end up just waiting in sync-queue anyways. + return true; + } return false; } @@ -942,11 +971,47 @@ class TransitionController { * `running` is playing based on its current state. */ static boolean getIsIndependent(Transition running, Transition incoming) { + // For tests if (running.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL && incoming.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL) { return true; } - return false; + // For now there's only one mutually-independent pair: an all activity-level transition and + // a transient-launch where none of the activities are part of the transient-launch task, + // so the following logic is hard-coded specifically for this. + // Also, we currently restrict valid transient-launches to just recents. + final Transition recents; + final Transition other; + if (running.mParallelCollectType == Transition.PARALLEL_TYPE_RECENTS + && running.hasTransientLaunch()) { + if (incoming.mParallelCollectType == Transition.PARALLEL_TYPE_RECENTS) { + // Recents can't be independent from itself. + return false; + } + recents = running; + other = incoming; + } else if (incoming.mParallelCollectType == Transition.PARALLEL_TYPE_RECENTS + && incoming.hasTransientLaunch()) { + recents = incoming; + other = running; + } else { + return false; + } + // Check against *targets* because that is the post-promotion set of containers that are + // actually animating. + for (int i = 0; i < other.mTargets.size(); ++i) { + final WindowContainer wc = other.mTargets.get(i).mContainer; + final ActivityRecord ar = wc.asActivityRecord(); + if (ar == null && wc.asWindowState() == null && wc.asWindowToken() == null) { + // Is task or above, so for now don't let them be independent. + return false; + } + if (ar != null && recents.isTransientLaunch(ar)) { + // Change overlaps with recents, so serialize. + return false; + } + } + return true; } void assignTrack(Transition transition, TransitionInfo info) { @@ -970,9 +1035,15 @@ class TransitionController { if (track < 0) { // Didn't overlap with anything, so give it its own track track = mTrackCount; + if (track > 0) { + ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Playing #%d in parallel on " + + "track #%d", transition.getSyncId(), track); + } } if (sync) { info.setFlags(info.getFlags() | TransitionInfo.FLAG_SYNC); + ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Marking #%d animation as SYNC.", + transition.getSyncId()); } transition.mAnimationTrack = track; info.setTrack(track); @@ -1145,6 +1216,8 @@ class TransitionController { // Check if we can run in parallel here. if (canStartCollectingNow(transit)) { // start running in parallel. + ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Moving #%d from" + + " collecting to waiting.", mCollectingTransition.getSyncId()); mWaitingTransitions.add(mCollectingTransition); mCollectingTransition = null; moveToCollecting(transit); diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index cd42528ad79b..d5aa520e1b6e 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -299,6 +299,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub final boolean needsSetReady = t != null; final Transition nextTransition = new Transition(type, 0 /* flags */, mTransitionController, mService.mWindowManager.mSyncEngine); + nextTransition.calcParallelCollectType(wct); mTransitionController.startCollectOrQueue(nextTransition, (deferred) -> { nextTransition.start(); |