Merge "Create AppStartInfo records" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 83e3fab..7f261d4 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -5285,9 +5285,10 @@
     field public static final int START_TIMESTAMP_RESERVED_RANGE_DEVELOPER_START = 21; // 0x15
     field public static final int START_TIMESTAMP_RESERVED_RANGE_SYSTEM = 20; // 0x14
     field public static final int START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE = 7; // 0x7
-    field public static final int START_TYPE_COLD = 0; // 0x0
-    field public static final int START_TYPE_HOT = 2; // 0x2
-    field public static final int START_TYPE_WARM = 1; // 0x1
+    field public static final int START_TYPE_COLD = 1; // 0x1
+    field public static final int START_TYPE_HOT = 3; // 0x3
+    field public static final int START_TYPE_UNSET = 0; // 0x0
+    field public static final int START_TYPE_WARM = 2; // 0x2
   }
 
   public final class AsyncNotedAppOp implements android.os.Parcelable {
diff --git a/core/java/android/app/ApplicationStartInfo.java b/core/java/android/app/ApplicationStartInfo.java
index c8317c8..656feb0 100644
--- a/core/java/android/app/ApplicationStartInfo.java
+++ b/core/java/android/app/ApplicationStartInfo.java
@@ -104,14 +104,17 @@
     /** Process started due to Activity started for any reason not explicitly listed. */
     public static final int START_REASON_START_ACTIVITY = 11;
 
+    /** Start type not yet set. */
+    public static final int START_TYPE_UNSET = 0;
+
     /** Process started from scratch. */
-    public static final int START_TYPE_COLD = 0;
+    public static final int START_TYPE_COLD = 1;
 
     /** Process retained minimally SavedInstanceState. */
-    public static final int START_TYPE_WARM = 1;
+    public static final int START_TYPE_WARM = 2;
 
     /** Process brought back to foreground. */
-    public static final int START_TYPE_HOT = 2;
+    public static final int START_TYPE_HOT = 3;
 
     /**
      * Default. The system always creates a new instance of the activity in the target task and
@@ -277,6 +280,7 @@
     @IntDef(
             prefix = {"START_TYPE_"},
             value = {
+                START_TYPE_UNSET,
                 START_TYPE_COLD,
                 START_TYPE_WARM,
                 START_TYPE_HOT,
@@ -769,6 +773,7 @@
 
     private static String startTypeToString(@StartType int startType) {
         return switch (startType) {
+            case START_TYPE_UNSET -> "UNSET";
             case START_TYPE_COLD -> "COLD";
             case START_TYPE_WARM -> "WARM";
             case START_TYPE_HOT -> "HOT";
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7191684..df8f17a 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -5175,6 +5175,8 @@
             return null;
         }
 
+        final long startTimeNs = SystemClock.elapsedRealtimeNanos();
+
         if (DEBUG_SERVICE) {
             Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent + " fg=" + r.fgRequired);
         }
@@ -5333,9 +5335,14 @@
                 bringDownServiceLocked(r, enqueueOomAdj);
                 return msg;
             }
+            mAm.mProcessList.getAppStartInfoTracker().handleProcessServiceStart(startTimeNs, app, r,
+                    hostingRecord, true);
             if (isolated) {
                 r.isolationHostProc = app;
             }
+        } else {
+            mAm.mProcessList.getAppStartInfoTracker().handleProcessServiceStart(startTimeNs, app, r,
+                    hostingRecord, false);
         }
 
         if (r.fgRequired) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ac173f3..21b2d32 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1103,9 +1103,51 @@
 
     private final ActivityMetricsLaunchObserver mActivityLaunchObserver =
             new ActivityMetricsLaunchObserver() {
+
         @Override
-        public void onActivityLaunched(long id, ComponentName name, int temperature) {
+        public void onIntentStarted(@NonNull Intent intent, long timestampNanos) {
+            synchronized (this) {
+                mProcessList.getAppStartInfoTracker().onIntentStarted(intent, timestampNanos);
+            }
+        }
+
+        @Override
+        public void onIntentFailed(long id) {
+            mProcessList.getAppStartInfoTracker().onIntentFailed(id);
+        }
+
+        @Override
+        public void onActivityLaunched(long id, ComponentName name, int temperature, int userId) {
             mAppProfiler.onActivityLaunched();
+            synchronized (ActivityManagerService.this) {
+                ProcessRecord record = null;
+                try {
+                    record = getProcessRecordLocked(name.getPackageName(), mContext
+                            .getPackageManager().getPackageUidAsUser(name.getPackageName(), 0,
+                            userId));
+                } catch (NameNotFoundException nnfe) {
+                    // Ignore, record will be lost.
+                }
+                mProcessList.getAppStartInfoTracker().onActivityLaunched(id, name, temperature,
+                        record);
+            }
+        }
+
+        @Override
+        public void onActivityLaunchCancelled(long id) {
+            mProcessList.getAppStartInfoTracker().onActivityLaunchCancelled(id);
+        }
+
+        @Override
+        public void onActivityLaunchFinished(long id, ComponentName name, long timestampNanos,
+                int launchMode) {
+            mProcessList.getAppStartInfoTracker().onActivityLaunchFinished(id, name,
+                    timestampNanos, launchMode);
+        }
+
+        @Override
+        public void onReportFullyDrawn(long id, long timestampNanos) {
+            mProcessList.getAppStartInfoTracker().onReportFullyDrawn(id, timestampNanos);
         }
     };
 
@@ -4488,13 +4530,13 @@
     @GuardedBy("this")
     private void attachApplicationLocked(@NonNull IApplicationThread thread,
             int pid, int callingUid, long startSeq) {
-
         // Find the application record that is being attached...  either via
         // the pid if we are running in multiple processes, or just pull the
         // next app record if we are emulating process with anonymous threads.
         ProcessRecord app;
         long startTime = SystemClock.uptimeMillis();
         long bindApplicationTimeMillis;
+        long bindApplicationTimeNanos;
         if (pid != MY_PID && pid >= 0) {
             synchronized (mPidsSelfLocked) {
                 app = mPidsSelfLocked.get(pid);
@@ -4698,6 +4740,7 @@
 
             checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
             bindApplicationTimeMillis = SystemClock.uptimeMillis();
+            bindApplicationTimeNanos = SystemClock.elapsedRealtimeNanos();
             mAtmInternal.preBindApplication(app.getWindowProcessController());
             final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
             if (mPlatformCompat != null) {
@@ -4754,6 +4797,8 @@
             }
 
             app.setBindApplicationTime(bindApplicationTimeMillis);
+            mProcessList.getAppStartInfoTracker()
+                    .reportBindApplicationTimeNanos(app, bindApplicationTimeNanos);
 
             // Make app active after binding application or client may be running requests (e.g
             // starting activities) before it is ready.
@@ -9799,12 +9844,12 @@
             final int uid = enforceDumpPermissionForPackage(packageName, userId, callingUid,
                         "getHistoricalProcessStartReasons");
             if (uid != INVALID_UID) {
-                mProcessList.mAppStartInfoTracker.getStartInfo(
+                mProcessList.getAppStartInfoTracker().getStartInfo(
                         packageName, userId, callingPid, maxNum, results);
             }
         } else {
             // If no package name is given, use the caller's uid as the filter uid.
-            mProcessList.mAppStartInfoTracker.getStartInfo(
+            mProcessList.getAppStartInfoTracker().getStartInfo(
                     packageName, callingUid, callingPid, maxNum, results);
         }
         return new ParceledListSlice<ApplicationStartInfo>(results);
@@ -9822,7 +9867,7 @@
         }
 
         final int callingUid = Binder.getCallingUid();
-        mProcessList.mAppStartInfoTracker.addStartInfoCompleteListener(listener, callingUid);
+        mProcessList.getAppStartInfoTracker().addStartInfoCompleteListener(listener, callingUid);
     }
 
 
@@ -9836,7 +9881,7 @@
         }
 
         final int callingUid = Binder.getCallingUid();
-        mProcessList.mAppStartInfoTracker.clearStartInfoCompleteListener(callingUid, true);
+        mProcessList.getAppStartInfoTracker().clearStartInfoCompleteListener(callingUid, true);
     }
 
     @Override
@@ -10138,7 +10183,7 @@
             pw.println();
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
-                mProcessList.mAppStartInfoTracker.dumpHistoryProcessStartInfo(pw, dumpPackage);
+                mProcessList.getAppStartInfoTracker().dumpHistoryProcessStartInfo(pw, dumpPackage);
                 pw.println("-------------------------------------------------------------------------------");
                 mProcessList.mAppExitInfoTracker.dumpHistoryProcessExitInfo(pw, dumpPackage);
             }
@@ -10541,7 +10586,7 @@
                     dumpPackage = args[opti];
                     opti++;
                 }
-                mProcessList.mAppStartInfoTracker.dumpHistoryProcessStartInfo(pw, dumpPackage);
+                mProcessList.getAppStartInfoTracker().dumpHistoryProcessStartInfo(pw, dumpPackage);
             } else if ("exit-info".equals(cmd)) {
                 if (opti < args.length) {
                     dumpPackage = args[opti];
@@ -13831,6 +13876,7 @@
     // activity manager to announce its creation.
     public boolean bindBackupAgent(String packageName, int backupMode, int targetUserId,
             @BackupDestination int backupDestination) {
+        long startTimeNs = SystemClock.elapsedRealtimeNanos();
         if (DEBUG_BACKUP) {
             Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode=" + backupMode
                     + " targetUserId=" + targetUserId + " callingUid = " + Binder.getCallingUid()
@@ -13906,15 +13952,20 @@
                             ? new ComponentName(app.packageName, app.backupAgentName)
                             : new ComponentName("android", "FullBackupAgent");
 
-            // startProcessLocked() returns existing proc's record if it's already running
-            ProcessRecord proc = startProcessLocked(app.processName, app,
-                    false, 0,
-                    new HostingRecord(HostingRecord.HOSTING_TYPE_BACKUP, hostingName),
-                    ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS, false, false);
+            ProcessRecord proc = getProcessRecordLocked(app.processName, app.uid);
+            boolean isProcessStarted = proc != null;
+            if (!isProcessStarted) {
+                proc = startProcessLocked(app.processName, app,
+                  false, 0,
+                  new HostingRecord(HostingRecord.HOSTING_TYPE_BACKUP, hostingName),
+                  ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS, false, false);
+            }
             if (proc == null) {
                 Slog.e(TAG, "Unable to start backup agent process " + r);
                 return false;
             }
+            mProcessList.getAppStartInfoTracker().handleProcessBackupStart(startTimeNs, proc, r,
+                    !isProcessStarted);
 
             // If the app is a regular app (uid >= 10000) and not the system server or phone
             // process, etc, then mark it as being in full backup so that certain calls to the
@@ -18741,8 +18792,12 @@
                     // If the process is known as top app, set a hint so when the process is
                     // started, the top priority can be applied immediately to avoid cpu being
                     // preempted by other processes before attaching the process of top app.
-                    startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
-                            new HostingRecord(hostingType, hostingName, isTop),
+                    final long startTimeNs = SystemClock.elapsedRealtimeNanos();
+                    HostingRecord hostingRecord =
+                            new HostingRecord(hostingType, hostingName, isTop);
+                    ProcessRecord rec = getProcessRecordLocked(processName, info.uid);
+                    ProcessRecord app = startProcessLocked(processName, info, knownToBeDead,
+                            0 /* intentFlags */, hostingRecord,
                             ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
                             false /* isolated */);
                 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index f3b2ef3..ae0cd65 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1362,7 +1362,7 @@
             }
             userId = user.id;
         }
