From c1d2ff60f0f95cdfdfe8d89c9326ae5f16e7adc4 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 8 Nov 2018 16:50:12 -0800 Subject: [PATCH] [DO NOT MERGE] AM: Fix invalid hot launch app metrics seen with quickstep When quickstep is enabled, and the home button is pressed, AML receives two launches. The second launch is always incomplete. When an activity is then launched, the Launcher activity is treated as a trampoline activity and the launch will be reported as a hot launch with inflated times. The second launch is incomplete because we never get a window's drawn message for the second launch. We solve this by keeping track of windows drawn state in the Activity Record. If an activity is launched and its windows are already drawn, then we abort the launch metrics. Test: manual test with quickstep Test: atest ActivityMetricsLoggerTest Bug: 119221454 Change-Id: Id34a1c42c9b2ea356757109fedf5e2a1a3b020c8 --- .../server/am/ActivityMetricsLogger.java | 2 +- .../com/android/server/am/ActivityRecord.java | 10 ++++++++++ .../server/wm/AppWindowContainerController.java | 17 +++++++++++++++-- .../server/wm/AppWindowContainerListener.java | 2 ++ .../com/android/server/wm/AppWindowToken.java | 4 ++++ 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 552a162c18451..5cbd8fd1cd60d 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -372,7 +372,7 @@ class ActivityMetricsLogger { return; } - if (launchedActivity != null && launchedActivity.nowVisible) { + if (launchedActivity != null && launchedActivity.drawn) { // Launched activity is already visible. We cannot measure windows drawn delay. reset(true /* abort */, info); return; diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 1d7e00e182839..97ae3772ca3a5 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -308,6 +308,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // process that it is hidden. boolean sleeping; // have we told the activity to sleep? boolean nowVisible; // is this activity's window visible? + boolean drawn; // is this activity's window drawn? boolean mClientVisibilityDeferred;// was the visibility change message to client deferred? boolean idle; // has the activity gone idle? boolean hasBeenLaunched;// has this activity ever been launched? @@ -871,6 +872,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo inHistory = false; visible = false; nowVisible = false; + drawn = false; idle = false; hasBeenLaunched = false; mStackSupervisor = supervisor; @@ -1999,6 +2001,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo @Override public void onWindowsDrawn(long timestamp) { synchronized (service) { + drawn = true; final WindowingModeTransitionInfoSnapshot info = mStackSupervisor .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp); final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY; @@ -2012,6 +2015,13 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } } + @Override + public void onWindowsNotDrawn(long timestamp) { + synchronized (service) { + drawn = false; + } + } + @Override public void onWindowsVisible() { synchronized (service) { diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index 4f15c5d149fff..2e29931421893 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -18,9 +18,9 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; - import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS; import static android.view.WindowManager.TRANSIT_UNSET; + import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; @@ -65,6 +65,7 @@ public class AppWindowContainerController private final class H extends Handler { public static final int NOTIFY_WINDOWS_DRAWN = 1; public static final int NOTIFY_STARTING_WINDOW_DRAWN = 2; + public static final int NOTIFY_WINDOWS_NOTDRAWN = 3; public H(Looper looper) { super(looper); @@ -85,10 +86,18 @@ public class AppWindowContainerController if (mListener == null) { return; } - if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in " + if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting starting window drawn in " + AppWindowContainerController.this.mToken); mListener.onStartingWindowDrawn(msg.getWhen()); break; + case NOTIFY_WINDOWS_NOTDRAWN: + if (mListener == null) { + return; + } + if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting undrawn in " + + AppWindowContainerController.this.mToken); + mListener.onWindowsNotDrawn(msg.getWhen()); + break; default: break; } @@ -740,6 +749,10 @@ public class AppWindowContainerController mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_DRAWN)); } + void reportWindowsNotDrawn() { + mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_NOTDRAWN)); + } + void reportWindowsVisible() { mHandler.post(mOnWindowsVisible); } diff --git a/services/core/java/com/android/server/wm/AppWindowContainerListener.java b/services/core/java/com/android/server/wm/AppWindowContainerListener.java index 8a39a7408058e..9d2758a6b9e27 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerListener.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerListener.java @@ -20,6 +20,8 @@ package com.android.server.wm; public interface AppWindowContainerListener extends WindowContainerListener { /** Called when the windows associated app window container are drawn. */ void onWindowsDrawn(long timestamp); + /** Called when the windows associated app window container are no longer drawn. */ + default void onWindowsNotDrawn(long timestamp) {} /** Called when the windows associated app window container are visible. */ void onWindowsVisible(); /** Called when the windows associated app window container are no longer visible. */ diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index fa6079c51906e..bd5d35eae77d8 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -354,6 +354,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (controller != null) { controller.reportWindowsDrawn(); } + } else { + if (controller != null) { + controller.reportWindowsNotDrawn(); + } } reportedDrawn = nowDrawn; }