Loading services/core/java/com/android/server/am/ActivityManagerService.java +1 −22 Original line number Diff line number Diff line Loading @@ -1024,30 +1024,9 @@ public class ActivityManagerService extends IActivityManager.Stub private final ActivityMetricsLaunchObserver mActivityLaunchObserver = new ActivityMetricsLaunchObserver() { @Override public void onActivityLaunched(byte[] activity, int temperature) { public void onActivityLaunched(long id, ComponentName name, int temperature) { mAppProfiler.onActivityLaunched(); } // The other observer methods are unused @Override public void onIntentStarted(Intent intent, long timestampNs) { } @Override public void onIntentFailed() { } @Override public void onActivityLaunchCancelled(byte[] abortingActivity) { } @Override public void onActivityLaunchFinished(byte[] finalActivity, long timestampNs) { } @Override public void onReportFullyDrawn(byte[] finalActivity, long timestampNs) { } }; private volatile boolean mBinderTransactionTrackingEnabled = false; Loading services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java +35 −46 Original line number Diff line number Diff line Loading @@ -18,17 +18,19 @@ package com.android.server.wm; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Intent; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Observe activity manager launch sequences. * Observe activity launch sequences. * * The activity manager can have at most 1 concurrent launch sequences. Calls to this interface * are ordered by a happens-before relation for each defined state transition (see below). * Multiple calls to the callback methods can occur without first terminating the current launch * sequence because activity can be launched concurrently. So the implementation should associate * the corresponding event according to the timestamp from {@link #onIntentStarted} which is also * used as the identifier to indicate which launch sequence it belongs to. * * When a new launch sequence is made, that sequence is in the {@code INTENT_STARTED} state which * is communicated by the {@link #onIntentStarted} callback. This is a transient state. Loading @@ -47,7 +49,7 @@ import java.lang.annotation.RetentionPolicy; * Note this transition may not happen if the reportFullyDrawn event is not receivied, * in which case {@code FINISHED} is terminal. * * Note that the {@code ActivityRecordProto} provided as a parameter to some state transitions isn't * Note that the {@code ComponentName} provided as a parameter to some state transitions isn't * necessarily the same within a single launch sequence: it is only the top-most activity at the * time (if any). Trampoline activities coalesce several activity starts into a single launch * sequence. Loading @@ -67,7 +69,7 @@ import java.lang.annotation.RetentionPolicy; * ╚════════════════╝ ╚═══════════════════════════╝ ╚═══════════════════════════╝ * </pre> */ public interface ActivityMetricsLaunchObserver { public class ActivityMetricsLaunchObserver { /** * The 'temperature' at which a launch sequence had started. * Loading Loading @@ -98,14 +100,6 @@ public interface ActivityMetricsLaunchObserver { /** Hot launch sequence: process reused, activity brought-to-top. */ public static final int TEMPERATURE_HOT = 3; /** * Typedef marker that a {@code byte[]} actually contains an * <a href="proto/android/server/activitymanagerservice.proto">ActivityRecordProto</a> * in the protobuf format. */ @Retention(RetentionPolicy.SOURCE) @interface ActivityRecordProto {} /** * Notifies the observer that a new launch sequence has begun as a result of a new intent. * Loading @@ -113,26 +107,25 @@ public interface ActivityMetricsLaunchObserver { * {@link #onActivityLaunched} or abort early (for example due to a resolution error or due to * a security error) with {@link #onIntentFailed}. * * Multiple calls to this method cannot occur without first terminating the current * launch sequence. * @param timestampNanos The timestamp when receiving the intent. It is also use as an * identifier for other callback methods to known which launch sequence * it is associated with. */ public void onIntentStarted(@NonNull Intent intent, long timestampNanos); public void onIntentStarted(@NonNull Intent intent, long timestampNanos) { } /** * Notifies the observer that the current launch sequence has failed to launch an activity. * * This function call terminates the current launch sequence. The next method call, if any, * must be {@link #onIntentStarted}. * This function call terminates the current launch sequence. * * Examples of this happening: * - Failure to resolve to an activity * - Calling package did not have the security permissions to call the requested activity * - Resolved activity was already running and only needed to be brought to the top * * Multiple calls to this method cannot occur without first terminating the current * launch sequence. */ public void onIntentFailed(); public void onIntentFailed(long id) { } /** * Notifies the observer that the current launch sequence had begun starting an activity. Loading @@ -145,62 +138,58 @@ public interface ActivityMetricsLaunchObserver { * necessarily the activity which will be considered as displayed when the activity * finishes launching (e.g. {@code activity} in {@link #onActivityLaunchFinished}). * * Multiple calls to this method cannot occur without first terminating the current * launch sequence. * @param id The timestamp as an identifier from {@link #onIntentStarted}. It may be a new id * 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. */ public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity, @Temperature int temperature); public void onActivityLaunched(long id, ComponentName name, @Temperature int temperature) { } /** * Notifies the observer that the current launch sequence has been aborted. * * This function call terminates the current launch sequence. The next method call, if any, * must be {@link #onIntentStarted}. * This function call terminates the current launch sequence. * * This can happen for many reasons, for example the user switches away to another app * prior to the launch sequence completing, or the application being killed. * * Multiple calls to this method cannot occur without first terminating the current * launch sequence. * * @param abortingActivity the last activity that had the top-most window during abort * (this can be {@code null} in rare situations its unknown). * @param id The timestamp as an identifier from {@link #onIntentStarted}. * * @apiNote The aborting 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 is reported here. */ public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] abortingActivity); public void onActivityLaunchCancelled(long id) { } /** * Notifies the observer that the current launch sequence has been successfully finished. * * This function call terminates the current launch sequence. The next method call, if any, * must be {@link #onIntentStarted}. * This function call terminates the current launch sequence. * * A launch sequence is considered to be successfully finished when a frame is fully * drawn for the first time: the top-most activity at the time is what's reported here. * * @param finalActivity the top-most activity whose windows were first to fully draw * @param id The timestamp as an identifier from {@link #onIntentStarted}. * @param name The name of drawn activity. It can be different from {@link #onActivityLaunched} * if the transition contains multiple launching activities (e.g. trampoline). * @param timestampNanos the timestamp of ActivityLaunchFinished event in nanoseconds. * To compute the TotalTime duration, deduct the timestamp {@link #onIntentStarted} * from {@code timestampNanos}. * * Multiple calls to this method cannot occur without first terminating the current * launch sequence. * * @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(@NonNull @ActivityRecordProto byte[] finalActivity, long timestampNanos); public void onActivityLaunchFinished(long id, ComponentName name, long timestampNanos) { } /** * Notifies the observer that the application self-reported itself as being fully drawn. * * @param activity the activity that triggers the ReportFullyDrawn event. * @param id The timestamp as an identifier from {@link #onIntentStarted}. * @param timestampNanos the timestamp of ReportFullyDrawn event in nanoseconds. * To compute the duration, deduct the deduct the timestamp {@link #onIntentStarted} * from {@code timestampNanos}. Loading @@ -209,7 +198,7 @@ public interface ActivityMetricsLaunchObserver { * It is used as an accurate estimate of meanfully app startup time. * This event may be missing for many apps. */ public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity, long timestampNanos); public void onReportFullyDrawn(long id, long timestampNanos) { } } services/core/java/com/android/server/wm/ActivityMetricsLogger.java +12 −38 Original line number Diff line number Diff line Loading @@ -97,7 +97,6 @@ import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; Loading Loading @@ -176,7 +175,6 @@ class ActivityMetricsLogger { * in-order on the same thread to fulfill the "happens-before" guarantee in LaunchObserver. */ private final LaunchObserverRegistryImpl mLaunchObserver; @VisibleForTesting static final int LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE = 512; private final ArrayMap<String, Boolean> mLastHibernationStates = new ArrayMap<>(); private AppHibernationManagerInternal mAppHibernationManagerInternal; Loading Loading @@ -675,7 +673,7 @@ class ActivityMetricsLogger { launchObserverNotifyActivityLaunched(newInfo); } else { // As abort for no process switch. launchObserverNotifyIntentFailed(); launchObserverNotifyIntentFailed(newInfo.mTransitionStartTimeNs); } scheduleCheckActivityToBeDrawnIfSleeping(launchedActivity); Loading Loading @@ -910,7 +908,7 @@ class ActivityMetricsLogger { } if (DEBUG_METRICS) Slog.i(TAG, "abort launch cause=" + cause); state.stopTrace(true /* abort */); launchObserverNotifyIntentFailed(); launchObserverNotifyIntentFailed(state.mCurrentTransitionStartTimeNs); } /** Aborts tracking of current launch metrics. */ Loading Loading @@ -1187,7 +1185,7 @@ class ActivityMetricsLogger { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); // Notify reportFullyDrawn event. launchObserverNotifyReportFullyDrawn(r, currentTimestampNs); launchObserverNotifyReportFullyDrawn(info, currentTimestampNs); return infoSnapshot; } Loading Loading @@ -1531,11 +1529,11 @@ class ActivityMetricsLogger { * aborted due to intent failure (e.g. intent resolve failed or security error, etc) or * intent being delivered to the top running activity. */ private void launchObserverNotifyIntentFailed() { private void launchObserverNotifyIntentFailed(long id) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyIntentFailed"); mLaunchObserver.onIntentFailed(); mLaunchObserver.onIntentFailed(id); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } Loading @@ -1552,8 +1550,8 @@ class ActivityMetricsLogger { convertTransitionTypeToLaunchObserverTemperature(info.mTransitionType); // Beginning a launch is timing sensitive and so should be observed as soon as possible. mLaunchObserver.onActivityLaunched(convertActivityRecordToProto(info.mLastLaunchedActivity), temperature); mLaunchObserver.onActivityLaunched(info.mTransitionStartTimeNs, info.mLastLaunchedActivity.mActivityComponent, temperature); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } Loading @@ -1561,10 +1559,10 @@ class ActivityMetricsLogger { /** * Notifies the {@link ActivityMetricsLaunchObserver} the reportFullDrawn event. */ private void launchObserverNotifyReportFullyDrawn(ActivityRecord r, long timestampNs) { private void launchObserverNotifyReportFullyDrawn(TransitionInfo info, long timestampNs) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyReportFullyDrawn"); mLaunchObserver.onReportFullyDrawn(convertActivityRecordToProto(r), timestampNs); mLaunchObserver.onReportFullyDrawn(info.mTransitionStartTimeNs, timestampNs); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } Loading @@ -1576,10 +1574,7 @@ class ActivityMetricsLogger { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyActivityLaunchCancelled"); final @ActivityMetricsLaunchObserver.ActivityRecordProto byte[] activityRecordProto = info != null ? convertActivityRecordToProto(info.mLastLaunchedActivity) : null; mLaunchObserver.onActivityLaunchCancelled(activityRecordProto); mLaunchObserver.onActivityLaunchCancelled(info.mTransitionStartTimeNs); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } Loading @@ -1592,33 +1587,12 @@ class ActivityMetricsLogger { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyActivityLaunchFinished"); mLaunchObserver.onActivityLaunchFinished( convertActivityRecordToProto(info.mLastLaunchedActivity), timestampNs); mLaunchObserver.onActivityLaunchFinished(info.mTransitionStartTimeNs, info.mLastLaunchedActivity.mActivityComponent, timestampNs); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } @VisibleForTesting static @ActivityMetricsLaunchObserver.ActivityRecordProto byte[] convertActivityRecordToProto(ActivityRecord record) { // May take non-negligible amount of time to convert ActivityRecord into a proto, // so track the time. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:convertActivityRecordToProto"); // There does not appear to be a way to 'reset' a ProtoOutputBuffer stream, // so create a new one every time. final ProtoOutputStream protoOutputStream = new ProtoOutputStream(LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE); // Write this data out as the top-most ActivityRecordProto (i.e. it is not a sub-object). record.dumpDebug(protoOutputStream, WindowTraceLogLevel.ALL); final byte[] bytes = protoOutputStream.getBytes(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); return bytes; } private static @ActivityMetricsLaunchObserver.Temperature int convertTransitionTypeToLaunchObserverTemperature(int transitionType) { switch (transitionType) { Loading services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java +26 −46 Original line number Diff line number Diff line Loading @@ -16,12 +16,11 @@ package com.android.server.wm; import android.content.ComponentName; import android.content.Intent; import android.os.Handler; import android.os.Looper; import android.os.Message; import com.android.internal.os.BackgroundThread; import com.android.internal.util.function.pooled.PooledLambda; import java.util.ArrayList; Loading @@ -39,8 +38,8 @@ import java.util.ArrayList; * * @see ActivityTaskManagerInternal#getLaunchObserverRegistry() */ class LaunchObserverRegistryImpl implements ActivityMetricsLaunchObserverRegistry, ActivityMetricsLaunchObserver { class LaunchObserverRegistryImpl extends ActivityMetricsLaunchObserver implements ActivityMetricsLaunchObserverRegistry { private final ArrayList<ActivityMetricsLaunchObserver> mList = new ArrayList<>(); /** Loading Loading @@ -79,45 +78,36 @@ class LaunchObserverRegistryImpl implements } @Override public void onIntentFailed() { public void onIntentFailed(long id) { mHandler.sendMessage(PooledLambda.obtainMessage( LaunchObserverRegistryImpl::handleOnIntentFailed, this)); LaunchObserverRegistryImpl::handleOnIntentFailed, this, id)); } @Override public void onActivityLaunched( @ActivityRecordProto byte[] activity, int temperature) { public void onActivityLaunched(long id, ComponentName name, int temperature) { mHandler.sendMessage(PooledLambda.obtainMessage( LaunchObserverRegistryImpl::handleOnActivityLaunched, this, activity, temperature)); this, id, name, temperature)); } @Override public void onActivityLaunchCancelled( @ActivityRecordProto byte[] activity) { public void onActivityLaunchCancelled(long id) { mHandler.sendMessage(PooledLambda.obtainMessage( LaunchObserverRegistryImpl::handleOnActivityLaunchCancelled, this, activity)); LaunchObserverRegistryImpl::handleOnActivityLaunchCancelled, this, id)); } @Override public void onActivityLaunchFinished( @ActivityRecordProto byte[] activity, long timestampNs) { public void onActivityLaunchFinished(long id, ComponentName name, long timestampNs) { mHandler.sendMessage(PooledLambda.obtainMessage( LaunchObserverRegistryImpl::handleOnActivityLaunchFinished, this, activity, timestampNs)); this, id, name, timestampNs)); } @Override public void onReportFullyDrawn(@ActivityRecordProto byte[] activity, long timestampNs) { public void onReportFullyDrawn(long id, long timestampNs) { mHandler.sendMessage(PooledLambda.obtainMessage( LaunchObserverRegistryImpl::handleOnReportFullyDrawn, this, activity, timestampNs)); this, id, timestampNs)); } // Use PooledLambda.obtainMessage to invoke below methods. Every method reference must be Loading @@ -135,53 +125,43 @@ class LaunchObserverRegistryImpl implements private void handleOnIntentStarted(Intent intent, long timestampNs) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onIntentStarted(intent, timestampNs); mList.get(i).onIntentStarted(intent, timestampNs); } } private void handleOnIntentFailed() { private void handleOnIntentFailed(long id) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onIntentFailed(); mList.get(i).onIntentFailed(id); } } private void handleOnActivityLaunched( @ActivityRecordProto byte[] activity, private void handleOnActivityLaunched(long id, ComponentName name, @Temperature int temperature) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onActivityLaunched(activity, temperature); mList.get(i).onActivityLaunched(id, name, temperature); } } private void handleOnActivityLaunchCancelled( @ActivityRecordProto byte[] activity) { private void handleOnActivityLaunchCancelled(long id) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onActivityLaunchCancelled(activity); mList.get(i).onActivityLaunchCancelled(id); } } private void handleOnActivityLaunchFinished( @ActivityRecordProto byte[] activity, long timestampNs) { private void handleOnActivityLaunchFinished(long id, ComponentName name, long timestampNs) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onActivityLaunchFinished(activity, timestampNs); mList.get(i).onActivityLaunchFinished(id, name, timestampNs); } } private void handleOnReportFullyDrawn( @ActivityRecordProto byte[] activity, long timestampNs) { private void handleOnReportFullyDrawn(long id, long timestampNs) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onReportFullyDrawn(activity, timestampNs); mList.get(i).onReportFullyDrawn(id, timestampNs); } } } services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +1 −26 Original line number Diff line number Diff line Loading @@ -274,36 +274,11 @@ public final class ProfcollectForwardingService extends SystemService { } } private class AppLaunchObserver implements ActivityMetricsLaunchObserver { private class AppLaunchObserver extends ActivityMetricsLaunchObserver { @Override public void onIntentStarted(Intent intent, long timestampNanos) { traceOnAppStart(intent.getPackage()); } @Override public void onIntentFailed() { // Ignored } @Override public void onActivityLaunched(byte[] activity, int temperature) { // Ignored } @Override public void onActivityLaunchCancelled(byte[] abortingActivity) { // Ignored } @Override public void onActivityLaunchFinished(byte[] finalActivity, long timestampNanos) { // Ignored } @Override public void onReportFullyDrawn(byte[] activity, long timestampNanos) { // Ignored } } private void registerOTAObserver() { Loading Loading
services/core/java/com/android/server/am/ActivityManagerService.java +1 −22 Original line number Diff line number Diff line Loading @@ -1024,30 +1024,9 @@ public class ActivityManagerService extends IActivityManager.Stub private final ActivityMetricsLaunchObserver mActivityLaunchObserver = new ActivityMetricsLaunchObserver() { @Override public void onActivityLaunched(byte[] activity, int temperature) { public void onActivityLaunched(long id, ComponentName name, int temperature) { mAppProfiler.onActivityLaunched(); } // The other observer methods are unused @Override public void onIntentStarted(Intent intent, long timestampNs) { } @Override public void onIntentFailed() { } @Override public void onActivityLaunchCancelled(byte[] abortingActivity) { } @Override public void onActivityLaunchFinished(byte[] finalActivity, long timestampNs) { } @Override public void onReportFullyDrawn(byte[] finalActivity, long timestampNs) { } }; private volatile boolean mBinderTransactionTrackingEnabled = false; Loading
services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java +35 −46 Original line number Diff line number Diff line Loading @@ -18,17 +18,19 @@ package com.android.server.wm; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Intent; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Observe activity manager launch sequences. * Observe activity launch sequences. * * The activity manager can have at most 1 concurrent launch sequences. Calls to this interface * are ordered by a happens-before relation for each defined state transition (see below). * Multiple calls to the callback methods can occur without first terminating the current launch * sequence because activity can be launched concurrently. So the implementation should associate * the corresponding event according to the timestamp from {@link #onIntentStarted} which is also * used as the identifier to indicate which launch sequence it belongs to. * * When a new launch sequence is made, that sequence is in the {@code INTENT_STARTED} state which * is communicated by the {@link #onIntentStarted} callback. This is a transient state. Loading @@ -47,7 +49,7 @@ import java.lang.annotation.RetentionPolicy; * Note this transition may not happen if the reportFullyDrawn event is not receivied, * in which case {@code FINISHED} is terminal. * * Note that the {@code ActivityRecordProto} provided as a parameter to some state transitions isn't * Note that the {@code ComponentName} provided as a parameter to some state transitions isn't * necessarily the same within a single launch sequence: it is only the top-most activity at the * time (if any). Trampoline activities coalesce several activity starts into a single launch * sequence. Loading @@ -67,7 +69,7 @@ import java.lang.annotation.RetentionPolicy; * ╚════════════════╝ ╚═══════════════════════════╝ ╚═══════════════════════════╝ * </pre> */ public interface ActivityMetricsLaunchObserver { public class ActivityMetricsLaunchObserver { /** * The 'temperature' at which a launch sequence had started. * Loading Loading @@ -98,14 +100,6 @@ public interface ActivityMetricsLaunchObserver { /** Hot launch sequence: process reused, activity brought-to-top. */ public static final int TEMPERATURE_HOT = 3; /** * Typedef marker that a {@code byte[]} actually contains an * <a href="proto/android/server/activitymanagerservice.proto">ActivityRecordProto</a> * in the protobuf format. */ @Retention(RetentionPolicy.SOURCE) @interface ActivityRecordProto {} /** * Notifies the observer that a new launch sequence has begun as a result of a new intent. * Loading @@ -113,26 +107,25 @@ public interface ActivityMetricsLaunchObserver { * {@link #onActivityLaunched} or abort early (for example due to a resolution error or due to * a security error) with {@link #onIntentFailed}. * * Multiple calls to this method cannot occur without first terminating the current * launch sequence. * @param timestampNanos The timestamp when receiving the intent. It is also use as an * identifier for other callback methods to known which launch sequence * it is associated with. */ public void onIntentStarted(@NonNull Intent intent, long timestampNanos); public void onIntentStarted(@NonNull Intent intent, long timestampNanos) { } /** * Notifies the observer that the current launch sequence has failed to launch an activity. * * This function call terminates the current launch sequence. The next method call, if any, * must be {@link #onIntentStarted}. * This function call terminates the current launch sequence. * * Examples of this happening: * - Failure to resolve to an activity * - Calling package did not have the security permissions to call the requested activity * - Resolved activity was already running and only needed to be brought to the top * * Multiple calls to this method cannot occur without first terminating the current * launch sequence. */ public void onIntentFailed(); public void onIntentFailed(long id) { } /** * Notifies the observer that the current launch sequence had begun starting an activity. Loading @@ -145,62 +138,58 @@ public interface ActivityMetricsLaunchObserver { * necessarily the activity which will be considered as displayed when the activity * finishes launching (e.g. {@code activity} in {@link #onActivityLaunchFinished}). * * Multiple calls to this method cannot occur without first terminating the current * launch sequence. * @param id The timestamp as an identifier from {@link #onIntentStarted}. It may be a new id * 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. */ public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity, @Temperature int temperature); public void onActivityLaunched(long id, ComponentName name, @Temperature int temperature) { } /** * Notifies the observer that the current launch sequence has been aborted. * * This function call terminates the current launch sequence. The next method call, if any, * must be {@link #onIntentStarted}. * This function call terminates the current launch sequence. * * This can happen for many reasons, for example the user switches away to another app * prior to the launch sequence completing, or the application being killed. * * Multiple calls to this method cannot occur without first terminating the current * launch sequence. * * @param abortingActivity the last activity that had the top-most window during abort * (this can be {@code null} in rare situations its unknown). * @param id The timestamp as an identifier from {@link #onIntentStarted}. * * @apiNote The aborting 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 is reported here. */ public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] abortingActivity); public void onActivityLaunchCancelled(long id) { } /** * Notifies the observer that the current launch sequence has been successfully finished. * * This function call terminates the current launch sequence. The next method call, if any, * must be {@link #onIntentStarted}. * This function call terminates the current launch sequence. * * A launch sequence is considered to be successfully finished when a frame is fully * drawn for the first time: the top-most activity at the time is what's reported here. * * @param finalActivity the top-most activity whose windows were first to fully draw * @param id The timestamp as an identifier from {@link #onIntentStarted}. * @param name The name of drawn activity. It can be different from {@link #onActivityLaunched} * if the transition contains multiple launching activities (e.g. trampoline). * @param timestampNanos the timestamp of ActivityLaunchFinished event in nanoseconds. * To compute the TotalTime duration, deduct the timestamp {@link #onIntentStarted} * from {@code timestampNanos}. * * Multiple calls to this method cannot occur without first terminating the current * launch sequence. * * @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(@NonNull @ActivityRecordProto byte[] finalActivity, long timestampNanos); public void onActivityLaunchFinished(long id, ComponentName name, long timestampNanos) { } /** * Notifies the observer that the application self-reported itself as being fully drawn. * * @param activity the activity that triggers the ReportFullyDrawn event. * @param id The timestamp as an identifier from {@link #onIntentStarted}. * @param timestampNanos the timestamp of ReportFullyDrawn event in nanoseconds. * To compute the duration, deduct the deduct the timestamp {@link #onIntentStarted} * from {@code timestampNanos}. Loading @@ -209,7 +198,7 @@ public interface ActivityMetricsLaunchObserver { * It is used as an accurate estimate of meanfully app startup time. * This event may be missing for many apps. */ public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity, long timestampNanos); public void onReportFullyDrawn(long id, long timestampNanos) { } }
services/core/java/com/android/server/wm/ActivityMetricsLogger.java +12 −38 Original line number Diff line number Diff line Loading @@ -97,7 +97,6 @@ import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; Loading Loading @@ -176,7 +175,6 @@ class ActivityMetricsLogger { * in-order on the same thread to fulfill the "happens-before" guarantee in LaunchObserver. */ private final LaunchObserverRegistryImpl mLaunchObserver; @VisibleForTesting static final int LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE = 512; private final ArrayMap<String, Boolean> mLastHibernationStates = new ArrayMap<>(); private AppHibernationManagerInternal mAppHibernationManagerInternal; Loading Loading @@ -675,7 +673,7 @@ class ActivityMetricsLogger { launchObserverNotifyActivityLaunched(newInfo); } else { // As abort for no process switch. launchObserverNotifyIntentFailed(); launchObserverNotifyIntentFailed(newInfo.mTransitionStartTimeNs); } scheduleCheckActivityToBeDrawnIfSleeping(launchedActivity); Loading Loading @@ -910,7 +908,7 @@ class ActivityMetricsLogger { } if (DEBUG_METRICS) Slog.i(TAG, "abort launch cause=" + cause); state.stopTrace(true /* abort */); launchObserverNotifyIntentFailed(); launchObserverNotifyIntentFailed(state.mCurrentTransitionStartTimeNs); } /** Aborts tracking of current launch metrics. */ Loading Loading @@ -1187,7 +1185,7 @@ class ActivityMetricsLogger { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); // Notify reportFullyDrawn event. launchObserverNotifyReportFullyDrawn(r, currentTimestampNs); launchObserverNotifyReportFullyDrawn(info, currentTimestampNs); return infoSnapshot; } Loading Loading @@ -1531,11 +1529,11 @@ class ActivityMetricsLogger { * aborted due to intent failure (e.g. intent resolve failed or security error, etc) or * intent being delivered to the top running activity. */ private void launchObserverNotifyIntentFailed() { private void launchObserverNotifyIntentFailed(long id) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyIntentFailed"); mLaunchObserver.onIntentFailed(); mLaunchObserver.onIntentFailed(id); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } Loading @@ -1552,8 +1550,8 @@ class ActivityMetricsLogger { convertTransitionTypeToLaunchObserverTemperature(info.mTransitionType); // Beginning a launch is timing sensitive and so should be observed as soon as possible. mLaunchObserver.onActivityLaunched(convertActivityRecordToProto(info.mLastLaunchedActivity), temperature); mLaunchObserver.onActivityLaunched(info.mTransitionStartTimeNs, info.mLastLaunchedActivity.mActivityComponent, temperature); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } Loading @@ -1561,10 +1559,10 @@ class ActivityMetricsLogger { /** * Notifies the {@link ActivityMetricsLaunchObserver} the reportFullDrawn event. */ private void launchObserverNotifyReportFullyDrawn(ActivityRecord r, long timestampNs) { private void launchObserverNotifyReportFullyDrawn(TransitionInfo info, long timestampNs) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyReportFullyDrawn"); mLaunchObserver.onReportFullyDrawn(convertActivityRecordToProto(r), timestampNs); mLaunchObserver.onReportFullyDrawn(info.mTransitionStartTimeNs, timestampNs); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } Loading @@ -1576,10 +1574,7 @@ class ActivityMetricsLogger { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyActivityLaunchCancelled"); final @ActivityMetricsLaunchObserver.ActivityRecordProto byte[] activityRecordProto = info != null ? convertActivityRecordToProto(info.mLastLaunchedActivity) : null; mLaunchObserver.onActivityLaunchCancelled(activityRecordProto); mLaunchObserver.onActivityLaunchCancelled(info.mTransitionStartTimeNs); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } Loading @@ -1592,33 +1587,12 @@ class ActivityMetricsLogger { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyActivityLaunchFinished"); mLaunchObserver.onActivityLaunchFinished( convertActivityRecordToProto(info.mLastLaunchedActivity), timestampNs); mLaunchObserver.onActivityLaunchFinished(info.mTransitionStartTimeNs, info.mLastLaunchedActivity.mActivityComponent, timestampNs); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } @VisibleForTesting static @ActivityMetricsLaunchObserver.ActivityRecordProto byte[] convertActivityRecordToProto(ActivityRecord record) { // May take non-negligible amount of time to convert ActivityRecord into a proto, // so track the time. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:convertActivityRecordToProto"); // There does not appear to be a way to 'reset' a ProtoOutputBuffer stream, // so create a new one every time. final ProtoOutputStream protoOutputStream = new ProtoOutputStream(LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE); // Write this data out as the top-most ActivityRecordProto (i.e. it is not a sub-object). record.dumpDebug(protoOutputStream, WindowTraceLogLevel.ALL); final byte[] bytes = protoOutputStream.getBytes(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); return bytes; } private static @ActivityMetricsLaunchObserver.Temperature int convertTransitionTypeToLaunchObserverTemperature(int transitionType) { switch (transitionType) { Loading
services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java +26 −46 Original line number Diff line number Diff line Loading @@ -16,12 +16,11 @@ package com.android.server.wm; import android.content.ComponentName; import android.content.Intent; import android.os.Handler; import android.os.Looper; import android.os.Message; import com.android.internal.os.BackgroundThread; import com.android.internal.util.function.pooled.PooledLambda; import java.util.ArrayList; Loading @@ -39,8 +38,8 @@ import java.util.ArrayList; * * @see ActivityTaskManagerInternal#getLaunchObserverRegistry() */ class LaunchObserverRegistryImpl implements ActivityMetricsLaunchObserverRegistry, ActivityMetricsLaunchObserver { class LaunchObserverRegistryImpl extends ActivityMetricsLaunchObserver implements ActivityMetricsLaunchObserverRegistry { private final ArrayList<ActivityMetricsLaunchObserver> mList = new ArrayList<>(); /** Loading Loading @@ -79,45 +78,36 @@ class LaunchObserverRegistryImpl implements } @Override public void onIntentFailed() { public void onIntentFailed(long id) { mHandler.sendMessage(PooledLambda.obtainMessage( LaunchObserverRegistryImpl::handleOnIntentFailed, this)); LaunchObserverRegistryImpl::handleOnIntentFailed, this, id)); } @Override public void onActivityLaunched( @ActivityRecordProto byte[] activity, int temperature) { public void onActivityLaunched(long id, ComponentName name, int temperature) { mHandler.sendMessage(PooledLambda.obtainMessage( LaunchObserverRegistryImpl::handleOnActivityLaunched, this, activity, temperature)); this, id, name, temperature)); } @Override public void onActivityLaunchCancelled( @ActivityRecordProto byte[] activity) { public void onActivityLaunchCancelled(long id) { mHandler.sendMessage(PooledLambda.obtainMessage( LaunchObserverRegistryImpl::handleOnActivityLaunchCancelled, this, activity)); LaunchObserverRegistryImpl::handleOnActivityLaunchCancelled, this, id)); } @Override public void onActivityLaunchFinished( @ActivityRecordProto byte[] activity, long timestampNs) { public void onActivityLaunchFinished(long id, ComponentName name, long timestampNs) { mHandler.sendMessage(PooledLambda.obtainMessage( LaunchObserverRegistryImpl::handleOnActivityLaunchFinished, this, activity, timestampNs)); this, id, name, timestampNs)); } @Override public void onReportFullyDrawn(@ActivityRecordProto byte[] activity, long timestampNs) { public void onReportFullyDrawn(long id, long timestampNs) { mHandler.sendMessage(PooledLambda.obtainMessage( LaunchObserverRegistryImpl::handleOnReportFullyDrawn, this, activity, timestampNs)); this, id, timestampNs)); } // Use PooledLambda.obtainMessage to invoke below methods. Every method reference must be Loading @@ -135,53 +125,43 @@ class LaunchObserverRegistryImpl implements private void handleOnIntentStarted(Intent intent, long timestampNs) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onIntentStarted(intent, timestampNs); mList.get(i).onIntentStarted(intent, timestampNs); } } private void handleOnIntentFailed() { private void handleOnIntentFailed(long id) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onIntentFailed(); mList.get(i).onIntentFailed(id); } } private void handleOnActivityLaunched( @ActivityRecordProto byte[] activity, private void handleOnActivityLaunched(long id, ComponentName name, @Temperature int temperature) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onActivityLaunched(activity, temperature); mList.get(i).onActivityLaunched(id, name, temperature); } } private void handleOnActivityLaunchCancelled( @ActivityRecordProto byte[] activity) { private void handleOnActivityLaunchCancelled(long id) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onActivityLaunchCancelled(activity); mList.get(i).onActivityLaunchCancelled(id); } } private void handleOnActivityLaunchFinished( @ActivityRecordProto byte[] activity, long timestampNs) { private void handleOnActivityLaunchFinished(long id, ComponentName name, long timestampNs) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onActivityLaunchFinished(activity, timestampNs); mList.get(i).onActivityLaunchFinished(id, name, timestampNs); } } private void handleOnReportFullyDrawn( @ActivityRecordProto byte[] activity, long timestampNs) { private void handleOnReportFullyDrawn(long id, long timestampNs) { // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee. for (int i = 0; i < mList.size(); i++) { ActivityMetricsLaunchObserver o = mList.get(i); o.onReportFullyDrawn(activity, timestampNs); mList.get(i).onReportFullyDrawn(id, timestampNs); } } }
services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +1 −26 Original line number Diff line number Diff line Loading @@ -274,36 +274,11 @@ public final class ProfcollectForwardingService extends SystemService { } } private class AppLaunchObserver implements ActivityMetricsLaunchObserver { private class AppLaunchObserver extends ActivityMetricsLaunchObserver { @Override public void onIntentStarted(Intent intent, long timestampNanos) { traceOnAppStart(intent.getPackage()); } @Override public void onIntentFailed() { // Ignored } @Override public void onActivityLaunched(byte[] activity, int temperature) { // Ignored } @Override public void onActivityLaunchCancelled(byte[] abortingActivity) { // Ignored } @Override public void onActivityLaunchFinished(byte[] finalActivity, long timestampNanos) { // Ignored } @Override public void onReportFullyDrawn(byte[] activity, long timestampNanos) { // Ignored } } private void registerOTAObserver() { Loading