summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java6
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java46
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java3
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java16
-rw-r--r--services/core/java/com/android/server/wm/Task.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfacePlacer.java10
7 files changed, 79 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 065dc6e4f8ed..c39cf91d6160 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -183,6 +183,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+import static com.android.server.wm.ActivityTaskManagerService.SKIP_LAYOUT_REASON_ALLOWED;
import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutMillisLocked;
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
@@ -5361,6 +5362,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mAtmService.deferWindowLayout();
try {
task.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
+ // If there is no possible transition to execute, then allow to skip layout
+ // because it may be done by next resumed activity.
+ if (!pausingActivity.mDisplayContent.areOpeningAppsReady()) {
+ mAtmService.addWindowLayoutReasons(SKIP_LAYOUT_REASON_ALLOWED);
+ }
} finally {
mAtmService.continueWindowLayout();
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 66e55e04d198..8262c59945c4 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1549,6 +1549,8 @@ class ActivityStarter {
mService.getTransitionController().collect(r);
try {
mService.deferWindowLayout();
+ // Allow to skip layout because it may be done by the window of the starting activity.
+ mService.addWindowLayoutReasons(ActivityTaskManagerService.SKIP_LAYOUT_REASON_ALLOWED);
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 37a9b8012cb7..28c6349a0e96 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -657,14 +657,27 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@IntDef({
LAYOUT_REASON_CONFIG_CHANGED,
LAYOUT_REASON_VISIBILITY_CHANGED,
+ SKIP_LAYOUT_REASON_ALLOWED,
+ SKIP_LAYOUT_REASON_EXPECT_NEXT_RELAYOUT,
})
@interface LayoutReason {
}
+ static final int LAYOUT_REASON_MASK = 0x0000ffff;
static final int LAYOUT_REASON_CONFIG_CHANGED = 0x1;
static final int LAYOUT_REASON_VISIBILITY_CHANGED = 0x2;
+ static final int SKIP_LAYOUT_REASON_MASK = 0xfffe0000;
- /** The reasons to perform surface placement. */
+ /**
+ * Allow to call {@link WindowSurfacePlacer#endDeferAndSkipLayout} if there is a reason
+ * included in {@link #SKIP_LAYOUT_REASON_MASK} was added.
+ */
+ static final int SKIP_LAYOUT_REASON_ALLOWED = 1 << 16;
+
+ /** Used when the client is scheduled to call relayout. */
+ static final int SKIP_LAYOUT_REASON_EXPECT_NEXT_RELAYOUT = 1 << 17;
+
+ /** The reasons to perform or skip surface placement. */
@LayoutReason
private int mLayoutReasons;
@@ -4187,18 +4200,35 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mWindowManager.mWindowPlacerLocked.deferLayout();
}
- /** @see WindowSurfacePlacer#continueLayout */
+ /**
+ * @see WindowSurfacePlacer#continueLayout
+ * @see WindowSurfacePlacer#endDeferAndSkipLayout
+ */
void continueWindowLayout() {
- mWindowManager.mWindowPlacerLocked.continueLayout(mLayoutReasons != 0);
- if (DEBUG_ALL && !mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
- Slog.i(TAG, "continueWindowLayout reason=" + mLayoutReasons);
+ if ((mLayoutReasons & SKIP_LAYOUT_REASON_ALLOWED) != 0) {
+ final int skipReasons = mLayoutReasons & SKIP_LAYOUT_REASON_MASK;
+ if (skipReasons != 0) {
+ if (DEBUG_ALL) {
+ Slog.i(TAG, "continueWindowLayout skip-reasons="
+ + Integer.toHexString(skipReasons));
+ }
+ mWindowManager.mWindowPlacerLocked.endDeferAndSkipLayout();
+ return;
+ }
+ }
+
+ final int reasons = mLayoutReasons & LAYOUT_REASON_MASK;
+ mWindowManager.mWindowPlacerLocked.continueLayout(reasons != 0);
+ if (DEBUG_ALL && reasons != 0 && !mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
+ Slog.i(TAG, "continueWindowLayout reasons=" + Integer.toHexString(reasons));
}
}
/**
- * If a reason is added between {@link #deferWindowLayout} and {@link #continueWindowLayout},
- * it will make sure {@link WindowSurfacePlacer#performSurfacePlacement} is called when the last
- * defer count is gone.
+ * If a reason within {@link #LAYOUT_REASON_MASK} is added between {@link #deferWindowLayout}
+ * and {@link #continueWindowLayout}, {@link WindowSurfacePlacer#performSurfacePlacement} will
+ * be called when the last defer count is gone. Note that the {@link #SKIP_LAYOUT_REASON_MASK}
+ * has higher priority to determine whether to perform layout.
*/
void addWindowLayoutReasons(@LayoutReason int reasons) {
mLayoutReasons |= reasons;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 7fe0f5be287c..b1404514f1f5 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -938,6 +938,9 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
if (r.app != null) {
r.app.updateServiceConnectionActivities();
}
+ // Expect a window of the starting activity will perform relayout.
+ mService.addWindowLayoutReasons(
+ ActivityTaskManagerService.SKIP_LAYOUT_REASON_EXPECT_NEXT_RELAYOUT);
return true;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d6bf46119cb1..343a4b541f2b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3995,6 +3995,22 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return mLayoutNeeded;
}
+ /** Returns {@code true} if all opening apps may be ready to execute transition. */
+ boolean areOpeningAppsReady() {
+ final int size = mOpeningApps.size();
+ for (int i = size - 1; i >= 0; i--) {
+ final ActivityRecord r = mOpeningApps.valueAt(i);
+ if (!r.hasVisible) {
+ return false;
+ }
+ final WindowState w = r.findMainWindow();
+ if (w != null && !w.isDrawn()) {
+ return false;
+ }
+ }
+ return size > 0;
+ }
+
void dumpTokens(PrintWriter pw, boolean dumpAll) {
if (mTokenMap.isEmpty()) {
return;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 93fc4f2a3149..8bb635e032a7 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -106,6 +106,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIB
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_TASK_MSG;
+import static com.android.server.wm.ActivityTaskManagerService.SKIP_LAYOUT_REASON_EXPECT_NEXT_RELAYOUT;
import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
@@ -6288,6 +6289,8 @@ class Task extends WindowContainer<WindowContainer> {
if (lastResumed != null) {
lastResumed.setWillCloseOrEnterPip(true);
}
+ // There may be a relayout from resuming next activity after the previous is paused.
+ mAtmService.addWindowLayoutReasons(SKIP_LAYOUT_REASON_EXPECT_NEXT_RELAYOUT);
return true;
} else if (mResumedActivity == next && next.isState(RESUMED)
&& taskDisplayArea.allResumedActivitiesComplete()) {
@@ -6497,6 +6500,7 @@ class Task extends WindowContainer<WindowContainer> {
ResumeActivityItem.obtain(next.app.getReportedProcState(),
dc.isNextTransitionForward()));
mAtmService.getLifecycleManager().scheduleTransaction(transaction);
+ mAtmService.addWindowLayoutReasons(SKIP_LAYOUT_REASON_EXPECT_NEXT_RELAYOUT);
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Resumed %s", next);
} catch (Exception e) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 2ee5fb01efb3..2d2b1f4ad322 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -101,6 +101,16 @@ class WindowSurfacePlacer {
}
}
+ /**
+ * Resumes layout passes but skip to perform layout even if there was a request. This can only
+ * be called when there will be another layout request from client side, e.g. an activity is
+ * starting or resuming. And there should be no other significant changes need to apply.
+ */
+ void endDeferAndSkipLayout() {
+ mDeferDepth--;
+ mDeferredRequests = 0;
+ }
+
boolean isLayoutDeferred() {
return mDeferDepth > 0;
}