diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 427662aa9eaa8..b7f819f0724c8 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -235,6 +235,7 @@ message Atom { BluetoothClassicPairingEventReported bluetooth_classic_pairing_event_reported = 166; BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported = 167; ScreenTimeoutExtensionReported screen_timeout_extension_reported = 168; + ProcessStartTime process_start_time = 169; } // Pulled events will start at field 10000. @@ -5303,3 +5304,59 @@ message ScreenTimeoutExtensionReported { // Describes how many times in a row did the power manager reset the screen off timeout. optional uint32 consecutive_timeout_extended_count = 1; } + +/* +* Logs number of milliseconds it takes to start a process. +* The definition of app process start time is from the app launch time to +* the time that Zygote finished forking the app process and loaded the +* application package's java classes. + +* This metric is different from AppStartOccurred which is for foreground +* activity only. + +* ProcessStartTime can report all processes (both foreground and background) +* start time. +* +* Logged from: +* frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java +*/ +message ProcessStartTime { + // The uid of the ProcessRecord. + optional int32 uid = 1 [(is_uid) = true]; + + // The process pid. + optional int32 pid = 2; + + // The process name. + // Usually package name, "system" for system server. + // Provided by ActivityManagerService. + optional string process_name = 3; + + enum StartType { + UNKNOWN = 0; + WARM = 1; + HOT = 2; + COLD = 3; + } + + // The start type. + optional StartType type = 4; + + // The elapsed realtime at the start of the process. + optional int64 process_start_time_millis = 5; + + // Number of milliseconds it takes to reach bind application. + optional int32 bind_application_delay_millis = 6; + + // Number of milliseconds it takes to finish start of the process. + optional int32 process_start_delay_millis = 7; + + // hostingType field in ProcessRecord, the component type such as "activity", + // "service", "content provider", "broadcast" or other strings. + optional string hosting_type = 8; + + // hostingNameStr field in ProcessRecord. The component class name that runs + // in this process. + optional string hosting_name = 9; +} + diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d94fc03751f38..7baac543b238f 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4504,6 +4504,7 @@ public class ActivityManagerService extends IActivityManager.Stub // next app record if we are emulating process with anonymous threads. ProcessRecord app; long startTime = SystemClock.uptimeMillis(); + long bindApplicationTimeMillis; if (pid != MY_PID && pid >= 0) { synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); @@ -4741,6 +4742,7 @@ public class ActivityManagerService extends IActivityManager.Stub } checkTime(startTime, "attachApplicationLocked: immediately before bindApplication"); + bindApplicationTimeMillis = SystemClock.elapsedRealtime(); mAtmInternal.preBindApplication(app.getWindowProcessController()); final ActiveInstrumentation instr2 = app.getActiveInstrumentation(); if (app.isolatedEntryPoint != null) { @@ -4862,6 +4864,17 @@ public class ActivityManagerService extends IActivityManager.Stub checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked"); } + StatsLog.write( + StatsLog.PROCESS_START_TIME, + app.info.uid, + app.pid, + app.info.packageName, + StatsLog.PROCESS_START_TIME__TYPE__COLD, + app.startTime, + (int) (bindApplicationTimeMillis - app.startTime), + (int) (SystemClock.elapsedRealtime() - app.startTime), + app.hostingType, + (app.hostingNameStr != null ? app.hostingNameStr : "")); return true; }