Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +40 −16 Original line number Diff line number Diff line Loading @@ -97,12 +97,13 @@ public class Transitions implements RemoteCallable<Transitions> { private float mTransitionAnimationScaleSetting = 1.0f; private static final class ActiveTransition { IBinder mToken = null; TransitionHandler mHandler = null; boolean mMerged = false; TransitionInfo mInfo = null; SurfaceControl.Transaction mStartT = null; SurfaceControl.Transaction mFinishT = null; IBinder mToken; TransitionHandler mHandler; boolean mMerged; boolean mAborted; TransitionInfo mInfo; SurfaceControl.Transaction mStartT; SurfaceControl.Transaction mFinishT; } /** Keeps track of currently playing transitions in the order of receipt. */ Loading Loading @@ -422,17 +423,19 @@ public class Transitions implements RemoteCallable<Transitions> { /** Special version of finish just for dealing with no-op/invalid transitions. */ private void onAbort(IBinder transition) { final int activeIdx = findActiveTransition(transition); if (activeIdx < 0) return; ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition animation aborted due to no-op, notifying core %s", transition); mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(transition, null /* wct */, null /* wctCB */); onFinish(transition, null /* wct */, null /* wctCB */, true /* abort */); } private void onFinish(IBinder transition, @Nullable WindowContainerTransaction wct, @Nullable WindowContainerTransactionCallback wctCB) { onFinish(transition, wct, wctCB, false /* abort */); } private void onFinish(IBinder transition, @Nullable WindowContainerTransaction wct, @Nullable WindowContainerTransactionCallback wctCB, boolean abort) { int activeIdx = findActiveTransition(transition); if (activeIdx < 0) { Log.e(TAG, "Trying to finish a non-running transition. Either remote crashed or " Loading @@ -440,28 +443,37 @@ public class Transitions implements RemoteCallable<Transitions> { return; } else if (activeIdx > 0) { // This transition was merged. ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition was merged: %s", transition); ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition was merged (abort=%b:" + " %s", abort, transition); final ActiveTransition active = mActiveTransitions.get(activeIdx); active.mMerged = true; active.mAborted = abort; if (active.mHandler != null) { active.mHandler.onTransitionMerged(active.mToken); } return; } mActiveTransitions.get(activeIdx).mAborted = abort; ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition animation finished, notifying core %s", transition); "Transition animation finished (abort=%b), notifying core %s", abort, transition); // Merge all relevant transactions together SurfaceControl.Transaction fullFinish = mActiveTransitions.get(activeIdx).mFinishT; for (int iA = activeIdx + 1; iA < mActiveTransitions.size(); ++iA) { final ActiveTransition toMerge = mActiveTransitions.get(iA); if (!toMerge.mMerged) break; // aborted transitions have no start/finish transactions if (mActiveTransitions.get(iA).mStartT == null) break; if (fullFinish == null) { fullFinish = new SurfaceControl.Transaction(); } // Include start. It will be a no-op if it was already applied. Otherwise, we need it // to maintain consistent state. fullFinish.merge(mActiveTransitions.get(iA).mStartT); fullFinish.merge(mActiveTransitions.get(iA).mFinishT); } if (fullFinish != null) { fullFinish.apply(); } // Now perform all the finishes. mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(transition, wct, wctCB); Loading @@ -470,6 +482,12 @@ public class Transitions implements RemoteCallable<Transitions> { ActiveTransition merged = mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(merged.mToken, null /* wct */, null /* wctCB */); } // sift through aborted transitions while (mActiveTransitions.size() > activeIdx && mActiveTransitions.get(activeIdx).mAborted) { ActiveTransition aborted = mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(aborted.mToken, null /* wct */, null /* wctCB */); } if (mActiveTransitions.size() <= activeIdx) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "All active transition animations " + "finished"); Loading Loading @@ -500,6 +518,12 @@ public class Transitions implements RemoteCallable<Transitions> { int mergeIdx = activeIdx + 1; while (mergeIdx < mActiveTransitions.size()) { ActiveTransition mergeCandidate = mActiveTransitions.get(mergeIdx); if (mergeCandidate.mAborted) { // transition was aborted, so we can skip for now (still leave it in the list // so that it gets cleaned-up in the right order). ++mergeIdx; continue; } if (mergeCandidate.mMerged) { throw new IllegalStateException("Can't merge a transition after not-merging" + " a preceding one."); Loading services/core/java/com/android/server/wm/ActivityRecord.java +16 −0 Original line number Diff line number Diff line Loading @@ -665,6 +665,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean allDrawn; private boolean mLastAllDrawn; /** * Solely for reporting to ActivityMetricsLogger. Just tracks whether, the last time this * Actiivty was part of a syncset, all windows were ready by the time the sync was ready (vs. * only the top-occluding ones). The assumption here is if some were not ready, they were * covered with starting-window/splash-screen. */ boolean mLastAllReadyAtSync = false; private boolean mLastContainsShowWhenLockedWindow; private boolean mLastContainsDismissKeyguardWindow; private boolean mLastContainsTurnScreenOnWindow; Loading Loading @@ -9018,6 +9026,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return false; } @Override void finishSync(Transaction outMergedTransaction, boolean cancel) { // This override is just for getting metrics. allFinished needs to be checked before // finish because finish resets all the states. mLastAllReadyAtSync = allSyncFinished(); super.finishSync(outMergedTransaction, cancel); } static class Builder { private final ActivityTaskManagerService mAtmService; private WindowProcessController mCallerApp; Loading services/core/java/com/android/server/wm/BLASTSyncEngine.java +4 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,10 @@ class BLASTSyncEngine { setReady(id, true); } boolean isReady(int id) { return mActiveSyncs.get(id).mReady; } /** * Aborts the sync (ie. it doesn't wait for ready or anything to finish) */ Loading services/core/java/com/android/server/wm/DisplayContent.java +5 −1 Original line number Diff line number Diff line Loading @@ -3100,7 +3100,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp screenRotationAnimation.dumpDebug(proto, SCREEN_ROTATION_ANIMATION); } mDisplayFrames.dumpDebug(proto, DISPLAY_FRAMES); if (mAtmService.getTransitionController().isShellTransitionsEnabled()) { mAtmService.getTransitionController().dumpDebugLegacy(proto, APP_TRANSITION); } else { mAppTransition.dumpDebug(proto, APP_TRANSITION); } if (mFocusedApp != null) { mFocusedApp.writeNameToProto(proto, FOCUSED_APP); } Loading services/core/java/com/android/server/wm/Transition.java +26 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,9 @@ 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 com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN; import android.annotation.IntDef; import android.annotation.NonNull; import android.app.ActivityManager; Loading Loading @@ -395,6 +398,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe handleNonAppWindowsInTransition(displayId, mType, mFlags); reportStartReasonsToLogger(); // Manually show any activities that are visibleRequested. This is needed to properly // support simultaneous animation queueing/merging. Specifically, if transition A makes // an activity invisible, it's finishTransaction (which is applied *after* the animation) Loading Loading @@ -575,6 +580,23 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } } private void reportStartReasonsToLogger() { // Record transition start in metrics logger. We just assume everything is "DRAWN" // at this point since splash-screen is a presentation (shell) detail. ArrayMap<WindowContainer, Integer> reasons = new ArrayMap<>(); for (int i = mParticipants.size() - 1; i >= 0; --i) { ActivityRecord r = mParticipants.valueAt(i).asActivityRecord(); if (r == null) continue; // At this point, r is "ready", but if it's not "ALL ready" then it is probably only // ready due to starting-window. reasons.put(r, (r.mStartingData instanceof SplashScreenStartingData && !r.mLastAllReadyAtSync) ? APP_TRANSITION_SPLASH_SCREEN : APP_TRANSITION_WINDOWS_DRAWN); } mController.mAtm.mTaskSupervisor.getActivityMetricsLogger().notifyTransitionStarting( reasons); } @Override public String toString() { StringBuilder sb = new StringBuilder(64); Loading Loading @@ -953,6 +975,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe return out; } boolean getLegacyIsReady() { return mState == STATE_STARTED && mSyncId >= 0 && mSyncEngine.isReady(mSyncId); } static Transition fromBinder(IBinder binder) { return (Transition) binder; } Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java +40 −16 Original line number Diff line number Diff line Loading @@ -97,12 +97,13 @@ public class Transitions implements RemoteCallable<Transitions> { private float mTransitionAnimationScaleSetting = 1.0f; private static final class ActiveTransition { IBinder mToken = null; TransitionHandler mHandler = null; boolean mMerged = false; TransitionInfo mInfo = null; SurfaceControl.Transaction mStartT = null; SurfaceControl.Transaction mFinishT = null; IBinder mToken; TransitionHandler mHandler; boolean mMerged; boolean mAborted; TransitionInfo mInfo; SurfaceControl.Transaction mStartT; SurfaceControl.Transaction mFinishT; } /** Keeps track of currently playing transitions in the order of receipt. */ Loading Loading @@ -422,17 +423,19 @@ public class Transitions implements RemoteCallable<Transitions> { /** Special version of finish just for dealing with no-op/invalid transitions. */ private void onAbort(IBinder transition) { final int activeIdx = findActiveTransition(transition); if (activeIdx < 0) return; ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition animation aborted due to no-op, notifying core %s", transition); mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(transition, null /* wct */, null /* wctCB */); onFinish(transition, null /* wct */, null /* wctCB */, true /* abort */); } private void onFinish(IBinder transition, @Nullable WindowContainerTransaction wct, @Nullable WindowContainerTransactionCallback wctCB) { onFinish(transition, wct, wctCB, false /* abort */); } private void onFinish(IBinder transition, @Nullable WindowContainerTransaction wct, @Nullable WindowContainerTransactionCallback wctCB, boolean abort) { int activeIdx = findActiveTransition(transition); if (activeIdx < 0) { Log.e(TAG, "Trying to finish a non-running transition. Either remote crashed or " Loading @@ -440,28 +443,37 @@ public class Transitions implements RemoteCallable<Transitions> { return; } else if (activeIdx > 0) { // This transition was merged. ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition was merged: %s", transition); ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition was merged (abort=%b:" + " %s", abort, transition); final ActiveTransition active = mActiveTransitions.get(activeIdx); active.mMerged = true; active.mAborted = abort; if (active.mHandler != null) { active.mHandler.onTransitionMerged(active.mToken); } return; } mActiveTransitions.get(activeIdx).mAborted = abort; ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition animation finished, notifying core %s", transition); "Transition animation finished (abort=%b), notifying core %s", abort, transition); // Merge all relevant transactions together SurfaceControl.Transaction fullFinish = mActiveTransitions.get(activeIdx).mFinishT; for (int iA = activeIdx + 1; iA < mActiveTransitions.size(); ++iA) { final ActiveTransition toMerge = mActiveTransitions.get(iA); if (!toMerge.mMerged) break; // aborted transitions have no start/finish transactions if (mActiveTransitions.get(iA).mStartT == null) break; if (fullFinish == null) { fullFinish = new SurfaceControl.Transaction(); } // Include start. It will be a no-op if it was already applied. Otherwise, we need it // to maintain consistent state. fullFinish.merge(mActiveTransitions.get(iA).mStartT); fullFinish.merge(mActiveTransitions.get(iA).mFinishT); } if (fullFinish != null) { fullFinish.apply(); } // Now perform all the finishes. mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(transition, wct, wctCB); Loading @@ -470,6 +482,12 @@ public class Transitions implements RemoteCallable<Transitions> { ActiveTransition merged = mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(merged.mToken, null /* wct */, null /* wctCB */); } // sift through aborted transitions while (mActiveTransitions.size() > activeIdx && mActiveTransitions.get(activeIdx).mAborted) { ActiveTransition aborted = mActiveTransitions.remove(activeIdx); mOrganizer.finishTransition(aborted.mToken, null /* wct */, null /* wctCB */); } if (mActiveTransitions.size() <= activeIdx) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "All active transition animations " + "finished"); Loading Loading @@ -500,6 +518,12 @@ public class Transitions implements RemoteCallable<Transitions> { int mergeIdx = activeIdx + 1; while (mergeIdx < mActiveTransitions.size()) { ActiveTransition mergeCandidate = mActiveTransitions.get(mergeIdx); if (mergeCandidate.mAborted) { // transition was aborted, so we can skip for now (still leave it in the list // so that it gets cleaned-up in the right order). ++mergeIdx; continue; } if (mergeCandidate.mMerged) { throw new IllegalStateException("Can't merge a transition after not-merging" + " a preceding one."); Loading
services/core/java/com/android/server/wm/ActivityRecord.java +16 −0 Original line number Diff line number Diff line Loading @@ -665,6 +665,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean allDrawn; private boolean mLastAllDrawn; /** * Solely for reporting to ActivityMetricsLogger. Just tracks whether, the last time this * Actiivty was part of a syncset, all windows were ready by the time the sync was ready (vs. * only the top-occluding ones). The assumption here is if some were not ready, they were * covered with starting-window/splash-screen. */ boolean mLastAllReadyAtSync = false; private boolean mLastContainsShowWhenLockedWindow; private boolean mLastContainsDismissKeyguardWindow; private boolean mLastContainsTurnScreenOnWindow; Loading Loading @@ -9018,6 +9026,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return false; } @Override void finishSync(Transaction outMergedTransaction, boolean cancel) { // This override is just for getting metrics. allFinished needs to be checked before // finish because finish resets all the states. mLastAllReadyAtSync = allSyncFinished(); super.finishSync(outMergedTransaction, cancel); } static class Builder { private final ActivityTaskManagerService mAtmService; private WindowProcessController mCallerApp; Loading
services/core/java/com/android/server/wm/BLASTSyncEngine.java +4 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,10 @@ class BLASTSyncEngine { setReady(id, true); } boolean isReady(int id) { return mActiveSyncs.get(id).mReady; } /** * Aborts the sync (ie. it doesn't wait for ready or anything to finish) */ Loading
services/core/java/com/android/server/wm/DisplayContent.java +5 −1 Original line number Diff line number Diff line Loading @@ -3100,7 +3100,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp screenRotationAnimation.dumpDebug(proto, SCREEN_ROTATION_ANIMATION); } mDisplayFrames.dumpDebug(proto, DISPLAY_FRAMES); if (mAtmService.getTransitionController().isShellTransitionsEnabled()) { mAtmService.getTransitionController().dumpDebugLegacy(proto, APP_TRANSITION); } else { mAppTransition.dumpDebug(proto, APP_TRANSITION); } if (mFocusedApp != null) { mFocusedApp.writeNameToProto(proto, FOCUSED_APP); } Loading
services/core/java/com/android/server/wm/Transition.java +26 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,9 @@ 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 com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN; import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN; import android.annotation.IntDef; import android.annotation.NonNull; import android.app.ActivityManager; Loading Loading @@ -395,6 +398,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe handleNonAppWindowsInTransition(displayId, mType, mFlags); reportStartReasonsToLogger(); // Manually show any activities that are visibleRequested. This is needed to properly // support simultaneous animation queueing/merging. Specifically, if transition A makes // an activity invisible, it's finishTransaction (which is applied *after* the animation) Loading Loading @@ -575,6 +580,23 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } } private void reportStartReasonsToLogger() { // Record transition start in metrics logger. We just assume everything is "DRAWN" // at this point since splash-screen is a presentation (shell) detail. ArrayMap<WindowContainer, Integer> reasons = new ArrayMap<>(); for (int i = mParticipants.size() - 1; i >= 0; --i) { ActivityRecord r = mParticipants.valueAt(i).asActivityRecord(); if (r == null) continue; // At this point, r is "ready", but if it's not "ALL ready" then it is probably only // ready due to starting-window. reasons.put(r, (r.mStartingData instanceof SplashScreenStartingData && !r.mLastAllReadyAtSync) ? APP_TRANSITION_SPLASH_SCREEN : APP_TRANSITION_WINDOWS_DRAWN); } mController.mAtm.mTaskSupervisor.getActivityMetricsLogger().notifyTransitionStarting( reasons); } @Override public String toString() { StringBuilder sb = new StringBuilder(64); Loading Loading @@ -953,6 +975,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe return out; } boolean getLegacyIsReady() { return mState == STATE_STARTED && mSyncId >= 0 && mSyncEngine.isReady(mSyncId); } static Transition fromBinder(IBinder binder) { return (Transition) binder; } Loading