From 6fe7b0757a8d1488bb4ad8d27e4f395ea5b1e1fd Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Fri, 14 Apr 2023 23:35:36 +0800 Subject: [PATCH] Set client invisible immediately for trampoline with window Since shell transition moves "commit invisible" from transition ready to transition finish. The relayout from a invisible-requested client may still enter WindowState#relayoutVisibleWindow because it is still client-visible. If the client is a trampoline activity, then it will draw an unnecessary frame because the client considers it needs to report draw complete for the first traversal. The flow: 1. Start activity A - Assume there is a starting window for it 2. A's onCreate starts activity B - Starting window is transferred from A to B - Schedule A to pause 3. A continues to resume and add its window, receive pause request 4. A completes paused - Resume B, set visibility to false for B - Assume starting window was drawn so trigger transition ready 5. A performs traversal by previous resume. - Relayout returns RELAYOUT_RES_FIRST_TIME if the client visibility ActivityRecord is true - ViewRootImpl executes reportNextDraw("first_relayout") Note that it has no such problem if the trampoline activity finishes itself right after starting next activity, because client will skip adding window by the finishing state. Bug: 277303796 Test: Launch an activity which starts another activity in its onCreate. Change-Id: I4196056b7f6b6161b431cb80444c9d86fef9492a --- .../core/java/com/android/server/wm/ActivityRecord.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 64e1ae5b8c9e5..68d60b0544227 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -5311,6 +5311,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (finishing || isState(STOPPED)) { displayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this); } + // Because starting window was transferred, this activity may be a trampoline which has + // been occluded by next activity. If it has added windows, set client visibility + // immediately to avoid the client getting RELAYOUT_RES_FIRST_TIME from relayout and + // drawing an unnecessary frame. + if (startingMoved && !firstWindowDrawn && hasChild()) { + setClientVisible(false); + } } else { if (!appTransition.isTransitionSet() && appTransition.isReady()) {