-        mInternal.mProcessList.mAppStartInfoTracker
+        mInternal.mProcessList.getAppStartInfoTracker()
                 .clearHistoryProcessStartInfo(packageName, userId);
         return 0;
     }
diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java
index edca74f..82e554e 100644
--- a/services/core/java/com/android/server/am/AppStartInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java
@@ -22,11 +22,12 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
-import android.app.ActivityOptions;
+import android.annotation.NonNull;
 import android.app.ApplicationStartInfo;
 import android.app.Flags;
 import android.app.IApplicationStartInfoCompleteListener;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -138,6 +139,15 @@
     /** The path to the historical proc start info file, persisted in the storage. */
     @VisibleForTesting File mProcStartInfoFile;
 
+
+    /**
+     * Temporary list of records that have not been completed.
+     *
+     * Key is timestamp of launch from {@link #ActivityMetricsLaunchObserver}.
+     */
+    @GuardedBy("mLock")
+    private ArrayMap<Long, ApplicationStartInfo> mInProgRecords = new ArrayMap<>();
+
     AppStartInfoTracker() {
         mCallbacks = new SparseArray<>();
         mData = new ProcessMap<AppStartInfoContainer>();
@@ -174,68 +184,99 @@
         });
     }
 
-    void handleProcessColdStarted(long startTimeNs, HostingRecord hostingRecord,
-            ProcessRecord app) {
-        synchronized (mLock) {
-            if (!mEnabled) {
-                return;
-            }
-            ApplicationStartInfo start = new ApplicationStartInfo();
-            addBaseFieldsFromProcessRecord(start, app);
-            start.setStartupState(ApplicationStartInfo.STARTUP_STATE_STARTED);
-            start.addStartupTimestamp(
-                    ApplicationStartInfo.START_TIMESTAMP_LAUNCH, startTimeNs);
-            start.addStartupTimestamp(
-                    ApplicationStartInfo.START_TIMESTAMP_FORK, app.getStartElapsedTime());
-            start.setStartType(ApplicationStartInfo.START_TYPE_COLD);
-            start.setReason(ApplicationStartInfo.START_REASON_OTHER);
-            addStartInfoLocked(start);
-        }
-    }
-
-    public void handleProcessActivityWarmOrHotStarted(long startTimeNs,
-            ActivityOptions activityOptions, Intent intent) {
+    void onIntentStarted(@NonNull Intent intent, long timestampNanos) {
         synchronized (mLock) {
             if (!mEnabled) {
                 return;
             }
             ApplicationStartInfo start = new ApplicationStartInfo();
             start.setStartupState(ApplicationStartInfo.STARTUP_STATE_STARTED);
-            start.addStartupTimestamp(
-                    ApplicationStartInfo.START_TIMESTAMP_LAUNCH, startTimeNs);
             start.setIntent(intent);
-            start.setReason(ApplicationStartInfo.START_REASON_LAUNCHER);
-            if (activityOptions != null) {
-                start.setProcessName(activityOptions.getPackageName());
-            }
-            start.setStartType(ApplicationStartInfo.START_TYPE_WARM);
+            start.setStartType(ApplicationStartInfo.START_TYPE_UNSET);
+            start.addStartupTimestamp(ApplicationStartInfo.START_TIMESTAMP_LAUNCH, timestampNanos);
             if (intent != null && intent.getCategories() != null
                     && intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
                 start.setReason(ApplicationStartInfo.START_REASON_LAUNCHER);
             } else {
                 start.setReason(ApplicationStartInfo.START_REASON_START_ACTIVITY);
             }
-            addStartInfoLocked(start);
+            mInProgRecords.put(timestampNanos, start);
         }
     }
 
-    public void handleProcessActivityStartedFromRecents(long startTimeNs,
-            ActivityOptions activityOptions) {
+    void onIntentFailed(long id) {
         synchronized (mLock) {
             if (!mEnabled) {
                 return;
             }
-            ApplicationStartInfo start = new ApplicationStartInfo();
-            start.setStartupState(ApplicationStartInfo.STARTUP_STATE_STARTED);
-            start.addStartupTimestamp(
-                    ApplicationStartInfo.START_TIMESTAMP_LAUNCH, startTimeNs);
-            if (activityOptions != null) {
-                start.setIntent(activityOptions.getResultData());
-                start.setProcessName(activityOptions.getPackageName());
+            if (!mInProgRecords.containsKey(id)) {
+                return;
             }
-            start.setReason(ApplicationStartInfo.START_REASON_LAUNCHER_RECENTS);
-            start.setStartType(ApplicationStartInfo.START_TYPE_WARM);
-            addStartInfoLocked(start);
+            mInProgRecords.get(id).setStartupState(ApplicationStartInfo.STARTUP_STATE_ERROR);
+            mInProgRecords.remove(id);
+        }
+    }
+
+    void onActivityLaunched(long id, ComponentName name, long temperature, ProcessRecord app) {
+        synchronized (mLock) {
+            if (!mEnabled) {
+                return;
+            }
+            if (!mInProgRecords.containsKey(id)) {
+                return;
+            }
+            if (app != null) {
+                ApplicationStartInfo info = mInProgRecords.get(id);
+                info.setStartType((int) temperature);
+                addBaseFieldsFromProcessRecord(info, app);
+                addStartInfoLocked(info);
+            } else {
+                mInProgRecords.remove(id);
+            }
+        }
+    }
+
+    void onActivityLaunchCancelled(long id) {
+        synchronized (mLock) {
+            if (!mEnabled) {
+                return;
+            }
+            if (!mInProgRecords.containsKey(id)) {
+                return;
+            }
+            ApplicationStartInfo info = mInProgRecords.get(id);
+            info.setStartupState(ApplicationStartInfo.STARTUP_STATE_ERROR);
+            mInProgRecords.remove(id);
+        }
+    }
+
+    void onActivityLaunchFinished(long id, ComponentName name, long timestampNanos,
+            int launchMode) {
+        synchronized (mLock) {
+            if (!mEnabled) {
+                return;
+            }
+            if (!mInProgRecords.containsKey(id)) {
+                return;
+            }
+            ApplicationStartInfo info = mInProgRecords.get(id);
+            info.setStartupState(ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN);
+            info.setLaunchMode(launchMode);
+        }
+    }
+
+    void onReportFullyDrawn(long id, long timestampNanos) {
+        synchronized (mLock) {
+            if (!mEnabled) {
+                return;
+            }
+            if (!mInProgRecords.containsKey(id)) {
+                return;
+            }
+            ApplicationStartInfo info = mInProgRecords.get(id);
+            info.addStartupTimestamp(ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN,
+                    timestampNanos);
+            mInProgRecords.remove(id);
         }
     }
 
@@ -347,7 +388,8 @@
                 ApplicationStartInfo.START_TIMESTAMP_APPLICATION_ONCREATE);
     }
 
-    void reportBindApplicationTimeNanos(ProcessRecord app, long timeNs) {
+    /** Report a bind application timestamp to add to {@link ApplicationStartInfo}. */
+    public void reportBindApplicationTimeNanos(ProcessRecord app, long timeNs) {
         addTimestampToStart(app, timeNs,
                 ApplicationStartInfo.START_TIMESTAMP_BIND_APPLICATION);
     }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 4ff34b1..3156e9d 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -498,7 +498,7 @@
 
     /** Manages the {@link android.app.ApplicationStartInfo} records. */
     @GuardedBy("mAppStartInfoTracker")
-    final AppStartInfoTracker mAppStartInfoTracker = new AppStartInfoTracker();
+    private final AppStartInfoTracker mAppStartInfoTracker = new AppStartInfoTracker();
 
     /**
      * The currently running SDK sandbox processes for a uid.
@@ -1523,6 +1523,10 @@
         return mCachedRestoreLevel;
     }
 
+    AppStartInfoTracker getAppStartInfoTracker() {
+        return mAppStartInfoTracker;
+    }
+
     /**
      * Set the out-of-memory badness adjustment for a process.
      * If {@code pid <= 0}, this method will be a no-op.
@@ -2572,6 +2576,7 @@
             boolean isSdkSandbox, int sdkSandboxUid, String sdkSandboxClientAppPackage,
             String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
         long startTime = SystemClock.uptimeMillis();
+        final long startTimeNs = SystemClock.elapsedRealtimeNanos();
         ProcessRecord app;
         if (!isolated) {
             app = getProcessRecordLocked(processName, info.uid);
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
index 81e5fbd..769f01c 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
@@ -142,8 +142,11 @@
      *           if the launching activity is started from an existing launch sequence (trampoline)
      *           but cannot coalesce to the existing one, e.g. to a different display.
      * @param name The launching activity name.
+     * @param temperature The temperature at which a launch sequence had started.
+     * @param userId The id of the user the activity is being launched for.
      */
-    public void onActivityLaunched(long id, ComponentName name, @Temperature int temperature) {
+    public void onActivityLaunched(long id, ComponentName name, @Temperature int temperature,
+            int userId) {
     }
 
     /**
@@ -177,13 +180,15 @@
      * @param timestampNanos the timestamp of ActivityLaunchFinished event in nanoseconds.
      *        To compute the TotalTime duration, deduct the timestamp {@link #onIntentStarted}
      *        from {@code timestampNanos}.
+     * @param launchMode The activity launch mode.
      *
      * @apiNote The finishing activity isn't necessarily the same as the starting activity;
      *          in the case of a trampoline, multiple activities could've been started
      *          and only the latest activity that was top-most during first-frame drawn
      *          is reported here.
      */
-    public void onActivityLaunchFinished(long id, ComponentName name, long timestampNanos) {
+    public void onActivityLaunchFinished(long id, ComponentName name, long timestampNanos,
+            int launchMode) {
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 7b20529..78f501a 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -1737,7 +1737,8 @@
 
         // Beginning a launch is timing sensitive and so should be observed as soon as possible.
         mLaunchObserver.onActivityLaunched(info.mLaunchingState.mStartUptimeNs,
-                info.mLastLaunchedActivity.mActivityComponent, temperature);
+                info.mLastLaunchedActivity.mActivityComponent, temperature,
+                info.mLastLaunchedActivity.mUserId);
 
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
@@ -1774,7 +1775,8 @@
                 "MetricsLogger:launchObserverNotifyActivityLaunchFinished");
 
         mLaunchObserver.onActivityLaunchFinished(info.mLaunchingState.mStartUptimeNs,
-                info.mLastLaunchedActivity.mActivityComponent, timestampNs);
+                info.mLastLaunchedActivity.mActivityComponent, timestampNs,
+                info.mLastLaunchedActivity.launchMode);
 
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index f8fda91..869bcc0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1275,7 +1275,6 @@
             @Nullable String callingFeatureId, Intent intent, String resolvedType,
             IBinder resultTo, String resultWho, int requestCode, int startFlags,
             ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
-
         final SafeActivityOptions opts = SafeActivityOptions.fromBundle(bOptions);
 
         assertPackageMatchesCallingUid(callingPackage);
@@ -1316,7 +1315,6 @@
                 .setActivityOptions(opts)
                 .setUserId(userId)
                 .execute();
-
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java b/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java
index 9cbc1bd..4c73a41 100644
--- a/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java
+++ b/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java
@@ -84,10 +84,10 @@
     }
 
     @Override
-    public void onActivityLaunched(long id, ComponentName name, int temperature) {
+    public void onActivityLaunched(long id, ComponentName name, int temperature, int userId) {
         mHandler.sendMessage(PooledLambda.obtainMessage(
                 LaunchObserverRegistryImpl::handleOnActivityLaunched,
-                this, id, name, temperature));
+                this, id, name, temperature, userId));
     }
 
     @Override
