summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/window/SystemPerformanceHinter.java117
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java50
-rw-r--r--services/core/java/com/android/server/wm/Transition.java16
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java58
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java47
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java6
-rw-r--r--services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java57
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java6
9 files changed, 248 insertions, 123 deletions
diff --git a/core/java/android/window/SystemPerformanceHinter.java b/core/java/android/window/SystemPerformanceHinter.java
index 2736b68845a2..5b0d8d1233c6 100644
--- a/core/java/android/window/SystemPerformanceHinter.java
+++ b/core/java/android/window/SystemPerformanceHinter.java
@@ -29,11 +29,11 @@ import android.content.Context;
import android.os.PerformanceHintManager;
import android.os.Trace;
import android.util.Log;
+import android.view.Display;
import android.view.SurfaceControl;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Random;
import java.util.function.Supplier;
/**
@@ -45,6 +45,7 @@ import java.util.function.Supplier;
public class SystemPerformanceHinter {
private static final String TAG = "SystemPerformanceHinter";
+ private static final int HINT_NO_OP = 0;
// Change app and SF wakeup times to allow sf more time to composite a frame
public static final int HINT_SF_EARLY_WAKEUP = 1 << 0;
// Force max refresh rate
@@ -88,14 +89,17 @@ public class SystemPerformanceHinter {
private final @HintFlags int hintFlags;
private final String reason;
private final int displayId;
- private final int traceCookie;
+ private String mTraceName;
protected HighPerfSession(@HintFlags int hintFlags, int displayId, @NonNull String reason) {
this.hintFlags = hintFlags;
this.reason = reason;
this.displayId = displayId;
- this.traceCookie = new Random().nextInt();
- if (hintFlags != 0) {
+ }
+
+ /** Makes this session active. It is no-op if this session is already active. */
+ public void start() {
+ if (!mActiveSessions.contains(this)) {
startSession(this);
}
}
@@ -103,15 +107,36 @@ public class SystemPerformanceHinter {
/**
* Closes this session.
*/
+ @Override
public void close() {
- if (hintFlags != 0) {
- endSession(this);
- }
+ endSession(this);
}
+ @Override
public void finalize() {
close();
}
+
+ boolean asyncTraceBegin() {
+ if (!Trace.isTagEnabled(mTraceTag)) {
+ mTraceName = null;
+ return false;
+ }
+ if (mTraceName == null) {
+ mTraceName = "PerfSession-d" + displayId + "-" + reason;
+ }
+ Trace.asyncTraceForTrackBegin(mTraceTag, TAG, mTraceName,
+ System.identityHashCode(this));
+ return true;
+ }
+
+ boolean asyncTraceEnd() {
+ if (mTraceName == null) {
+ return false;
+ }
+ Trace.asyncTraceForTrackEnd(mTraceTag, TAG, System.identityHashCode(this));
+ return true;
+ }
}
/**
@@ -119,14 +144,22 @@ public class SystemPerformanceHinter {
*/
private class NoOpHighPerfSession extends HighPerfSession {
public NoOpHighPerfSession() {
- super(0 /* hintFlags */, -1 /* displayId */, "");
+ super(HINT_NO_OP, Display.INVALID_DISPLAY, "");
+ }
+
+ @Override
+ public void start() {
}
+ @Override
public void close() {
// Do nothing
}
}
+ /** The tag category of trace. */
+ public long mTraceTag = Trace.TRACE_TAG_APP;
+
// The active sessions
private final ArrayList<HighPerfSession> mActiveSessions = new ArrayList<>();
private final SurfaceControl.Transaction mTransaction;
@@ -134,7 +167,6 @@ public class SystemPerformanceHinter {
private @Nullable PerformanceHintManager.Session mAdpfSession;
private @Nullable DisplayRootProvider mDisplayRootProvider;
-
/**
* Constructor for the hinter.
* @hide
@@ -167,12 +199,12 @@ public class SystemPerformanceHinter {
mAdpfSession = adpfSession;
}
- /**
- * Starts a session that requires high performance.
- * @hide
- */
- public HighPerfSession startSession(@HintFlags int hintFlags, int displayId,
+ /** Creates a session that requires high performance. */
+ public HighPerfSession createSession(@HintFlags int hintFlags, int displayId,
@NonNull String reason) {
+ if (hintFlags == HINT_NO_OP) {
+ throw new IllegalArgumentException("Not allow empty hint flags");
+ }
if (mDisplayRootProvider == null && (hintFlags & HINT_SF_FRAME_RATE) != 0) {
throw new IllegalArgumentException(
"Using SF frame rate hints requires a valid display root provider");
@@ -193,9 +225,20 @@ public class SystemPerformanceHinter {
}
/**
- * Starts a session that requires high performance.
+ * Starts a new session that requires high performance.
*/
+ public HighPerfSession startSession(@HintFlags int hintFlags, int displayId,
+ @NonNull String reason) {
+ final HighPerfSession session = createSession(hintFlags, displayId, reason);
+ if (session.hintFlags != HINT_NO_OP) {
+ startSession(session);
+ }
+ return session;
+ }
+
+ /** Starts the session that requires high performance. */
private void startSession(HighPerfSession session) {
+ final boolean isTraceEnabled = session.asyncTraceBegin();
int oldGlobalFlags = calculateActiveHintFlags(HINT_GLOBAL);
int oldPerDisplayFlags = calculateActiveHintFlagsForDisplay(HINT_PER_DISPLAY,
session.displayId);
@@ -217,19 +260,24 @@ public class SystemPerformanceHinter {
mTransaction.setFrameRateCategory(
displaySurfaceControl, FRAME_RATE_CATEGORY_HIGH, /* smoothSwitchOnly= */ false);
transactionChanged = true;
- Trace.beginAsyncSection("PerfHint-framerate-" + session.displayId + "-"
- + session.reason, session.traceCookie);
+ if (isTraceEnabled) {
+ asyncTraceBegin(HINT_SF_FRAME_RATE, session.displayId);
+ }
}
// Global flags
if (nowEnabled(oldGlobalFlags, newGlobalFlags, HINT_SF_EARLY_WAKEUP)) {
mTransaction.setEarlyWakeupStart();
transactionChanged = true;
- Trace.beginAsyncSection("PerfHint-early_wakeup-" + session.reason, session.traceCookie);
+ if (isTraceEnabled) {
+ asyncTraceBegin(HINT_SF_EARLY_WAKEUP, Display.INVALID_DISPLAY);
+ }
}
if (nowEnabled(oldGlobalFlags, newGlobalFlags, HINT_ADPF)) {
mAdpfSession.sendHint(PerformanceHintManager.Session.CPU_LOAD_UP);
- Trace.beginAsyncSection("PerfHint-adpf-" + session.reason, session.traceCookie);
+ if (isTraceEnabled) {
+ asyncTraceBegin(HINT_ADPF, Display.INVALID_DISPLAY);
+ }
}
if (transactionChanged) {
mTransaction.applyAsyncUnsafe();
@@ -240,6 +288,7 @@ public class SystemPerformanceHinter {
* Ends a session that requires high performance.
*/
private void endSession(HighPerfSession session) {
+ final boolean isTraceEnabled = session.asyncTraceEnd();
int oldGlobalFlags = calculateActiveHintFlags(HINT_GLOBAL);
int oldPerDisplayFlags = calculateActiveHintFlagsForDisplay(HINT_PER_DISPLAY,
session.displayId);
@@ -261,19 +310,24 @@ public class SystemPerformanceHinter {
mTransaction.setFrameRateCategory(displaySurfaceControl, FRAME_RATE_CATEGORY_DEFAULT,
/* smoothSwitchOnly= */ false);
transactionChanged = true;
- Trace.endAsyncSection("PerfHint-framerate-" + session.displayId + "-" + session.reason,
- session.traceCookie);
+ if (isTraceEnabled) {
+ asyncTraceEnd(HINT_SF_FRAME_RATE);
+ }
}
// Global flags
if (nowDisabled(oldGlobalFlags, newGlobalFlags, HINT_SF_EARLY_WAKEUP)) {
mTransaction.setEarlyWakeupEnd();
transactionChanged = true;
- Trace.endAsyncSection("PerfHint-early_wakeup-" + session.reason, session.traceCookie);
+ if (isTraceEnabled) {
+ asyncTraceEnd(HINT_SF_EARLY_WAKEUP);
+ }
}
if (nowDisabled(oldGlobalFlags, newGlobalFlags, HINT_ADPF)) {
mAdpfSession.sendHint(PerformanceHintManager.Session.CPU_LOAD_RESET);
- Trace.endAsyncSection("PerfHint-adpf-" + session.reason, session.traceCookie);
+ if (isTraceEnabled) {
+ asyncTraceEnd(HINT_ADPF);
+ }
}
if (transactionChanged) {
mTransaction.applyAsyncUnsafe();
@@ -323,6 +377,23 @@ public class SystemPerformanceHinter {
return flags;
}
+ private void asyncTraceBegin(@HintFlags int flag, int displayId) {
+ final String prefix = switch (flag) {
+ case HINT_SF_EARLY_WAKEUP -> "PerfHint-early_wakeup";
+ case HINT_SF_FRAME_RATE -> "PerfHint-framerate";
+ case HINT_ADPF -> "PerfHint-adpf";
+ default -> "PerfHint-" + flag;
+ };
+ final String name = displayId != Display.INVALID_DISPLAY
+ ? (prefix + "-d" + displayId) : prefix;
+ Trace.asyncTraceForTrackBegin(mTraceTag, TAG, name,
+ flag ^ System.identityHashCode(this));
+ }
+
+ private void asyncTraceEnd(@HintFlags int flag) {
+ Trace.asyncTraceForTrackEnd(mTraceTag, TAG, flag ^ System.identityHashCode(this));
+ }
+
/**
* Dumps the existing sessions.
*/
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index f31490060fc8..697402016f35 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -160,6 +160,7 @@ import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
import static com.android.server.wm.utils.RegionUtils.forEachRectReverse;
import static com.android.server.wm.utils.RegionUtils.rectListToRegion;
+import static com.android.window.flags.Flags.explicitRefreshRateHints;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -245,6 +246,7 @@ import android.window.DisplayWindowPolicyController;
import android.window.IDisplayAreaOrganizer;
import android.window.ScreenCapture;
import android.window.ScreenCapture.SynchronousScreenCaptureListener;
+import android.window.SystemPerformanceHinter;
import android.window.TransitionRequestInfo;
import com.android.internal.R;
@@ -572,6 +574,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
private final SurfaceSession mSession = new SurfaceSession();
/**
+ * A perf hint session which will boost the refresh rate for the display and change sf duration
+ * to handle larger workloads.
+ */
+ private SystemPerformanceHinter.HighPerfSession mTransitionPrefSession;
+
+ /** A perf hint session which will boost the refresh rate. */
+ private SystemPerformanceHinter.HighPerfSession mHighFrameRateSession;
+
+ /**
* Window that is currently interacting with the user. This window is responsible for receiving
* key events and pointer events from the user.
*/
@@ -761,6 +772,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
boolean mDontMoveToTop;
+ /** Whether this display contains a WindowContainer with running SurfaceAnimator. */
+ boolean mLastContainsRunningSurfaceAnimator;
+
/** Used for windows that want to keep the screen awake. */
private PowerManager.WakeLock mHoldScreenWakeLock;
@@ -3447,6 +3461,42 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return dockFrame.bottom - imeFrame.top;
}
+ void enableHighPerfTransition(boolean enable) {
+ if (!explicitRefreshRateHints()) {
+ if (enable) {
+ getPendingTransaction().setEarlyWakeupStart();
+ } else {
+ getPendingTransaction().setEarlyWakeupEnd();
+ }
+ return;
+ }
+ if (enable) {
+ if (mTransitionPrefSession == null) {
+ mTransitionPrefSession = mWmService.mSystemPerformanceHinter.createSession(
+ SystemPerformanceHinter.HINT_SF, mDisplayId, "Transition");
+ }
+ mTransitionPrefSession.start();
+ } else if (mTransitionPrefSession != null) {
+ mTransitionPrefSession.close();
+ }
+ }
+
+ void enableHighFrameRate(boolean enable) {
+ if (!explicitRefreshRateHints()) {
+ // Done by RefreshRatePolicy.
+ return;
+ }
+ if (enable) {
+ if (mHighFrameRateSession == null) {
+ mHighFrameRateSession = mWmService.mSystemPerformanceHinter.createSession(
+ SystemPerformanceHinter.HINT_SF_FRAME_RATE, mDisplayId, "WindowAnimation");
+ }
+ mHighFrameRateSession.start();
+ } else if (mHighFrameRateSession != null) {
+ mHighFrameRateSession.close();
+ }
+ }
+
void rotateBounds(@Rotation int oldRotation, @Rotation int newRotation, Rect inOutBounds) {
// Get display bounds on oldRotation as parent bounds for the rotation.
getBounds(mTmpRect, oldRotation);
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index f6b4972de250..9594c65ad5fc 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -249,7 +249,6 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
private boolean mIsSeamlessRotation = false;
private IContainerFreezer mContainerFreezer = null;
- private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
/**
* {@code true} if some other operation may have caused the originally-recorded state (in
@@ -628,11 +627,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
mLogger.mStartTimeNs = SystemClock.elapsedRealtimeNanos();
- mController.updateAnimatingState(mTmpTransaction);
- // merge into the next-time the global transaction is applied. This is too-early to set
- // early-wake anyways, so we don't need to apply immediately (in fact applying right now
- // can preempt more-important work).
- SurfaceControl.mergeToGlobalTransaction(mTmpTransaction);
+ mController.updateAnimatingState();
}
/**
@@ -704,7 +699,11 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
if (dc == null || mTargetDisplays.contains(dc)) return;
mTargetDisplays.add(dc);
addOnTopTasks(dc, mOnTopTasksStart);
- mController.startPerfHintForDisplay(dc.mDisplayId);
+ // Handle the case {transition.start(); applyTransaction(wct);} that the animating state
+ // is set before collecting participants.
+ if (mController.isAnimating()) {
+ dc.enableHighPerfTransition(true);
+ }
}
/**
@@ -1407,8 +1406,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
false /* forceRelayout */);
}
cleanUpInternal();
- mController.updateAnimatingState(mTmpTransaction);
- mTmpTransaction.apply();
+ mController.updateAnimatingState();
// Handle back animation if it's already started.
mController.mAtm.mBackNavigationController.onTransitionFinish(mTargets, this);
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 28c24c82e830..c134464bc33a 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -22,10 +22,8 @@ import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.window.SystemPerformanceHinter.HINT_SF;
import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;
-import static com.android.window.flags.Flags.explicitRefreshRateHints;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -41,18 +39,14 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
-import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.ITransitionMetricsReporter;
import android.window.ITransitionPlayer;
import android.window.RemoteTransition;
-import android.window.SystemPerformanceHinter;
-import android.window.SystemPerformanceHinter.HighPerfSession;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
@@ -131,7 +125,6 @@ class TransitionController {
SnapshotController mSnapshotController;
TransitionTracer mTransitionTracer;
- private SystemPerformanceHinter mSystemPerformanceHinter;
private boolean mFullReadyTracking = false;
private final ArrayList<WindowManagerInternal.AppTransitionListener> mLegacyListeners =
@@ -185,24 +178,6 @@ class TransitionController {
private final IBinder.DeathRecipient mTransitionPlayerDeath;
- /**
- * Tracks active perf sessions that boost frame rate and hint sf to increase its
- * estimated work duration.
- */
- private final ArraySet<HighPerfSession> mHighPerfSessions = new ArraySet<>();
-
-
- /**
- * Starts a perf hint session which will boost the refresh rate for the display and change
- * sf duration to handle larger workloads.
- */
- void startPerfHintForDisplay(int displayId) {
- if (explicitRefreshRateHints()) {
- mHighPerfSessions.add(mSystemPerformanceHinter.startSession(HINT_SF, displayId,
- "Transition collected"));
- }
- }
-
static class QueuedTransition {
final Transition mTransition;
final OnStartCollect mOnStartCollect;
@@ -282,16 +257,10 @@ class TransitionController {
mIsWaitingForDisplayEnabled = !wms.mDisplayEnabled;
registerLegacyListener(wms.mActivityManagerAppTransitionNotifier);
setSyncEngine(wms.mSyncEngine);
- setSystemPerformanceHinter(wms.mSystemPerformanceHinter);
mFullReadyTracking = Flags.transitReadyTracking();
}
@VisibleForTesting
- void setSystemPerformanceHinter(SystemPerformanceHinter hinter) {
- mSystemPerformanceHinter = hinter;
- }
-
- @VisibleForTesting
void setSyncEngine(BLASTSyncEngine syncEngine) {
mSyncEngine = syncEngine;
// Check the queue whenever the sync-engine becomes idle.
@@ -508,7 +477,7 @@ class TransitionController {
return false;
}
- /** @return {@code true} if wc is in a participant subtree */
+ /** Returns {@code true} if the display contains a running or pending transition. */
boolean isTransitionOnDisplay(@NonNull DisplayContent dc) {
if (mCollectingTransition != null && mCollectingTransition.isOnDisplay(dc)) {
return true;
@@ -1240,12 +1209,22 @@ class TransitionController {
}
}
- void updateAnimatingState(SurfaceControl.Transaction t) {
+ /** Returns {@code true} if a transition is playing or the collecting transition is started. */
+ boolean isAnimating() {
+ return mAnimatingState;
+ }
+
+ void updateAnimatingState() {
final boolean animatingState = !mPlayingTransitions.isEmpty()
|| (mCollectingTransition != null && mCollectingTransition.isStarted());
if (animatingState && !mAnimatingState) {
- if (!explicitRefreshRateHints()) {
- t.setEarlyWakeupStart();
+ // Note that Transition#start() can be called before adding participants, so the
+ // enableHighPerfTransition(true) is also called in Transition#recordDisplay.
+ for (int i = mAtm.mRootWindowContainer.getChildCount() - 1; i >= 0; i--) {
+ final DisplayContent dc = mAtm.mRootWindowContainer.getChildAt(i);
+ if (isTransitionOnDisplay(dc)) {
+ dc.enableHighPerfTransition(true);
+ }
}
// Usually transitions put quite a load onto the system already (with all the things
// happening in app), so pause task snapshot persisting to not increase the load.
@@ -1253,18 +1232,13 @@ class TransitionController {
mAnimatingState = true;
Transition.asyncTraceBegin("animating", 0x41bfaf1 /* hashcode of TAG */);
} else if (!animatingState && mAnimatingState) {
- if (!explicitRefreshRateHints()) {
- t.setEarlyWakeupEnd();
+ for (int i = mAtm.mRootWindowContainer.getChildCount() - 1; i >= 0; i--) {
+ mAtm.mRootWindowContainer.getChildAt(i).enableHighPerfTransition(false);
}
mAtm.mWindowManager.scheduleAnimationLocked();
mSnapshotController.setPause(false);
mAnimatingState = false;
Transition.asyncTraceEnd(0x41bfaf1 /* hashcode of TAG */);
- // We close all perf sessions here when all transitions finish. The sessions are created
- // when we collect transitions because we have access to the display id.
- for (HighPerfSession perfSession : mHighPerfSessions) {
- perfSession.close();
- }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index adc0595f305b..e95d2651504b 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -117,6 +117,9 @@ public class WindowAnimator {
scheduleAnimation();
final RootWindowContainer root = mService.mRoot;
+ final boolean useShellTransition = root.mTransitionController.isShellTransitionsEnabled();
+ final int animationFlags = useShellTransition ? CHILDREN : (TRANSITION | CHILDREN);
+ boolean rootAnimating = false;
mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
mBulkUpdateParams = 0;
root.mOrientationChangeComplete = true;
@@ -149,6 +152,17 @@ public class WindowAnimator {
accessibilityController.drawMagnifiedRegionBorderIfNeeded(dc.mDisplayId,
mTransaction);
}
+
+ if (dc.isAnimating(animationFlags, ANIMATION_TYPE_ALL)) {
+ rootAnimating = true;
+ if (!dc.mLastContainsRunningSurfaceAnimator) {
+ dc.mLastContainsRunningSurfaceAnimator = true;
+ dc.enableHighFrameRate(true);
+ }
+ } else if (dc.mLastContainsRunningSurfaceAnimator) {
+ dc.mLastContainsRunningSurfaceAnimator = false;
+ dc.enableHighFrameRate(false);
+ }
}
cancelAnimation();
@@ -168,8 +182,6 @@ public class WindowAnimator {
mService.mWindowPlacerLocked.requestTraversal();
}
- final boolean rootAnimating = root.isAnimating(TRANSITION | CHILDREN /* flags */,
- ANIMATION_TYPE_ALL /* typesToCheck */);
if (rootAnimating && !mLastRootAnimating) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
}
@@ -179,20 +191,10 @@ public class WindowAnimator {
}
mLastRootAnimating = rootAnimating;
- final boolean runningExpensiveAnimations =
- root.isAnimating(TRANSITION | CHILDREN /* flags */,
- ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_SCREEN_ROTATION
- | ANIMATION_TYPE_RECENTS /* typesToCheck */);
- if (runningExpensiveAnimations && !mRunningExpensiveAnimations) {
- // Usually app transitions put quite a load onto the system already (with all the things
- // happening in app), so pause snapshot persisting to not increase the load.
- mService.mSnapshotController.setPause(true);
- mTransaction.setEarlyWakeupStart();
- } else if (!runningExpensiveAnimations && mRunningExpensiveAnimations) {
- mService.mSnapshotController.setPause(false);
- mTransaction.setEarlyWakeupEnd();
+ // APP_TRANSITION, SCREEN_ROTATION, TYPE_RECENTS are handled by shell transition.
+ if (!useShellTransition) {
+ updateRunningExpensiveAnimationsLegacy();
}
- mRunningExpensiveAnimations = runningExpensiveAnimations;
SurfaceControl.mergeToGlobalTransaction(mTransaction);
mService.closeSurfaceTransaction("WindowAnimator");
@@ -208,6 +210,21 @@ public class WindowAnimator {
}
}
+ private void updateRunningExpensiveAnimationsLegacy() {
+ final boolean runningExpensiveAnimations =
+ mService.mRoot.isAnimating(TRANSITION | CHILDREN /* flags */,
+ ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_SCREEN_ROTATION
+ | ANIMATION_TYPE_RECENTS /* typesToCheck */);
+ if (runningExpensiveAnimations && !mRunningExpensiveAnimations) {
+ mService.mSnapshotController.setPause(true);
+ mTransaction.setEarlyWakeupStart();
+ } else if (!runningExpensiveAnimations && mRunningExpensiveAnimations) {
+ mService.mSnapshotController.setPause(false);
+ mTransaction.setEarlyWakeupEnd();
+ }
+ mRunningExpensiveAnimations = runningExpensiveAnimations;
+ }
+
private static String bulkUpdateParamsToString(int bulkUpdateParams) {
StringBuilder builder = new StringBuilder(128);
if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4a074ff25c74..a90e08e4f372 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1346,8 +1346,8 @@ public class WindowManagerService extends IWindowManager.Stub
DisplayContent dc = mRoot.getDisplayContent(displayId);
return (dc == null) ? null : dc.getSurfaceControl();
}
-
}, mTransactionFactory);
+ mSystemPerformanceHinter.mTraceTag = TRACE_TAG_WINDOW_MANAGER;
}
DisplayAreaPolicy.Provider getDisplayAreaPolicyProvider() {
@@ -7195,6 +7195,10 @@ public class WindowManagerService extends IWindowManager.Stub
pw.println(separator);
}
mConstants.dump(pw);
+ if (dumpAll) {
+ pw.println(separator);
+ }
+ mSystemPerformanceHinter.dump(pw, "");
}
}
diff --git a/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java b/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java
index 34e8ff2ec5c4..b8dcecdbfb95 100644
--- a/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java
+++ b/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java
@@ -30,8 +30,6 @@ import android.view.InputWindowHandle;
import android.view.Surface;
import android.view.SurfaceControl;
-import com.android.server.testutils.StubTransaction;
-
import java.util.HashSet;
import java.util.concurrent.Executor;
@@ -262,6 +260,18 @@ public class StubTransaction extends SurfaceControl.Transaction {
}
@Override
+ public SurfaceControl.Transaction setFrameRateCategory(SurfaceControl sc, int category,
+ boolean smoothSwitchOnly) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setFrameRateSelectionStrategy(SurfaceControl sc,
+ int strategy) {
+ return this;
+ }
+
+ @Override
public SurfaceControl.Transaction unsetColor(SurfaceControl sc) {
return this;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 47730237f675..baf259461847 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -2438,41 +2438,36 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testTransitionsTriggerPerformanceHints() {
- assumeTrue(explicitRefreshRateHints());
- SystemPerformanceHinter systemPerformanceHinter = mock(SystemPerformanceHinter.class);
- final TransitionController controller = new TestTransitionController(mAtm);
+ final boolean explicitRefreshRateHints = explicitRefreshRateHints();
+ final var session = new SystemPerformanceHinter.HighPerfSession[1];
+ if (explicitRefreshRateHints) {
+ final SystemPerformanceHinter perfHinter = mWm.mSystemPerformanceHinter;
+ spyOn(perfHinter);
+ doAnswer(invocation -> {
+ session[0] = (SystemPerformanceHinter.HighPerfSession) invocation.callRealMethod();
+ return session[0];
+ }).when(perfHinter).createSession(anyInt(), anyInt(), anyString());
+ }
+ final TransitionController controller = mDisplayContent.mTransitionController;
final TestTransitionPlayer player = registerTestTransitionPlayer();
-
- mSyncEngine = createTestBLASTSyncEngine();
- controller.setSyncEngine(mSyncEngine);
- controller.setSystemPerformanceHinter(systemPerformanceHinter);
- SystemPerformanceHinter.HighPerfSession session = mock(
- SystemPerformanceHinter.HighPerfSession.class);
- doReturn(session).when(systemPerformanceHinter).startSession(anyInt(), anyInt(),
- anyString());
-
+ final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true).build();
final Transition transitA = createTestTransition(TRANSIT_OPEN, controller);
- final Task task = createTask(mDisplayContent,
- WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
- final ActivityRecord act = createActivityRecord(task);
- act.setVisibleRequested(true);
- act.setVisible(true);
-
- controller.startCollectOrQueue(transitA, (deferred) -> {
- });
- transitA.collect(act);
-
- verify(systemPerformanceHinter).startSession(
- eq(SystemPerformanceHinter.HINT_SF), anyInt(), eq("Transition collected"));
+ controller.moveToCollecting(transitA);
+ transitA.collectExistenceChange(app);
+ controller.requestStartTransition(transitA, app.getTask(),
+ null /* remoteTransition */, null /* displayChange */);
+ player.start();
- transitA.start();
- transitA.setAllReady();
+ verify(mDisplayContent).enableHighPerfTransition(true);
+ if (explicitRefreshRateHints) {
+ verify(session[0]).start();
+ }
- // Aborting here doesn't abort the transition, it aborts the sync allowing the transition to
- // finish successfully.
- mSyncEngine.abort(transitA.getSyncId());
- controller.finishTransition(transitA);
- verify(session).close();
+ player.finish();
+ verify(mDisplayContent).enableHighPerfTransition(false);
+ if (explicitRefreshRateHints) {
+ verify(session[0]).close();
+ }
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index a82459fc1baa..55a00fc0ec89 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -293,6 +293,7 @@ public class WindowContainerTests extends WindowTestsBase {
public void testRemoveImmediatelyClearsLeash() {
final AnimationAdapter animAdapter = mock(AnimationAdapter.class);
final WindowToken token = createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDisplayContent);
+ mWm.mAnimator.ready();
final SurfaceControl.Transaction t = token.getPendingTransaction();
token.startAnimation(t, animAdapter, false /* hidden */,
SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION);
@@ -300,9 +301,14 @@ public class WindowContainerTests extends WindowTestsBase {
ArgumentCaptor.forClass(SurfaceControl.class);
verify(animAdapter).startAnimation(leashCaptor.capture(), eq(t), anyInt(), any());
assertTrue(token.mSurfaceAnimator.hasLeash());
+ waitUntilWindowAnimatorIdle();
+ verify(mDisplayContent).enableHighFrameRate(true);
+
token.removeImmediately();
assertFalse(token.mSurfaceAnimator.hasLeash());
verify(t).remove(eq(leashCaptor.getValue()));
+ waitUntilWindowAnimatorIdle();
+ verify(mDisplayContent).enableHighFrameRate(false);
}
@Test