Loading core/java/android/app/ActivityOptions.java +5 −2 Original line number Original line Diff line number Diff line Loading @@ -403,8 +403,11 @@ public class ActivityOptions extends ComponentOptions { private static final String KEY_SPLASH_SCREEN_STYLE = private static final String KEY_SPLASH_SCREEN_STYLE = "android.activity.splashScreenStyle"; "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)}. */ /** see {@link #makeLaunchIntoPip(PictureInPictureParams)}. */ private static final String KEY_LAUNCH_INTO_PIP_PARAMS = private static final String KEY_LAUNCH_INTO_PIP_PARAMS = Loading data/etc/services.core.protolog.json +24 −6 Original line number Original line Diff line number Diff line Loading @@ -1183,6 +1183,12 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/AppTransitionController.java" "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": { "-1003678883": { "message": "Cleaning splash screen token=%s", "message": "Cleaning splash screen token=%s", "level": "VERBOSE", "level": "VERBOSE", Loading Loading @@ -1447,6 +1453,12 @@ "group": "WM_DEBUG_TASKS", "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/RootWindowContainer.java" "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": { "-771177730": { "message": "Removing focused app token:%s displayId=%d", "message": "Removing focused app token:%s displayId=%d", "level": "VERBOSE", "level": "VERBOSE", Loading Loading @@ -1495,12 +1507,6 @@ "group": "WM_DEBUG_CONFIGURATION", "group": "WM_DEBUG_CONFIGURATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" "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": { "-732715767": { "message": "Unable to retrieve window container to start recording for display %d", "message": "Unable to retrieve window container to start recording for display %d", "level": "VERBOSE", "level": "VERBOSE", Loading Loading @@ -2017,6 +2023,12 @@ "group": "WM_DEBUG_WALLPAPER", "group": "WM_DEBUG_WALLPAPER", "at": "com\/android\/server\/wm\/WallpaperController.java" "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": { "-262984451": { "message": "Relaunch failed %s", "message": "Relaunch failed %s", "level": "INFO", "level": "INFO", Loading Loading @@ -2089,6 +2101,12 @@ "group": "WM_DEBUG_WINDOW_MOVEMENT", "group": "WM_DEBUG_WINDOW_MOVEMENT", "at": "com\/android\/server\/wm\/WindowManagerService.java" "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": { "-182877285": { "message": "Wallpaper layer changed: assigning layers + relayout", "message": "Wallpaper layer changed: assigning layers + relayout", "level": "VERBOSE", "level": "VERBOSE", Loading services/core/java/com/android/server/wm/Transition.java +30 −2 Original line number Original line Diff line number Diff line Loading @@ -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_TASK_LAUNCHING_BEHIND; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; import static android.window.TransitionInfo.FLAG_WILL_IME_SHOWN; 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.ActivityRecord.State.RESUMED; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM; Loading @@ -65,12 +66,14 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.IApplicationThread; import android.app.IApplicationThread; import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo; import android.graphics.Point; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Rect; import android.hardware.HardwareBuffer; import android.hardware.HardwareBuffer; import android.os.Binder; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.IRemoteCallback; import android.os.RemoteException; import android.os.RemoteException; Loading @@ -85,6 +88,7 @@ import android.view.SurfaceControl; import android.view.WindowManager; import android.view.WindowManager; import android.window.ScreenCapture; import android.window.ScreenCapture; import android.window.TransitionInfo; import android.window.TransitionInfo; import android.window.WindowContainerTransaction; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; import com.android.internal.graphics.ColorUtils; Loading Loading @@ -185,7 +189,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { final ArraySet<WindowContainer> mParticipants = new ArraySet<>(); final ArraySet<WindowContainer> mParticipants = new ArraySet<>(); /** The final animation targets derived from participants after promotion. */ /** The final animation targets derived from participants after promotion. */ private ArrayList<ChangeInfo> mTargets; ArrayList<ChangeInfo> mTargets; /** The displays that this transition is running on. */ /** The displays that this transition is running on. */ private final ArrayList<DisplayContent> mTargetDisplays = new ArrayList<>(); private final ArrayList<DisplayContent> mTargetDisplays = new ArrayList<>(); Loading Loading @@ -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. */ /** Any 2 transitions of this type can run in parallel with each other. Used for testing. */ static final int PARALLEL_TYPE_MUTUAL = 1; static final int PARALLEL_TYPE_MUTUAL = 1; /** This is a recents transition. */ static final int PARALLEL_TYPE_RECENTS = 2; @IntDef(prefix = { "PARALLEL_TYPE_" }, value = { @IntDef(prefix = { "PARALLEL_TYPE_" }, value = { PARALLEL_TYPE_NONE, PARALLEL_TYPE_NONE, PARALLEL_TYPE_MUTUAL PARALLEL_TYPE_MUTUAL, PARALLEL_TYPE_RECENTS }) }) @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) @interface ParallelType {} @interface ParallelType {} Loading Loading @@ -328,6 +337,21 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { mFlags |= flag; 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. */ /** Records an activity as transient-launch. This activity must be already collected. */ void setTransientLaunch(@NonNull ActivityRecord activity, @Nullable Task restoreBelow) { void setTransientLaunch(@NonNull ActivityRecord activity, @Nullable Task restoreBelow) { if (mTransientLaunches == null) { if (mTransientLaunches == null) { Loading Loading @@ -380,6 +404,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { return false; return false; } } boolean hasTransientLaunch() { return mTransientLaunches != null && !mTransientLaunches.isEmpty(); } boolean isTransientLaunch(@NonNull ActivityRecord activity) { boolean isTransientLaunch(@NonNull ActivityRecord activity) { return mTransientLaunches != null && mTransientLaunches.containsKey(activity); return mTransientLaunches != null && mTransientLaunches.containsKey(activity); } } Loading services/core/java/com/android/server/wm/TransitionController.java +74 −1 Original line number Original line Diff line number Diff line Loading @@ -879,6 +879,8 @@ class TransitionController { // If it's a legacy sync, then it needs to wait until there is no collecting transition. // If it's a legacy sync, then it needs to wait until there is no collecting transition. if (queued.mTransition == null) return; if (queued.mTransition == null) return; if (!canStartCollectingNow(queued.mTransition)) 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); mWaitingTransitions.add(mCollectingTransition); mCollectingTransition = null; mCollectingTransition = null; } else if (mSyncEngine.hasActiveSync()) { } else if (mSyncEngine.hasActiveSync()) { Loading Loading @@ -930,10 +932,37 @@ class TransitionController { * in {@link #getIsIndependent} later. * in {@link #getIsIndependent} later. */ */ boolean getCanBeIndependent(Transition collecting, Transition queued) { boolean getCanBeIndependent(Transition collecting, Transition queued) { // For tests if (queued.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL if (queued.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL && collecting.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL) { && collecting.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL) { return true; 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; return false; } } Loading @@ -942,12 +971,48 @@ class TransitionController { * `running` is playing based on its current state. * `running` is playing based on its current state. */ */ static boolean getIsIndependent(Transition running, Transition incoming) { static boolean getIsIndependent(Transition running, Transition incoming) { // For tests if (running.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL if (running.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL && incoming.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL) { && incoming.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL) { return true; return true; } } // 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; 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) { void assignTrack(Transition transition, TransitionInfo info) { int track = -1; int track = -1; Loading @@ -970,9 +1035,15 @@ class TransitionController { if (track < 0) { if (track < 0) { // Didn't overlap with anything, so give it its own track // Didn't overlap with anything, so give it its own track track = mTrackCount; track = mTrackCount; if (track > 0) { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Playing #%d in parallel on " + "track #%d", transition.getSyncId(), track); } } } if (sync) { if (sync) { info.setFlags(info.getFlags() | TransitionInfo.FLAG_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; transition.mAnimationTrack = track; info.setTrack(track); info.setTrack(track); Loading Loading @@ -1145,6 +1216,8 @@ class TransitionController { // Check if we can run in parallel here. // Check if we can run in parallel here. if (canStartCollectingNow(transit)) { if (canStartCollectingNow(transit)) { // start running in parallel. // start running in parallel. ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Moving #%d from" + " collecting to waiting.", mCollectingTransition.getSyncId()); mWaitingTransitions.add(mCollectingTransition); mWaitingTransitions.add(mCollectingTransition); mCollectingTransition = null; mCollectingTransition = null; moveToCollecting(transit); moveToCollecting(transit); Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -299,6 +299,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub final boolean needsSetReady = t != null; final boolean needsSetReady = t != null; final Transition nextTransition = new Transition(type, 0 /* flags */, final Transition nextTransition = new Transition(type, 0 /* flags */, mTransitionController, mService.mWindowManager.mSyncEngine); mTransitionController, mService.mWindowManager.mSyncEngine); nextTransition.calcParallelCollectType(wct); mTransitionController.startCollectOrQueue(nextTransition, mTransitionController.startCollectOrQueue(nextTransition, (deferred) -> { (deferred) -> { nextTransition.start(); nextTransition.start(); Loading Loading
core/java/android/app/ActivityOptions.java +5 −2 Original line number Original line Diff line number Diff line Loading @@ -403,8 +403,11 @@ public class ActivityOptions extends ComponentOptions { private static final String KEY_SPLASH_SCREEN_STYLE = private static final String KEY_SPLASH_SCREEN_STYLE = "android.activity.splashScreenStyle"; "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)}. */ /** see {@link #makeLaunchIntoPip(PictureInPictureParams)}. */ private static final String KEY_LAUNCH_INTO_PIP_PARAMS = private static final String KEY_LAUNCH_INTO_PIP_PARAMS = Loading
data/etc/services.core.protolog.json +24 −6 Original line number Original line Diff line number Diff line Loading @@ -1183,6 +1183,12 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/AppTransitionController.java" "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": { "-1003678883": { "message": "Cleaning splash screen token=%s", "message": "Cleaning splash screen token=%s", "level": "VERBOSE", "level": "VERBOSE", Loading Loading @@ -1447,6 +1453,12 @@ "group": "WM_DEBUG_TASKS", "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/RootWindowContainer.java" "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": { "-771177730": { "message": "Removing focused app token:%s displayId=%d", "message": "Removing focused app token:%s displayId=%d", "level": "VERBOSE", "level": "VERBOSE", Loading Loading @@ -1495,12 +1507,6 @@ "group": "WM_DEBUG_CONFIGURATION", "group": "WM_DEBUG_CONFIGURATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" "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": { "-732715767": { "message": "Unable to retrieve window container to start recording for display %d", "message": "Unable to retrieve window container to start recording for display %d", "level": "VERBOSE", "level": "VERBOSE", Loading Loading @@ -2017,6 +2023,12 @@ "group": "WM_DEBUG_WALLPAPER", "group": "WM_DEBUG_WALLPAPER", "at": "com\/android\/server\/wm\/WallpaperController.java" "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": { "-262984451": { "message": "Relaunch failed %s", "message": "Relaunch failed %s", "level": "INFO", "level": "INFO", Loading Loading @@ -2089,6 +2101,12 @@ "group": "WM_DEBUG_WINDOW_MOVEMENT", "group": "WM_DEBUG_WINDOW_MOVEMENT", "at": "com\/android\/server\/wm\/WindowManagerService.java" "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": { "-182877285": { "message": "Wallpaper layer changed: assigning layers + relayout", "message": "Wallpaper layer changed: assigning layers + relayout", "level": "VERBOSE", "level": "VERBOSE", Loading
services/core/java/com/android/server/wm/Transition.java +30 −2 Original line number Original line Diff line number Diff line Loading @@ -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_TASK_LAUNCHING_BEHIND; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; import static android.window.TransitionInfo.FLAG_WILL_IME_SHOWN; 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.ActivityRecord.State.RESUMED; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM; Loading @@ -65,12 +66,14 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.IApplicationThread; import android.app.IApplicationThread; import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo; import android.graphics.Point; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Rect; import android.hardware.HardwareBuffer; import android.hardware.HardwareBuffer; import android.os.Binder; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.IRemoteCallback; import android.os.RemoteException; import android.os.RemoteException; Loading @@ -85,6 +88,7 @@ import android.view.SurfaceControl; import android.view.WindowManager; import android.view.WindowManager; import android.window.ScreenCapture; import android.window.ScreenCapture; import android.window.TransitionInfo; import android.window.TransitionInfo; import android.window.WindowContainerTransaction; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; import com.android.internal.graphics.ColorUtils; Loading Loading @@ -185,7 +189,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { final ArraySet<WindowContainer> mParticipants = new ArraySet<>(); final ArraySet<WindowContainer> mParticipants = new ArraySet<>(); /** The final animation targets derived from participants after promotion. */ /** The final animation targets derived from participants after promotion. */ private ArrayList<ChangeInfo> mTargets; ArrayList<ChangeInfo> mTargets; /** The displays that this transition is running on. */ /** The displays that this transition is running on. */ private final ArrayList<DisplayContent> mTargetDisplays = new ArrayList<>(); private final ArrayList<DisplayContent> mTargetDisplays = new ArrayList<>(); Loading Loading @@ -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. */ /** Any 2 transitions of this type can run in parallel with each other. Used for testing. */ static final int PARALLEL_TYPE_MUTUAL = 1; static final int PARALLEL_TYPE_MUTUAL = 1; /** This is a recents transition. */ static final int PARALLEL_TYPE_RECENTS = 2; @IntDef(prefix = { "PARALLEL_TYPE_" }, value = { @IntDef(prefix = { "PARALLEL_TYPE_" }, value = { PARALLEL_TYPE_NONE, PARALLEL_TYPE_NONE, PARALLEL_TYPE_MUTUAL PARALLEL_TYPE_MUTUAL, PARALLEL_TYPE_RECENTS }) }) @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) @interface ParallelType {} @interface ParallelType {} Loading Loading @@ -328,6 +337,21 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { mFlags |= flag; 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. */ /** Records an activity as transient-launch. This activity must be already collected. */ void setTransientLaunch(@NonNull ActivityRecord activity, @Nullable Task restoreBelow) { void setTransientLaunch(@NonNull ActivityRecord activity, @Nullable Task restoreBelow) { if (mTransientLaunches == null) { if (mTransientLaunches == null) { Loading Loading @@ -380,6 +404,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { return false; return false; } } boolean hasTransientLaunch() { return mTransientLaunches != null && !mTransientLaunches.isEmpty(); } boolean isTransientLaunch(@NonNull ActivityRecord activity) { boolean isTransientLaunch(@NonNull ActivityRecord activity) { return mTransientLaunches != null && mTransientLaunches.containsKey(activity); return mTransientLaunches != null && mTransientLaunches.containsKey(activity); } } Loading
services/core/java/com/android/server/wm/TransitionController.java +74 −1 Original line number Original line Diff line number Diff line Loading @@ -879,6 +879,8 @@ class TransitionController { // If it's a legacy sync, then it needs to wait until there is no collecting transition. // If it's a legacy sync, then it needs to wait until there is no collecting transition. if (queued.mTransition == null) return; if (queued.mTransition == null) return; if (!canStartCollectingNow(queued.mTransition)) 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); mWaitingTransitions.add(mCollectingTransition); mCollectingTransition = null; mCollectingTransition = null; } else if (mSyncEngine.hasActiveSync()) { } else if (mSyncEngine.hasActiveSync()) { Loading Loading @@ -930,10 +932,37 @@ class TransitionController { * in {@link #getIsIndependent} later. * in {@link #getIsIndependent} later. */ */ boolean getCanBeIndependent(Transition collecting, Transition queued) { boolean getCanBeIndependent(Transition collecting, Transition queued) { // For tests if (queued.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL if (queued.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL && collecting.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL) { && collecting.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL) { return true; 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; return false; } } Loading @@ -942,12 +971,48 @@ class TransitionController { * `running` is playing based on its current state. * `running` is playing based on its current state. */ */ static boolean getIsIndependent(Transition running, Transition incoming) { static boolean getIsIndependent(Transition running, Transition incoming) { // For tests if (running.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL if (running.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL && incoming.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL) { && incoming.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL) { return true; return true; } } // 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; 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) { void assignTrack(Transition transition, TransitionInfo info) { int track = -1; int track = -1; Loading @@ -970,9 +1035,15 @@ class TransitionController { if (track < 0) { if (track < 0) { // Didn't overlap with anything, so give it its own track // Didn't overlap with anything, so give it its own track track = mTrackCount; track = mTrackCount; if (track > 0) { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Playing #%d in parallel on " + "track #%d", transition.getSyncId(), track); } } } if (sync) { if (sync) { info.setFlags(info.getFlags() | TransitionInfo.FLAG_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; transition.mAnimationTrack = track; info.setTrack(track); info.setTrack(track); Loading Loading @@ -1145,6 +1216,8 @@ class TransitionController { // Check if we can run in parallel here. // Check if we can run in parallel here. if (canStartCollectingNow(transit)) { if (canStartCollectingNow(transit)) { // start running in parallel. // start running in parallel. ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "Moving #%d from" + " collecting to waiting.", mCollectingTransition.getSyncId()); mWaitingTransitions.add(mCollectingTransition); mWaitingTransitions.add(mCollectingTransition); mCollectingTransition = null; mCollectingTransition = null; moveToCollecting(transit); moveToCollecting(transit); Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -299,6 +299,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub final boolean needsSetReady = t != null; final boolean needsSetReady = t != null; final Transition nextTransition = new Transition(type, 0 /* flags */, final Transition nextTransition = new Transition(type, 0 /* flags */, mTransitionController, mService.mWindowManager.mSyncEngine); mTransitionController, mService.mWindowManager.mSyncEngine); nextTransition.calcParallelCollectType(wct); mTransitionController.startCollectOrQueue(nextTransition, mTransitionController.startCollectOrQueue(nextTransition, (deferred) -> { (deferred) -> { nextTransition.start(); nextTransition.start(); Loading