Merge "[DO NOT MERGE] AM: Use ActivityMetricsLogger to get app launch times" into pi-dev
am: a6fc25f6d3
Change-Id: I4bcc8c3a777d6537788b38cd27b2f670fbb9770b
diff --git a/core/java/android/app/WaitResult.java b/core/java/android/app/WaitResult.java
index 898d0ca..5baf2e2 100644
--- a/core/java/android/app/WaitResult.java
+++ b/core/java/android/app/WaitResult.java
@@ -28,10 +28,10 @@
* @hide
*/
public class WaitResult implements Parcelable {
+ public static final int INVALID_DELAY = -1;
public int result;
public boolean timeout;
public ComponentName who;
- public long thisTime;
public long totalTime;
public WaitResult() {
@@ -47,7 +47,6 @@
dest.writeInt(result);
dest.writeInt(timeout ? 1 : 0);
ComponentName.writeToParcel(who, dest);
- dest.writeLong(thisTime);
dest.writeLong(totalTime);
}
@@ -68,7 +67,6 @@
result = source.readInt();
timeout = source.readInt() != 0;
who = ComponentName.readFromParcel(source);
- thisTime = source.readLong();
totalTime = source.readLong();
}
@@ -77,7 +75,6 @@
pw.println(prefix + " result=" + result);
pw.println(prefix + " timeout=" + timeout);
pw.println(prefix + " who=" + who);
- pw.println(prefix + " thisTime=" + thisTime);
pw.println(prefix + " totalTime=" + totalTime);
}
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7234ed4..7e3c28a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5893,7 +5893,6 @@
private final void handleAppDiedLocked(ProcessRecord app,
boolean restarting, boolean allowRestart) {
int pid = app.pid;
- final boolean clearLaunchStartTime = !restarting && app.removed && app.foregroundActivities;
boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
false /*replacingPid*/);
if (!kept && !restarting) {
@@ -5935,18 +5934,6 @@
mWindowManager.continueSurfaceLayout();
}
- // Hack for pi
- // When an app process is removed, activities from the process may be relaunched. In the
- // case of forceStopPackageLocked the activities are finished before any window is drawn,
- // and the launch time is not cleared. This will be incorrectly used to calculate launch
- // time for the next launched activity launched in the same windowing mode.
- if (clearLaunchStartTime) {
- final LaunchTimeTracker.Entry entry = mStackSupervisor
- .getLaunchTimeTracker().getEntry(mStackSupervisor.getWindowingMode());
- if (entry != null) {
- entry.mLaunchStartTime = 0;
- }
- }
}
private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 093bd87..ccbc8ed 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -558,9 +558,6 @@
if (result.who != null) {
pw.println("Activity: " + result.who.flattenToShortString());
}
- if (result.thisTime >= 0) {
- pw.println("ThisTime: " + result.thisTime);
- }
if (result.totalTime >= 0) {
pw.println("TotalTime: " + result.totalTime);
}
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 9ffa662..552a162 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -4,12 +4,13 @@
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityManager.processStateAmToProto;
import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_ACTIVITY_START;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_BIND_APPLICATION_DELAY_MS;
@@ -28,9 +29,9 @@
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_LAUNCH_MODE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_LAUNCH_MODE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_PROCESS_NAME;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_REAL_ACTIVITY;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME;
@@ -57,16 +58,16 @@
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PENDING_UI_CLEAN;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PROCESS_NAME;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_PROC_STATE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_PROC_STATE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_PACKAGE_NAME;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_SHORT_COMPONENT_NAME;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_PROC_STATE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_WHITELIST_TAG;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_REASON;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_FILTER;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_REASON;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
@@ -75,6 +76,7 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_METRICS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME;
import static com.android.server.am.MemoryStatUtil.MemoryStat;
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
@@ -88,10 +90,14 @@
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
+import android.os.Trace;
+import android.util.EventLog;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.StatsLog;
+import android.util.TimeUtils;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.BackgroundThread;
@@ -101,7 +107,12 @@
import java.util.ArrayList;
/**
- * Handles logging into Tron.
+ * Listens to activity launches, transitions, visibility changes and window drawn callbacks to
+ * determine app launch times and draw delays. Source of truth for activity metrics and provides
+ * data for Tron, logcat, event logs and {@link android.app.WaitResult}.
+ *
+ * Tests:
+ * atest CtsActivityManagerDeviceTestCases:ActivityMetricsLoggerTests
*/
class ActivityMetricsLogger {
@@ -116,6 +127,8 @@
private static final int WINDOW_STATE_INVALID = -1;
private static final long INVALID_START_TIME = -1;
+ private static final int INVALID_DELAY = -1;
+ private static final int INVALID_TRANSITION_TYPE = -1;
private static final int MSG_CHECK_VISIBILITY = 0;
@@ -144,6 +157,8 @@
private final H mHandler;
private ArtManagerInternal mArtManagerInternal;
+ private boolean mDrawingTraceActive;
+ private final StringBuilder mStringBuilder = new StringBuilder();
private final class H extends Handler {
@@ -166,45 +181,69 @@
private ActivityRecord launchedActivity;
private int startResult;
private boolean currentTransitionProcessRunning;
+ /** Elapsed time from when we launch an activity to when its windows are drawn. */
private int windowsDrawnDelayMs;
- private int startingWindowDelayMs = -1;
- private int bindApplicationDelayMs = -1;
+ private int startingWindowDelayMs = INVALID_DELAY;
+ private int bindApplicationDelayMs = INVALID_DELAY;
private int reason = APP_TRANSITION_TIMEOUT;
private boolean loggedWindowsDrawn;
private boolean loggedStartingWindowDrawn;
+ private boolean launchTraceActive;
}
- private final class WindowingModeTransitionInfoSnapshot {
+ final class WindowingModeTransitionInfoSnapshot {
final private ApplicationInfo applicationInfo;
final private ProcessRecord processRecord;
- final private String packageName;
- final private String launchedActivityName;
+ final String packageName;
+ final String launchedActivityName;
final private String launchedActivityLaunchedFromPackage;
final private String launchedActivityLaunchToken;
final private String launchedActivityAppRecordRequiredAbi;
+ final String launchedActivityShortComponentName;
final private String processName;
final private int reason;
final private int startingWindowDelayMs;
final private int bindApplicationDelayMs;
- final private int windowsDrawnDelayMs;
- final private int type;
+ final int windowsDrawnDelayMs;
+ final int type;
+ final int userId;
+ /**
+ * Elapsed time from when we launch an activity to when the app reported it was
+ * fully drawn. If this is not reported then the value is set to INVALID_DELAY.
+ */
+ final int windowsFullyDrawnDelayMs;
+ final int activityRecordIdHashCode;
private WindowingModeTransitionInfoSnapshot(WindowingModeTransitionInfo info) {
- applicationInfo = info.launchedActivity.appInfo;
- packageName = info.launchedActivity.packageName;
- launchedActivityName = info.launchedActivity.info.name;
- launchedActivityLaunchedFromPackage = info.launchedActivity.launchedFromPackage;
- launchedActivityLaunchToken = info.launchedActivity.info.launchToken;
- launchedActivityAppRecordRequiredAbi = info.launchedActivity.app == null
+ this(info, info.launchedActivity);
+ }
+
+ private WindowingModeTransitionInfoSnapshot(WindowingModeTransitionInfo info,
+ ActivityRecord launchedActivity) {
+ this(info, launchedActivity, INVALID_DELAY);
+ }
+
+ private WindowingModeTransitionInfoSnapshot(WindowingModeTransitionInfo info,
+ ActivityRecord launchedActivity, int windowsFullyDrawnDelayMs) {
+ applicationInfo = launchedActivity.appInfo;
+ packageName = launchedActivity.packageName;
+ launchedActivityName = launchedActivity.info.name;
+ launchedActivityLaunchedFromPackage = launchedActivity.launchedFromPackage;
+ launchedActivityLaunchToken = launchedActivity.info.launchToken;
+ launchedActivityAppRecordRequiredAbi = launchedActivity.app == null
? null
- : info.launchedActivity.app.requiredAbi;
+ : launchedActivity.app.requiredAbi;
reason = info.reason;
startingWindowDelayMs = info.startingWindowDelayMs;
bindApplicationDelayMs = info.bindApplicationDelayMs;
windowsDrawnDelayMs = info.windowsDrawnDelayMs;
type = getTransitionType(info);
- processRecord = findProcessForActivity(info.launchedActivity);
- processName = info.launchedActivity.processName;
+ processRecord = findProcessForActivity(launchedActivity);
+ processName = launchedActivity.processName;
+ userId = launchedActivity.userId;
+ launchedActivityShortComponentName = launchedActivity.shortComponentName;
+ activityRecordIdHashCode = System.identityHashCode(launchedActivity);
+ this.windowsFullyDrawnDelayMs = windowsFullyDrawnDelayMs;
}
}
@@ -324,18 +363,24 @@
+ " processRunning=" + processRunning
+ " processSwitch=" + processSwitch);
- // If we are already in an existing transition, only update the activity name, but not the
- // other attributes.
final int windowingMode = launchedActivity != null
? launchedActivity.getWindowingMode()
: WINDOWING_MODE_UNDEFINED;
-
+ final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
if (mCurrentTransitionStartTime == INVALID_START_TIME) {
+ // No transition is active ignore this launch.
return;
}
- final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
+ if (launchedActivity != null && launchedActivity.nowVisible) {
+ // Launched activity is already visible. We cannot measure windows drawn delay.
+ reset(true /* abort */, info);
+ return;
+ }
+
if (launchedActivity != null && info != null) {
+ // If we are already in an existing transition, only update the activity name, but not
+ // the other attributes.
info.launchedActivity = launchedActivity;
return;
}
@@ -344,9 +389,8 @@
mWindowingModeTransitionInfo.size() > 0 && info == null;
if ((!isLoggableResultCode(resultCode) || launchedActivity == null || !processSwitch
|| windowingMode == WINDOWING_MODE_UNDEFINED) && !otherWindowModesLaunching) {
-
// Failed to launch or it was not a process switch, so we don't care about the timing.
- reset(true /* abort */);
+ reset(true /* abort */, info);
return;
} else if (otherWindowModesLaunching) {
// Don't log this windowing mode but continue with the other windowing modes.
@@ -362,6 +406,7 @@
mWindowingModeTransitionInfo.put(windowingMode, newInfo);
mLastWindowingModeTransitionInfo.put(windowingMode, newInfo);
mCurrentTransitionDeviceUptime = (int) (SystemClock.uptimeMillis() / 1000);
+ startTraces(newInfo);
}
/**
@@ -375,18 +420,21 @@
/**
* Notifies the tracker that all windows of the app have been drawn.
*/
- void notifyWindowsDrawn(int windowingMode, long timestamp) {
+ WindowingModeTransitionInfoSnapshot notifyWindowsDrawn(int windowingMode, long timestamp) {
if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn windowingMode=" + windowingMode);
final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
if (info == null || info.loggedWindowsDrawn) {
- return;
+ return null;
}
info.windowsDrawnDelayMs = calculateDelay(timestamp);
info.loggedWindowsDrawn = true;
+ final WindowingModeTransitionInfoSnapshot infoSnapshot =
+ new WindowingModeTransitionInfoSnapshot(info);
if (allWindowsDrawn() && mLoggedTransitionStarting) {
- reset(false /* abort */);
+ reset(false /* abort */, info);
}
+ return infoSnapshot;
}
/**
@@ -405,7 +453,7 @@
* Notifies the tracker that the app transition is starting.
*
* @param windowingModeToReason A map from windowing mode to a reason integer, which must be on
- * of ActivityManagerInternal.APP_TRANSITION_* reasons.
+ * of ActivityTaskManagerInternal.APP_TRANSITION_* reasons.
*/
void notifyTransitionStarting(SparseIntArray windowingModeToReason, long timestamp) {
if (!isAnyTransitionActive() || mLoggedTransitionStarting) {
@@ -424,7 +472,7 @@
info.reason = windowingModeToReason.valueAt(index);
}
if (allWindowsDrawn()) {
- reset(false /* abort */);
+ reset(false /* abort */, null /* WindowingModeTransitionInfo */);
}
}
@@ -463,8 +511,9 @@
logAppTransitionCancel(info);
mWindowingModeTransitionInfo.remove(r.getWindowingMode());
if (mWindowingModeTransitionInfo.size() == 0) {
- reset(true /* abort */);
+ reset(true /* abort */, info);
}
+ stopFullyDrawnTraceIfNeeded();
}
}
}
@@ -499,19 +548,19 @@
&& mWindowingModeTransitionInfo.size() > 0;
}
- private void reset(boolean abort) {
+ private void reset(boolean abort, WindowingModeTransitionInfo info) {
if (DEBUG_METRICS) Slog.i(TAG, "reset abort=" + abort);
if (!abort && isAnyTransitionActive()) {
logAppTransitionMultiEvents();
}
+ stopLaunchTrace(info);
mCurrentTransitionStartTime = INVALID_START_TIME;
- mCurrentTransitionDelayMs = -1;
+ mCurrentTransitionDelayMs = INVALID_DELAY;
mLoggedTransitionStarting = false;
mWindowingModeTransitionInfo.clear();
}
private int calculateCurrentDelay() {
-
// Shouldn't take more than 25 days to launch an app, so int is fine here.
return (int) (SystemClock.uptimeMillis() - mCurrentTransitionStartTime);
}
@@ -523,7 +572,7 @@
private void logAppTransitionCancel(WindowingModeTransitionInfo info) {
final int type = getTransitionType(info);
- if (type == -1) {
+ if (type == INVALID_TRANSITION_TYPE) {
return;
}
final LogMaker builder = new LogMaker(APP_TRANSITION_CANCELLED);
@@ -544,7 +593,7 @@
for (int index = mWindowingModeTransitionInfo.size() - 1; index >= 0; index--) {
final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.valueAt(index);
final int type = getTransitionType(info);
- if (type == -1) {
+ if (type == INVALID_TRANSITION_TYPE) {
return;
}
@@ -556,6 +605,7 @@
final int currentTransitionDelayMs = mCurrentTransitionDelayMs;
BackgroundThread.getHandler().post(() -> logAppTransition(
currentTransitionDeviceUptime, currentTransitionDelayMs, infoSnapshot));
+ BackgroundThread.getHandler().post(() -> logAppDisplayed(infoSnapshot));
info.launchedActivity.info.launchToken = null;
}
@@ -582,11 +632,11 @@
currentTransitionDeviceUptime);
builder.addTaggedData(APP_TRANSITION_DELAY_MS, currentTransitionDelayMs);
builder.setSubtype(info.reason);
- if (info.startingWindowDelayMs != -1) {
+ if (info.startingWindowDelayMs != INVALID_DELAY) {
builder.addTaggedData(APP_TRANSITION_STARTING_WINDOW_DELAY_MS,
info.startingWindowDelayMs);
}
- if (info.bindApplicationDelayMs != -1) {
+ if (info.bindApplicationDelayMs != INVALID_DELAY) {
builder.addTaggedData(APP_TRANSITION_BIND_APPLICATION_DELAY_MS,
info.bindApplicationDelayMs);
}
@@ -623,6 +673,24 @@
logAppStartMemoryStateCapture(info);
}
+ private void logAppDisplayed(WindowingModeTransitionInfoSnapshot info) {
+ if (info.type != TYPE_TRANSITION_WARM_LAUNCH && info.type != TYPE_TRANSITION_COLD_LAUNCH) {
+ return;
+ }
+
+ EventLog.writeEvent(AM_ACTIVITY_LAUNCH_TIME,
+ info.userId, info.activityRecordIdHashCode, info.launchedActivityShortComponentName,
+ info.windowsDrawnDelayMs);
+
+ StringBuilder sb = mStringBuilder;
+ sb.setLength(0);
+ sb.append("Displayed ");
+ sb.append(info.launchedActivityShortComponentName);
+ sb.append(": ");
+ TimeUtils.formatDuration(info.windowsDrawnDelayMs, sb);
+ Log.i(TAG, sb.toString());
+ }
+
private int convertAppStartTransitionType(int tronType) {
if (tronType == TYPE_TRANSITION_COLD_LAUNCH) {
return StatsLog.APP_START_OCCURRED__TYPE__COLD;
@@ -636,11 +704,12 @@
return StatsLog.APP_START_OCCURRED__TYPE__UNKNOWN;
}
- void logAppTransitionReportedDrawn(ActivityRecord r, boolean restoredFromBundle) {
+ WindowingModeTransitionInfoSnapshot logAppTransitionReportedDrawn(ActivityRecord r,
+ boolean restoredFromBundle) {
final WindowingModeTransitionInfo info = mLastWindowingModeTransitionInfo.get(
r.getWindowingMode());
if (info == null) {
- return;
+ return null;
}
final LogMaker builder = new LogMaker(APP_TRANSITION_REPORTED_DRAWN);
builder.setPackageName(r.packageName);
@@ -663,6 +732,25 @@
info.launchedActivity.info.name,
info.currentTransitionProcessRunning,
startupTimeMs);
+ stopFullyDrawnTraceIfNeeded();
+ final WindowingModeTransitionInfoSnapshot infoSnapshot =
+ new WindowingModeTransitionInfoSnapshot(info, r, (int) startupTimeMs);
+ BackgroundThread.getHandler().post(() -> logAppFullyDrawn(infoSnapshot));
+ return infoSnapshot;
+ }
+
+ private void logAppFullyDrawn(WindowingModeTransitionInfoSnapshot info) {
+ if (info.type != TYPE_TRANSITION_WARM_LAUNCH && info.type != TYPE_TRANSITION_COLD_LAUNCH) {
+ return;
+ }
+
+ StringBuilder sb = mStringBuilder;
+ sb.setLength(0);
+ sb.append("Fully drawn ");
+ sb.append(info.launchedActivityShortComponentName);
+ sb.append(": ");
+ TimeUtils.formatDuration(info.windowsFullyDrawnDelayMs, sb);
+ Log.i(TAG, sb.toString());
}
void logActivityStart(Intent intent, ProcessRecord callerApp, ActivityRecord r,
@@ -764,7 +852,7 @@
} else if (info.startResult == START_SUCCESS) {
return TYPE_TRANSITION_COLD_LAUNCH;
}
- return -1;
+ return INVALID_TRANSITION_TYPE;
}
private void logAppStartMemoryStateCapture(WindowingModeTransitionInfoSnapshot info) {
@@ -809,4 +897,46 @@
}
return mArtManagerInternal;
}
+
+ /**
+ * Starts traces for app launch and draw times. We stop the fully drawn trace if its already
+ * active since the app may not have reported fully drawn in the previous launch.
+ *
+ * See {@link android.app.Activity#reportFullyDrawn()}
+ *
+ * @param info
+ * */
+ private void startTraces(WindowingModeTransitionInfo info) {
+ if (info == null) {
+ return;
+ }
+ stopFullyDrawnTraceIfNeeded();
+ int transitionType = getTransitionType(info);
+ if (!info.launchTraceActive && transitionType == TYPE_TRANSITION_WARM_LAUNCH
+ || transitionType == TYPE_TRANSITION_COLD_LAUNCH) {
+ Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: "
+ + info.launchedActivity.packageName, 0);
+ Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
+ mDrawingTraceActive = true;
+ info.launchTraceActive = true;
+ }
+ }
+
+ private void stopLaunchTrace(WindowingModeTransitionInfo info) {
+ if (info == null) {
+ return;
+ }
+ if (info.launchTraceActive) {
+ Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: "
+ + info.launchedActivity.packageName, 0);
+ info.launchTraceActive = false;
+ }
+ }
+
+ void stopFullyDrawnTraceIfNeeded() {
+ if (mDrawingTraceActive) {
+ Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
+ mDrawingTraceActive = false;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 60f79f72..1d7e00e 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -31,6 +31,7 @@
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
+import static android.app.WaitResult.INVALID_DELAY;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -80,7 +81,6 @@
import static android.os.Build.VERSION_CODES.HONEYCOMB;
import static android.os.Build.VERSION_CODES.O;
import static android.os.Process.SYSTEM_UID;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
@@ -103,8 +103,6 @@
import static com.android.server.am.ActivityStack.LAUNCH_TICK_MSG;
import static com.android.server.am.ActivityStack.PAUSE_TIMEOUT_MSG;
import static com.android.server.am.ActivityStack.STOP_TIMEOUT_MSG;
-import static com.android.server.am.EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME;
-import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME;
import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
import static com.android.server.am.TaskPersister.DEBUG;
@@ -163,7 +161,6 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.service.voice.IVoiceInteractionSession;
@@ -185,6 +182,7 @@
import com.android.internal.util.XmlUtils;
import com.android.server.AttributeCache;
import com.android.server.AttributeCache.Entry;
+import com.android.server.am.ActivityMetricsLogger.WindowingModeTransitionInfoSnapshot;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.wm.AppWindowContainerController;
import com.android.server.wm.AppWindowContainerListener;
@@ -264,9 +262,6 @@
private int windowFlags; // custom window flags for preview window.
private TaskRecord task; // the task this is in.
private long createTime = System.currentTimeMillis();
- long displayStartTime; // when we started launching this activity
- long fullyDrawnStartTime; // when we started launching this activity
- private long startTime; // last time this activity was started
long lastVisibleTime; // last time this activity became visible
long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity
long pauseTime; // last time we started pausing the activity
@@ -523,15 +518,6 @@
pw.print("requestedVrComponent=");
pw.println(requestedVrComponent);
}
- if (displayStartTime != 0 || startTime != 0) {
- pw.print(prefix); pw.print("displayStartTime=");
- if (displayStartTime == 0) pw.print("0");
- else TimeUtils.formatDuration(displayStartTime, now, pw);
- pw.print(" startTime=");
- if (startTime == 0) pw.print("0");
- else TimeUtils.formatDuration(startTime, now, pw);
- pw.println();
- }
final boolean waitingVisible =
mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this);
if (lastVisibleTime != 0 || waitingVisible || nowVisible) {
@@ -1995,79 +1981,13 @@
}
public void reportFullyDrawnLocked(boolean restoredFromBundle) {
- final long curTime = SystemClock.uptimeMillis();
- if (displayStartTime != 0) {
- reportLaunchTimeLocked(curTime);
+ final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
+ .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
+ if (info != null) {
+ mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
+ info.windowsFullyDrawnDelayMs);
}
- final LaunchTimeTracker.Entry entry = mStackSupervisor.getLaunchTimeTracker().getEntry(
- getWindowingMode());
- if (fullyDrawnStartTime != 0 && entry != null) {
- final long thisTime = curTime - fullyDrawnStartTime;
- final long totalTime = entry.mFullyDrawnStartTime != 0
- ? (curTime - entry.mFullyDrawnStartTime) : thisTime;
- if (SHOW_ACTIVITY_START_TIME) {
- Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
- EventLog.writeEvent(AM_ACTIVITY_FULLY_DRAWN_TIME,
- userId, System.identityHashCode(this), shortComponentName,
- thisTime, totalTime);
- StringBuilder sb = service.mStringBuilder;
- sb.setLength(0);
- sb.append("Fully drawn ");
- sb.append(shortComponentName);
- sb.append(": ");
- TimeUtils.formatDuration(thisTime, sb);
- if (thisTime != totalTime) {
- sb.append(" (total ");
- TimeUtils.formatDuration(totalTime, sb);
- sb.append(")");
- }
- Log.i(TAG, sb.toString());
- }
- if (totalTime > 0) {
- //service.mUsageStatsService.noteFullyDrawnTime(realActivity, (int) totalTime);
- }
- entry.mFullyDrawnStartTime = 0;
- }
- mStackSupervisor.getActivityMetricsLogger().logAppTransitionReportedDrawn(this,
- restoredFromBundle);
- fullyDrawnStartTime = 0;
}
-
- private void reportLaunchTimeLocked(final long curTime) {
- final LaunchTimeTracker.Entry entry = mStackSupervisor.getLaunchTimeTracker().getEntry(
- getWindowingMode());
- if (entry == null) {
- return;
- }
- final long thisTime = curTime - displayStartTime;
- final long totalTime = entry.mLaunchStartTime != 0
- ? (curTime - entry.mLaunchStartTime) : thisTime;
- if (SHOW_ACTIVITY_START_TIME) {
- Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
- EventLog.writeEvent(AM_ACTIVITY_LAUNCH_TIME,
- userId, System.identityHashCode(this), shortComponentName,
- thisTime, totalTime);
- StringBuilder sb = service.mStringBuilder;
- sb.setLength(0);
- sb.append("Displayed ");
- sb.append(shortComponentName);
- sb.append(": ");
- TimeUtils.formatDuration(thisTime, sb);
- if (thisTime != totalTime) {
- sb.append(" (total ");
- TimeUtils.formatDuration(totalTime, sb);
- sb.append(")");
- }
- Log.i(TAG, sb.toString());
- }
- mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
- if (totalTime > 0) {
- //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
- }
- displayStartTime = 0;
- entry.mLaunchStartTime = 0;
- }
-
@Override
public void onStartingWindowDrawn(long timestamp) {
synchronized (service) {
@@ -2079,13 +1999,12 @@
@Override
public void onWindowsDrawn(long timestamp) {
synchronized (service) {
- mStackSupervisor.getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(),
- timestamp);
- if (displayStartTime != 0) {
- reportLaunchTimeLocked(timestamp);
- }
+ final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
+ .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp);
+ final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
+ mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
+ windowsDrawnDelayMs);
mStackSupervisor.sendWaitingVisibleReportLocked(this);
- startTime = 0;
finishLaunchTickingLocked();
if (task != null) {
task.hasBeenVisible = true;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index f58f717..aa5aa70 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1254,16 +1254,13 @@
+ " callers=" + Debug.getCallers(5));
r.setState(RESUMED, "minimalResumeActivityLocked");
r.completeResumeLocked();
- mStackSupervisor.getLaunchTimeTracker().setLaunchTime(r);
if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
"Launch completed; removing icicle of " + r.icicle);
}
private void clearLaunchTime(ActivityRecord r) {
// Make sure that there is no activity waiting for this to launch.
- if (mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
- r.displayStartTime = r.fullyDrawnStartTime = 0;
- } else {
+ if (!mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
mStackSupervisor.removeTimeoutsForActivityLocked(r);
mStackSupervisor.scheduleIdleTimeoutLocked(r);
}
@@ -1449,7 +1446,7 @@
prev.getTask().touchActiveTime();
clearLaunchTime(prev);
- mStackSupervisor.getLaunchTimeTracker().stopFullyDrawnTraceIfNeeded(getWindowingMode());
+ mStackSupervisor.getActivityMetricsLogger().stopFullyDrawnTraceIfNeeded();
mService.updateCpuStats();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 2ae056f..f08a3b9 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -27,6 +27,7 @@
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
+import static android.app.WaitResult.INVALID_DELAY;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -445,7 +446,6 @@
private boolean mTaskLayersChanged = true;
private ActivityMetricsLogger mActivityMetricsLogger;
- private LaunchTimeTracker mLaunchTimeTracker = new LaunchTimeTracker();
private final ArrayList<ActivityRecord> mTmpActivityList = new ArrayList<>();
@@ -630,10 +630,6 @@
return mActivityMetricsLogger;
}
- LaunchTimeTracker getLaunchTimeTracker() {
- return mLaunchTimeTracker;
- }
-
public KeyguardController getKeyguardController() {
return mKeyguardController;
}
@@ -1121,8 +1117,8 @@
}
}
- void waitActivityVisible(ComponentName name, WaitResult result) {
- final WaitInfo waitInfo = new WaitInfo(name, result);
+ void waitActivityVisible(ComponentName name, WaitResult result, long startTimeMs) {
+ final WaitInfo waitInfo = new WaitInfo(name, result, startTimeMs);
mWaitingForActivityVisible.add(waitInfo);
}
@@ -1153,8 +1149,7 @@
changed = true;
result.timeout = false;
result.who = w.getComponent();
- result.totalTime = SystemClock.uptimeMillis() - result.thisTime;
- result.thisTime = result.totalTime;
+ result.totalTime = SystemClock.uptimeMillis() - w.getStartTime();
mWaitingForActivityVisible.remove(w);
}
}
@@ -1193,8 +1188,7 @@
}
}
- void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
- long thisTime, long totalTime) {
+ void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r, long totalTime) {
boolean changed = false;
for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
WaitResult w = mWaitingActivityLaunched.remove(i);
@@ -1204,7 +1198,6 @@
if (r != null) {
w.who = new ComponentName(r.info.packageName, r.info.name);
}
- w.thisTime = thisTime;
w.totalTime = totalTime;
// Do not modify w.result.
}
@@ -1688,8 +1681,6 @@
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
- getLaunchTimeTracker().setLaunchTime(r);
-
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
@@ -2027,7 +2018,7 @@
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
r.finishLaunchTickingLocked();
if (fromTimeout) {
- reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
+ reportActivityLaunchedLocked(fromTimeout, r, INVALID_DELAY);
}
// This is a hack to semi-deal with a race condition
@@ -4916,10 +4907,13 @@
static class WaitInfo {
private final ComponentName mTargetComponent;
private final WaitResult mResult;
+ /** Time stamp when we started to wait for {@link WaitResult}. */
+ private final long mStartTimeMs;
- public WaitInfo(ComponentName targetComponent, WaitResult result) {
+ WaitInfo(ComponentName targetComponent, WaitResult result, long startTimeMs) {
this.mTargetComponent = targetComponent;
this.mResult = result;
+ this.mStartTimeMs = startTimeMs;
}
public boolean matches(ComponentName targetComponent) {
@@ -4930,6 +4924,10 @@
return mResult;
}
+ public long getStartTime() {
+ return mStartTimeMs;
+ }
+
public ComponentName getComponent() {
return mTargetComponent;
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 00ba3a6..a739af9 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1174,6 +1174,9 @@
mService.updateConfigurationLocked(globalConfig, null, false);
}
+ // Notify ActivityMetricsLogger that the activity has launched. ActivityMetricsLogger
+ // will then wait for the windows to be drawn and populate WaitResult.
+ mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);
if (outResult != null) {
outResult.result = res;
@@ -1198,7 +1201,6 @@
outResult.timeout = false;
outResult.who = r.realActivity;
outResult.totalTime = 0;
- outResult.thisTime = 0;
break;
}
case START_TASK_TO_FRONT: {
@@ -1208,10 +1210,9 @@
outResult.timeout = false;
outResult.who = r.realActivity;
outResult.totalTime = 0;
- outResult.thisTime = 0;
} else {
- outResult.thisTime = SystemClock.uptimeMillis();
- mSupervisor.waitActivityVisible(r.realActivity, outResult);
+ final long startTimeMs = SystemClock.uptimeMillis();
+ mSupervisor.waitActivityVisible(r.realActivity, outResult, startTimeMs);
// Note: the timeout variable is not currently not ever set.
do {
try {
@@ -1225,7 +1226,6 @@
}
}
- mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);
return res;
}
}
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index ed891df..0ef2a0a 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -87,9 +87,6 @@
# User switched
30041 am_switch_user (id|1|5)
-# Activity fully drawn time
-30042 am_activity_fully_drawn_time (User|1|5),(Token|1|5),(Component Name|3),(time|2|3)
-
# Activity set to resumed
30043 am_set_resumed_activity (User|1|5),(Component Name|3),(Reason|3)
diff --git a/services/core/java/com/android/server/am/LaunchTimeTracker.java b/services/core/java/com/android/server/am/LaunchTimeTracker.java
deleted file mode 100644
index ee86969..0000000
--- a/services/core/java/com/android/server/am/LaunchTimeTracker.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.am;
-
-import android.app.WaitResult;
-import android.os.SystemClock;
-import android.os.Trace;
-import android.util.SparseArray;
-
-/**
- * Tracks launch time of apps to be reported by {@link WaitResult}. Note that this is slightly
- * different from {@link ActivityMetricsLogger}, but should eventually merged with it.
- */
-class LaunchTimeTracker {
-
- private final SparseArray<Entry> mWindowingModeLaunchTime = new SparseArray<>();
-
- void setLaunchTime(ActivityRecord r) {
- Entry entry = mWindowingModeLaunchTime.get(r.getWindowingMode());
- if (entry == null){
- entry = new Entry();
- mWindowingModeLaunchTime.append(r.getWindowingMode(), entry);
- }
- entry.setLaunchTime(r);
- }
-
- void stopFullyDrawnTraceIfNeeded(int windowingMode) {
- final Entry entry = mWindowingModeLaunchTime.get(windowingMode);
- if (entry == null) {
- return;
- }
- entry.stopFullyDrawnTraceIfNeeded();
- }
-
- Entry getEntry(int windowingMode) {
- return mWindowingModeLaunchTime.get(windowingMode);
- }
-
- static class Entry {
-
- long mLaunchStartTime;
- long mFullyDrawnStartTime;
-
- void setLaunchTime(ActivityRecord r) {
- if (r.displayStartTime == 0) {
- r.fullyDrawnStartTime = r.displayStartTime = SystemClock.uptimeMillis();
- if (mLaunchStartTime == 0) {
- startLaunchTraces(r.packageName);
- mLaunchStartTime = mFullyDrawnStartTime = r.displayStartTime;
- }
- } else if (mLaunchStartTime == 0) {
- startLaunchTraces(r.packageName);
- mLaunchStartTime = mFullyDrawnStartTime = SystemClock.uptimeMillis();
- }
- }
-
- private void startLaunchTraces(String packageName) {
- if (mFullyDrawnStartTime != 0) {
- Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
- }
- Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
- Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
- }
-
- private void stopFullyDrawnTraceIfNeeded() {
- if (mFullyDrawnStartTime != 0 && mLaunchStartTime == 0) {
- Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
- mFullyDrawnStartTime = 0;
- }
- }
- }
-}
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index bd8c7dd..26de0b3 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -108,9 +108,8 @@
private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh";
private static final String APP_LAUNCH_CMD = "am start -W -n";
private static final String SUCCESS_MESSAGE = "Status: ok";
- private static final String WARNING_MESSAGE = "Warning:";
+ private static final String TOTAL_TIME_MESSAGE = "TotalTime:";
private static final String COMPILE_SUCCESS = "Success";
- private static final String THIS_TIME = "ThisTime:";
private static final String LAUNCH_ITERATION = "LAUNCH_ITERATION - %d";
private static final String TRACE_ITERATION = "TRACE_ITERATION-%d";
private static final String LAUNCH_ITERATION_PREFIX = "LAUNCH_ITERATION";
@@ -831,15 +830,13 @@
String launchTime = "-1";
String cpuCycles = "-1";
String majorFaults = "-1";
- boolean coldLaunchSuccess = false;
- boolean hotLaunchSuccess = false;
+ boolean launchSuccess = false;
try {
InputStream inputStream = new FileInputStream(parcelDesc.getFileDescriptor());
/* SAMPLE OUTPUT : Cold launch
Starting: Intent { cmp=com.google.android.calculator/com.android.calculator2.Calculator }
Status: ok
Activity: com.google.android.calculator/com.android.calculator2.Calculator
- ThisTime: 357
TotalTime: 357
WaitTime: 377
Complete*/
@@ -848,7 +845,6 @@
Warning: Activity not started, its current task has been brought to the front
Status: ok
Activity: com.google.android.calculator/com.android.calculator2.CalculatorGoogle
- ThisTime: 60
TotalTime: 60
WaitTime: 67
Complete*/
@@ -859,54 +855,37 @@
Total test time,1.462129,seconds,*/
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
inputStream));
- String line = null;
- int lineCount = 1;
+ String line;
mBufferedWriter.newLine();
mBufferedWriter.write(headerInfo);
mBufferedWriter.newLine();
while ((line = bufferedReader.readLine()) != null) {
- if (lineCount == 2 && line.startsWith(SUCCESS_MESSAGE)) {
- coldLaunchSuccess = true;
+ mBufferedWriter.write(line);
+ mBufferedWriter.newLine();
+ if (line.startsWith(SUCCESS_MESSAGE)) {
+ launchSuccess = true;
}
- if (lineCount == 2 && line.startsWith(WARNING_MESSAGE)) {
- hotLaunchSuccess = true;
+ if (!launchSuccess) {
+ continue;
}
// Parse TotalTime which is the launch time
- if (coldLaunchSuccess && lineCount == 5) {
- String launchSplit[] = line.split(":");
- launchTime = launchSplit[1].trim();
- }
- if (hotLaunchSuccess && lineCount == 6) {
+ if (line.startsWith(TOTAL_TIME_MESSAGE)) {
String launchSplit[] = line.split(":");
launchTime = launchSplit[1].trim();
}
if (mSimplePerfAppOnly) {
- // Parse simpleperf output.
- if ((lineCount == 9 && coldLaunchSuccess)
- || (lineCount == 10 && hotLaunchSuccess)) {
- if (!line.contains("cpu-cycles")) {
- Log.e(TAG, "Error in simpleperf output");
- } else {
- cpuCycles = line.split(",")[0].trim();
- }
- } else if ((lineCount == 10 && coldLaunchSuccess)
- || (lineCount == 11 && hotLaunchSuccess)) {
- if (!line.contains("major-faults")) {
- Log.e(TAG, "Error in simpleperf output");
- } else {
- majorFaults = line.split(",")[0].trim();
- }
+ if (line.contains(",cpu-cycles,")) {
+ cpuCycles = line.split(",")[0].trim();
+ } else if (line.contains(",major-faults,")) {
+ majorFaults = line.split(",")[0].trim();
}
}
- mBufferedWriter.write(line);
- mBufferedWriter.newLine();
- lineCount++;
}
mBufferedWriter.flush();
inputStream.close();
} catch (IOException e) {
- Log.w(TAG, "Error writing the launch file", e);
+ Log.w(TAG, "Error parsing launch time and writing to file", e);
}
return new AppLaunchResult(launchTime, cpuCycles, majorFaults);
}