From 6bb5bedc5bfa35346fbaf0a1ebd43577c2143ce0 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Tue, 9 Nov 2021 23:17:24 -0600 Subject: [PATCH] Skip traversal of invisible visibility change The typical partial steps of making an existing activity visible: 1. handleAppVisibility: mAppVisible=true 2. performRestart: setWindowStopped(false) 3. performStart: Activity#makeVisible (View.VISIBLE) A stopped activity has root view visibility=INVISIBLE. So when changing mAppVisible to true, there will have an intermediate GONE->INVISIBLE (host visibility is GONE if mAppVisible is false). For root view, because it doesn't have parent, GONE and INVISIBLE are no different. It is also the same on window manager side that only cares about whehther it is visible or not. So the intermediate change can be skipped to reduce overhead. In setWindowStopped, change to use mAppVisibilityChanged to reduce the extra invocation of destroyHardwareResources(). Bug: 205693679 Test: CtsWindowManagerDeviceTestCases Change-Id: I16ac73e5f5b837e9946114bee73602bf8c8228a2 --- core/java/android/view/ViewRootImpl.java | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index b8215b5a83472..8744ae09a9a51 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1551,9 +1551,14 @@ public final class ViewRootImpl implements ViewParent, void handleAppVisibility(boolean visible) { if (mAppVisible != visible) { + final boolean previousVisible = getHostVisibility() == View.VISIBLE; mAppVisible = visible; - mAppVisibilityChanged = true; - scheduleTraversals(); + final boolean currentVisible = getHostVisibility() == View.VISIBLE; + // Root view only cares about whether it is visible or not. + if (previousVisible != currentVisible) { + mAppVisibilityChanged = true; + scheduleTraversals(); + } if (!mAppVisible) { WindowManagerGlobal.trimForeground(); } @@ -1843,8 +1848,13 @@ public final class ViewRootImpl implements ViewParent, renderer.setStopped(mStopped); } if (!mStopped) { - mNewSurfaceNeeded = true; - scheduleTraversals(); + // Unnecessary to traverse if the window is not yet visible. + if (getHostVisibility() == View.VISIBLE) { + // Make sure that relayoutWindow will be called to get valid surface because + // the previous surface may have been released. + mAppVisibilityChanged = true; + scheduleTraversals(); + } } else { if (renderer != null) { renderer.destroyHardwareResources(mView); @@ -2025,7 +2035,8 @@ public final class ViewRootImpl implements ViewParent, } int getHostVisibility() { - return (mAppVisible || mForceDecorViewVisibility) ? mView.getVisibility() : View.GONE; + return mView != null && (mAppVisible || mForceDecorViewVisibility) + ? mView.getVisibility() : View.GONE; } /**