summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Evan Rosky <erosky@google.com> 2023-04-27 18:20:39 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-04-27 18:20:39 +0000
commit966ee1fd122e0810270f4806eb1c50adb69d72b7 (patch)
treeec1eb23f3f8f2db297f5534a3c110245537bf84f
parent2238fdb8f7ce0048489575ebec1dc75faef93268 (diff)
parentb4963b6da5669dc62b37a0e7ed80091e43203b73 (diff)
Merge "Allow Recents transitions to collect in parallel" into udc-dev
-rw-r--r--core/java/android/app/ActivityOptions.java7
-rw-r--r--data/etc/services.core.protolog.json30
-rw-r--r--services/core/java/com/android/server/wm/Transition.java32
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java75
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java1
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();