Add first frame timestamps to AppStartInfo
Logging same value used by StatsD for TTFF for consistency.
Adds a new call into AMS to allow the caller to supply a uid/pid and avoid enforcement against isolated callers.
Test: start several apps, ensure timestamp is added correctly
Bug: 287153617
Flag: android.app.activity_manager.app_start_info_timestamps
Change-Id: I4d5bd1c53462444a2cca6371361d6f1f25d33b99
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index e66f7fe..d8df447 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -1270,4 +1270,16 @@
* @hide
*/
public abstract boolean shouldDelayHomeLaunch(int userId);
+
+ /**
+ * Add a startup timestamp to the most recent start of the specified process.
+ *
+ * @param key The {@link ApplicationStartInfo} start timestamp key of the timestamp to add.
+ * @param timestampNs The clock monotonic timestamp to add in nanoseconds.
+ * @param uid The UID of the process to add this timestamp to.
+ * @param pid The process id of the process to add this timestamp to.
+ * @param userId The userId in the multi-user environment.
+ */
+ public abstract void addStartInfoTimestamp(int key, long timestampNs, int uid, int pid,
+ int userId);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bf048e6..8ec0e3d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -19953,6 +19953,20 @@
return !ActivityManagerService.this.mThemeOverlayReadyUsers.contains(userId);
}
}
+
+ @Override
+ public void addStartInfoTimestamp(int key, long timestampNs, int uid, int pid,
+ int userId) {
+ // For the simplification, we don't support USER_ALL nor USER_CURRENT here.
+ if (userId == UserHandle.USER_ALL || userId == UserHandle.USER_CURRENT) {
+ throw new IllegalArgumentException("Unsupported userId");
+ }
+
+ mUserController.handleIncomingUser(pid, uid, userId, true,
+ ALLOW_NON_FULL, "addStartInfoTimestampSystem", null);
+
+ addStartInfoTimestampInternal(key, timestampNs, userId, uid);
+ }
}
long inputDispatchingTimedOut(int pid, final boolean aboveSystem, TimeoutRecord timeoutRecord) {
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 6ec557a..b3208bf 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -88,6 +88,7 @@
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.ActivityOptions.SourceInfo;
+import android.app.ApplicationStartInfo;
import android.app.CameraCompatTaskInfo.CameraCompatControlState;
import android.app.WaitResult;
import android.app.WindowConfiguration.WindowingMode;
@@ -845,6 +846,16 @@
&& !r.mTransitionController.isCollecting(r))) {
done(false /* abort */, info, "notifyWindowsDrawn", timestampNs);
}
+
+ if (android.app.Flags.appStartInfoTimestamps()) {
+ // Log here to match StatsD for time to first frame.
+ mLoggerHandler.post(
+ () -> mSupervisor.mService.mWindowManager.mAmInternal.addStartInfoTimestamp(
+ ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME,
+ timestampNs, r.getUid(), r.getPid(),
+ info.mLastLaunchedActivity.mUserId));
+ }
+
return infoSnapshot;
}