@@ -97,10 +97,11 @@
     }
 
     @Override
-    public void onActivityLaunchFinished(long id, ComponentName name, long timestampNs) {
+    public void onActivityLaunchFinished(long id, ComponentName name, long timestampNs,
+            int launchMode) {
         mHandler.sendMessage(PooledLambda.obtainMessage(
                 LaunchObserverRegistryImpl::handleOnActivityLaunchFinished,
-                this, id, name, timestampNs));
+                this, id, name, timestampNs, launchMode));
     }
 
     @Override
@@ -137,10 +138,10 @@
     }
 
     private void handleOnActivityLaunched(long id, ComponentName name,
-            @Temperature int temperature) {
+            @Temperature int temperature, int userId) {
         // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
         for (int i = 0; i < mList.size(); i++) {
-            mList.get(i).onActivityLaunched(id, name, temperature);
+            mList.get(i).onActivityLaunched(id, name, temperature, userId);
         }
     }
 
@@ -151,10 +152,11 @@
         }
     }
 
-    private void handleOnActivityLaunchFinished(long id, ComponentName name, long timestampNs) {
+    private void handleOnActivityLaunchFinished(long id, ComponentName name, long timestampNs,
+            int launchMode) {
         // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
         for (int i = 0; i < mList.size(); i++) {
-            mList.get(i).onActivityLaunchFinished(id, name, timestampNs);
+            mList.get(i).onActivityLaunchFinished(id, name, timestampNs, launchMode);
         }
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 65e77dc..d4ba3b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -124,7 +124,7 @@
     private void verifyOnActivityLaunched(ActivityRecord activity) {
         final ArgumentCaptor<Long> idCaptor = ArgumentCaptor.forClass(Long.class);
         verifyAsync(mLaunchObserver).onActivityLaunched(idCaptor.capture(),
-                eq(activity.mActivityComponent), anyInt());
+                eq(activity.mActivityComponent), anyInt(), anyInt());
         final long id = idCaptor.getValue();
         setExpectedStartedId(id, activity);
         mLastLaunchedIds.put(activity.mActivityComponent, id);
@@ -132,7 +132,7 @@
 
     private void verifyOnActivityLaunchFinished(ActivityRecord activity) {
         verifyAsync(mLaunchObserver).onActivityLaunchFinished(eq(mExpectedStartedId),
-                eq(activity.mActivityComponent), anyLong());
+                eq(activity.mActivityComponent), anyLong(), anyInt());
     }
 
     private void setExpectedStartedId(long id, Object reason) {