diff options
| author | 2018-12-13 10:29:46 -0800 | |
|---|---|---|
| committer | 2018-12-13 10:29:46 -0800 | |
| commit | bb9ab4b9142eed30d4927bed91bc618b78a891a8 (patch) | |
| tree | ccc01dbdfefa094555e38cb86f5572d33d331ef8 | |
| parent | bef4aa5f19f42daac2138f832baad3df7ec13f0f (diff) | |
AM: Report launch state with activity launch info
Bug: 119988524
Test: atest ActivityMetricsLoggerTests
Test: adb shell am start -W ...
Change-Id: I1d323e84d725722a198a60c51884dba897ec253f
6 files changed, 88 insertions, 8 deletions
diff --git a/core/java/android/app/WaitResult.java b/core/java/android/app/WaitResult.java index 5baf2e22bc31..ad9f680ad196 100644 --- a/core/java/android/app/WaitResult.java +++ b/core/java/android/app/WaitResult.java @@ -16,11 +16,14 @@ package android.app; +import android.annotation.IntDef; import android.content.ComponentName; import android.os.Parcel; import android.os.Parcelable; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Information returned after waiting for an activity start. @@ -28,11 +31,43 @@ import java.io.PrintWriter; * @hide */ public class WaitResult implements Parcelable { + + /** + * The state at which a launch sequence had started. + * + * @see <a href="https://developer.android.com/topic/performance/vitals/launch-time"App startup + * time</a> + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"LAUNCH_STATE_"}, value = { + LAUNCH_STATE_COLD, + LAUNCH_STATE_WARM, + LAUNCH_STATE_HOT + }) + public @interface LaunchState { + } + + /** + * Cold launch sequence: a new process has started. + */ + public static final int LAUNCH_STATE_COLD = 1; + + /** + * Warm launch sequence: process reused, but activity has to be created. + */ + public static final int LAUNCH_STATE_WARM = 2; + + /** + * Hot launch sequence: process reused, activity brought-to-top. + */ + public static final int LAUNCH_STATE_HOT = 3; + public static final int INVALID_DELAY = -1; public int result; public boolean timeout; public ComponentName who; public long totalTime; + public @LaunchState int launchState; public WaitResult() { } @@ -48,6 +83,7 @@ public class WaitResult implements Parcelable { dest.writeInt(timeout ? 1 : 0); ComponentName.writeToParcel(who, dest); dest.writeLong(totalTime); + dest.writeInt(launchState); } public static final Parcelable.Creator<WaitResult> CREATOR @@ -68,6 +104,7 @@ public class WaitResult implements Parcelable { timeout = source.readInt() != 0; who = ComponentName.readFromParcel(source); totalTime = source.readLong(); + launchState = source.readInt(); } public void dump(PrintWriter pw, String prefix) { @@ -76,5 +113,19 @@ public class WaitResult implements Parcelable { pw.println(prefix + " timeout=" + timeout); pw.println(prefix + " who=" + who); pw.println(prefix + " totalTime=" + totalTime); + pw.println(prefix + " launchState=" + launchState); + } + + public static String launchStateToString(@LaunchState int type) { + switch (type) { + case LAUNCH_STATE_COLD: + return "COLD"; + case LAUNCH_STATE_WARM: + return "WARM"; + case LAUNCH_STATE_HOT: + return "HOT"; + default: + return "UNKNOWN (" + type + ")"; + } } }
\ No newline at end of file diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 67a4d14a6edb..640593237144 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -20,6 +20,7 @@ import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM; import static android.app.ActivityTaskManager.RESIZE_MODE_USER; +import static android.app.WaitResult.launchStateToString; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; @@ -491,6 +492,7 @@ final class ActivityManagerShellCommand extends ShellCommand { final long endTime = SystemClock.uptimeMillis(); PrintWriter out = mWaitOption ? pw : getErrPrintWriter(); boolean launched = false; + boolean hotLaunch = false; switch (res) { case ActivityManager.START_SUCCESS: launched = true; @@ -516,6 +518,8 @@ final class ActivityManagerShellCommand extends ShellCommand { break; case ActivityManager.START_TASK_TO_FRONT: launched = true; + //TODO(b/120981435) remove special case + hotLaunch = true; out.println( "Warning: Activity not started, its current " + "task has been brought to the front"); @@ -563,6 +567,9 @@ final class ActivityManagerShellCommand extends ShellCommand { result.who = intent.getComponent(); } pw.println("Status: " + (result.timeout ? "timeout" : "ok")); + final @WaitResult.LaunchState int launchState = + hotLaunch ? WaitResult.LAUNCH_STATE_HOT : result.launchState; + pw.println("LaunchState: " + launchStateToString(launchState)); if (result.who != null) { pw.println("Activity: " + result.who.flattenToShortString()); } diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index 12690a99062e..102318262798 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -3,6 +3,9 @@ package com.android.server.wm; import static android.app.ActivityManager.START_SUCCESS; import static android.app.ActivityManager.START_TASK_TO_FRONT; import static android.app.ActivityManager.processStateAmToProto; +import static android.app.WaitResult.LAUNCH_STATE_COLD; +import static android.app.WaitResult.LAUNCH_STATE_HOT; +import static android.app.WaitResult.LAUNCH_STATE_WARM; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; @@ -80,6 +83,7 @@ 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.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT; +import android.app.WaitResult; import android.app.WindowConfiguration.WindowingMode; import android.content.Context; import android.content.Intent; @@ -101,10 +105,10 @@ import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.os.BackgroundThread; import com.android.internal.os.SomeArgs; -import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; /** @@ -259,6 +263,19 @@ class ActivityMetricsLogger { activityRecordIdHashCode = System.identityHashCode(launchedActivity); this.windowsFullyDrawnDelayMs = windowsFullyDrawnDelayMs; } + + @WaitResult.LaunchState int getLaunchState() { + switch (type) { + case TYPE_TRANSITION_WARM_LAUNCH: + return LAUNCH_STATE_WARM; + case TYPE_TRANSITION_HOT_LAUNCH: + return LAUNCH_STATE_HOT; + case TYPE_TRANSITION_COLD_LAUNCH: + return LAUNCH_STATE_COLD; + default: + return -1; + } + } } ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context, Looper looper) { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index daf4b8ba6d48..793da128697c 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -122,8 +122,7 @@ 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.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.RELAUNCH_REASON_WINDOWING_MODE_RESIZE; import static com.android.server.wm.IdentifierProto.HASH_CODE; import static com.android.server.wm.IdentifierProto.TITLE; import static com.android.server.wm.IdentifierProto.USER_ID; @@ -145,6 +144,7 @@ import android.app.ActivityOptions; import android.app.PendingIntent; import android.app.PictureInPictureParams; import android.app.ResultInfo; +import android.app.WaitResult.LaunchState; import android.app.servertransaction.ActivityConfigurationChangeItem; import android.app.servertransaction.ActivityLifecycleItem; import android.app.servertransaction.ActivityRelaunchItem; @@ -2158,7 +2158,7 @@ final class ActivityRecord extends ConfigurationContainer { .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle); if (info != null) { mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this, - info.windowsFullyDrawnDelayMs); + info.windowsFullyDrawnDelayMs, info.getLaunchState()); } } @@ -2182,8 +2182,9 @@ final class ActivityRecord extends ConfigurationContainer { final WindowingModeTransitionInfoSnapshot info = mStackSupervisor .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp); final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY; + final @LaunchState int launchState = info != null ? info.getLaunchState() : -1; mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this, - windowsDrawnDelayMs); + windowsDrawnDelayMs, launchState); mStackSupervisor.sendWaitingVisibleReportLocked(this); finishLaunchTickingLocked(); if (task != null) { diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index f3c5630b53f0..aad2b492b128 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -598,7 +598,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } } - void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r, long totalTime) { + void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r, long totalTime, + @WaitResult.LaunchState int launchState) { boolean changed = false; for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) { WaitResult w = mWaitingActivityLaunched.remove(i); @@ -609,6 +610,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { w.who = new ComponentName(r.info.packageName, r.info.name); } w.totalTime = totalTime; + w.launchState = launchState; // Do not modify w.result. } } @@ -1242,7 +1244,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); r.finishLaunchTickingLocked(); if (fromTimeout) { - reportActivityLaunchedLocked(fromTimeout, r, INVALID_DELAY); + reportActivityLaunchedLocked(fromTimeout, r, INVALID_DELAY, + -1 /* launchState */); } // This is a hack to semi-deal with a race condition diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java index eed8ae7c1f70..5ea8ff1c4861 100644 --- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java +++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java @@ -39,7 +39,6 @@ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -840,6 +839,7 @@ public class AppLaunch extends InstrumentationTestCase { /* SAMPLE OUTPUT : Cold launch Starting: Intent { cmp=com.google.android.calculator/com.android.calculator2.Calculator } Status: ok + LaunchState: COLD Activity: com.google.android.calculator/com.android.calculator2.Calculator TotalTime: 357 WaitTime: 377 @@ -848,6 +848,7 @@ public class AppLaunch extends InstrumentationTestCase { Starting: Intent { cmp=com.google.android.calculator/com.android.calculator2.Calculator } Warning: Activity not started, its current task has been brought to the front Status: ok + LaunchState: HOT Activity: com.google.android.calculator/com.android.calculator2.CalculatorGoogle TotalTime: 60 WaitTime: 67 |