Loading services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java +12 −4 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ import java.lang.annotation.RetentionPolicy; * It must then transition to either {@code CANCELLED} with {@link #onActivityLaunchCancelled} * or into {@code FINISHED} with {@link #onActivityLaunchFinished}. These are terminal states. * * Note that the {@link ActivityRecord} provided as a parameter to some state transitions isn't * Note that the {@code ActivityRecordProto} 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 Loading @@ -93,6 +93,14 @@ 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 Loading @@ -135,7 +143,7 @@ public interface ActivityMetricsLaunchObserver { * Multiple calls to this method cannot occur without first terminating the current * launch sequence. */ public void onActivityLaunched(@NonNull ActivityRecord activity, public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity, @Temperature int temperature); /** Loading @@ -157,7 +165,7 @@ public interface ActivityMetricsLaunchObserver { * in the case of a trampoline, multiple activities could've been started * and only the latest activity is reported here. */ public void onActivityLaunchCancelled(@Nullable ActivityRecord abortingActivity); public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] abortingActivity); /** * Notifies the observer that the current launch sequence has been successfully finished. Loading @@ -178,5 +186,5 @@ public interface ActivityMetricsLaunchObserver { * and only the latest activity that was top-most during first-frame drawn * is reported here. */ public void onActivityLaunchFinished(@NonNull ActivityRecord finalActivity); public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] finalActivity); } services/core/java/com/android/server/wm/ActivityMetricsLaunchObserverRegistry.java 0 → 100644 +60 −0 Original line number Diff line number Diff line /* * 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.wm; import android.annotation.NonNull; /** * Multi-cast delegate implementation for {@link ActivityMetricsLaunchObserver}. * * <br/><br/> * This enables multiple launch observers to subscribe to {@link ActivityMetricsLogger} * independently of each other. * * <br/><br/> * Some callbacks in {@link ActivityMetricsLaunchObserver} have a {@code byte[]} * parameter; this array is reused by all the registered observers, so it must not be written to * (i.e. all observers must treat any array parameters as immutable). * * <br /><br /> * Multi-cast invocations occurs sequentially in-order of registered observers. */ public interface ActivityMetricsLaunchObserverRegistry { /** * Register an extra launch observer to receive the multi-cast. * * <br /><br /> * Multi-cast invocation happens in the same order the observers were registered. For example, * <pre> * registerLaunchObserver(A) * registerLaunchObserver(B) * * obs.onIntentFailed() -> * A.onIntentFailed() * B.onIntentFailed() * </pre> */ void registerLaunchObserver(@NonNull ActivityMetricsLaunchObserver launchObserver); /** * Unregister an existing launch observer. It will not receive the multi-cast in the future. * * <br /><br /> * This does nothing if this observer was not already registered. */ void unregisterLaunchObserver(@NonNull ActivityMetricsLaunchObserver launchObserver); } services/core/java/com/android/server/wm/ActivityMetricsLogger.java +65 −21 Original line number Diff line number Diff line Loading @@ -99,10 +99,12 @@ import android.util.SparseArray; import android.util.SparseIntArray; import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import com.android.internal.logging.MetricsLogger; import com.android.internal.os.BackgroundThread; import com.android.internal.os.SomeArgs; import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; /** Loading Loading @@ -168,7 +170,8 @@ class ActivityMetricsLogger { * Due to the global single concurrent launch sequence, all calls to this observer must be made * in-order on the same thread to fulfill the "happens-before" guarantee in LaunchObserver. */ private final ActivityMetricsLaunchObserver mLaunchObserver = null; private final LaunchObserverRegistryImpl mLaunchObserver; @VisibleForTesting static final int LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE = 512; private final class H extends Handler { Loading Loading @@ -263,6 +266,7 @@ class ActivityMetricsLogger { mSupervisor = supervisor; mContext = context; mHandler = new H(looper); mLaunchObserver = new LaunchObserverRegistryImpl(looper); } void logWindowState() { Loading Loading @@ -1000,12 +1004,19 @@ class ActivityMetricsLogger { } } public ActivityMetricsLaunchObserverRegistry getLaunchObserverRegistry() { return mLaunchObserver; } /** Notify the {@link ActivityMetricsLaunchObserver} that a new launch sequence has begun. */ private void launchObserverNotifyIntentStarted(Intent intent) { if (mLaunchObserver != null) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyIntentStarted"); // Beginning a launch is timing sensitive and so should be observed as soon as possible. mLaunchObserver.onIntentStarted(intent); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } /** Loading @@ -1014,9 +1025,12 @@ class ActivityMetricsLogger { * intent being delivered to the top running activity. */ private void launchObserverNotifyIntentFailed() { if (mLaunchObserver != null) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyIntentFailed"); mLaunchObserver.onIntentFailed(); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } /** Loading @@ -1024,14 +1038,17 @@ class ActivityMetricsLogger { * has started. */ private void launchObserverNotifyActivityLaunched(WindowingModeTransitionInfo info) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyActivityLaunched"); @ActivityMetricsLaunchObserver.Temperature int temperature = convertTransitionTypeToLaunchObserverTemperature(getTransitionType(info)); if (mLaunchObserver != null) { // Beginning a launch is timing sensitive and so should be observed as soon as possible. mLaunchObserver.onActivityLaunched(info.launchedActivity, mLaunchObserver.onActivityLaunched(convertActivityRecordToProto(info.launchedActivity), temperature); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } /** Loading @@ -1039,11 +1056,15 @@ class ActivityMetricsLogger { * cancelled. */ private void launchObserverNotifyActivityLaunchCancelled(WindowingModeTransitionInfo info) { final ActivityRecord launchedActivity = info != null ? info.launchedActivity : null; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyActivityLaunchCancelled"); if (mLaunchObserver != null) { mLaunchObserver.onActivityLaunchCancelled(launchedActivity); } final @ActivityMetricsLaunchObserver.ActivityRecordProto byte[] activityRecordProto = info != null ? convertActivityRecordToProto(info.launchedActivity) : null; mLaunchObserver.onActivityLaunchCancelled(activityRecordProto); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } /** Loading @@ -1051,11 +1072,34 @@ class ActivityMetricsLogger { * has fully finished (successfully). */ private void launchObserverNotifyActivityLaunchFinished(WindowingModeTransitionInfo info) { final ActivityRecord launchedActivity = info.launchedActivity; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyActivityLaunchFinished"); mLaunchObserver.onActivityLaunchFinished( convertActivityRecordToProto(info.launchedActivity)); if (mLaunchObserver != null) { mLaunchObserver.onActivityLaunchFinished(launchedActivity); 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.writeToProto(protoOutputStream); final byte[] bytes = protoOutputStream.getBytes(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); return bytes; } private static @ActivityMetricsLaunchObserver.Temperature int Loading services/core/java/com/android/server/wm/ActivityRecord.java +10 −2 Original line number Diff line number Diff line Loading @@ -3215,8 +3215,11 @@ final class ActivityRecord extends ConfigurationContainer { proto.end(token); } public void writeToProto(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); /** * Write all fields to an {@code ActivityRecordProto}. This assumes the * {@code ActivityRecordProto} is the outer-most proto data. */ void writeToProto(ProtoOutputStream proto) { super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); writeIdentifierToProto(proto, IDENTIFIER); proto.write(STATE, mState.toString()); Loading @@ -3226,6 +3229,11 @@ final class ActivityRecord extends ConfigurationContainer { proto.write(PROC_ID, app.getPid()); } proto.write(TRANSLUCENT, !fullscreen); } public void writeToProto(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); writeToProto(proto); proto.end(token); } } services/core/java/com/android/server/wm/ActivityStackSupervisor.java +3 −1 Original line number Diff line number Diff line Loading @@ -434,7 +434,9 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mInitialized = true; mRunningTasks = createRunningTasks(); mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext, mHandler.getLooper()); mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext, mHandler.getLooper()); mKeyguardController = new KeyguardController(mService, this); mPersisterQueue = new PersisterQueue(); Loading Loading
services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java +12 −4 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ import java.lang.annotation.RetentionPolicy; * It must then transition to either {@code CANCELLED} with {@link #onActivityLaunchCancelled} * or into {@code FINISHED} with {@link #onActivityLaunchFinished}. These are terminal states. * * Note that the {@link ActivityRecord} provided as a parameter to some state transitions isn't * Note that the {@code ActivityRecordProto} 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 Loading @@ -93,6 +93,14 @@ 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 Loading @@ -135,7 +143,7 @@ public interface ActivityMetricsLaunchObserver { * Multiple calls to this method cannot occur without first terminating the current * launch sequence. */ public void onActivityLaunched(@NonNull ActivityRecord activity, public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity, @Temperature int temperature); /** Loading @@ -157,7 +165,7 @@ public interface ActivityMetricsLaunchObserver { * in the case of a trampoline, multiple activities could've been started * and only the latest activity is reported here. */ public void onActivityLaunchCancelled(@Nullable ActivityRecord abortingActivity); public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] abortingActivity); /** * Notifies the observer that the current launch sequence has been successfully finished. Loading @@ -178,5 +186,5 @@ public interface ActivityMetricsLaunchObserver { * and only the latest activity that was top-most during first-frame drawn * is reported here. */ public void onActivityLaunchFinished(@NonNull ActivityRecord finalActivity); public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] finalActivity); }
services/core/java/com/android/server/wm/ActivityMetricsLaunchObserverRegistry.java 0 → 100644 +60 −0 Original line number Diff line number Diff line /* * 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.wm; import android.annotation.NonNull; /** * Multi-cast delegate implementation for {@link ActivityMetricsLaunchObserver}. * * <br/><br/> * This enables multiple launch observers to subscribe to {@link ActivityMetricsLogger} * independently of each other. * * <br/><br/> * Some callbacks in {@link ActivityMetricsLaunchObserver} have a {@code byte[]} * parameter; this array is reused by all the registered observers, so it must not be written to * (i.e. all observers must treat any array parameters as immutable). * * <br /><br /> * Multi-cast invocations occurs sequentially in-order of registered observers. */ public interface ActivityMetricsLaunchObserverRegistry { /** * Register an extra launch observer to receive the multi-cast. * * <br /><br /> * Multi-cast invocation happens in the same order the observers were registered. For example, * <pre> * registerLaunchObserver(A) * registerLaunchObserver(B) * * obs.onIntentFailed() -> * A.onIntentFailed() * B.onIntentFailed() * </pre> */ void registerLaunchObserver(@NonNull ActivityMetricsLaunchObserver launchObserver); /** * Unregister an existing launch observer. It will not receive the multi-cast in the future. * * <br /><br /> * This does nothing if this observer was not already registered. */ void unregisterLaunchObserver(@NonNull ActivityMetricsLaunchObserver launchObserver); }
services/core/java/com/android/server/wm/ActivityMetricsLogger.java +65 −21 Original line number Diff line number Diff line Loading @@ -99,10 +99,12 @@ import android.util.SparseArray; import android.util.SparseIntArray; import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import com.android.internal.logging.MetricsLogger; import com.android.internal.os.BackgroundThread; import com.android.internal.os.SomeArgs; import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; /** Loading Loading @@ -168,7 +170,8 @@ class ActivityMetricsLogger { * Due to the global single concurrent launch sequence, all calls to this observer must be made * in-order on the same thread to fulfill the "happens-before" guarantee in LaunchObserver. */ private final ActivityMetricsLaunchObserver mLaunchObserver = null; private final LaunchObserverRegistryImpl mLaunchObserver; @VisibleForTesting static final int LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE = 512; private final class H extends Handler { Loading Loading @@ -263,6 +266,7 @@ class ActivityMetricsLogger { mSupervisor = supervisor; mContext = context; mHandler = new H(looper); mLaunchObserver = new LaunchObserverRegistryImpl(looper); } void logWindowState() { Loading Loading @@ -1000,12 +1004,19 @@ class ActivityMetricsLogger { } } public ActivityMetricsLaunchObserverRegistry getLaunchObserverRegistry() { return mLaunchObserver; } /** Notify the {@link ActivityMetricsLaunchObserver} that a new launch sequence has begun. */ private void launchObserverNotifyIntentStarted(Intent intent) { if (mLaunchObserver != null) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyIntentStarted"); // Beginning a launch is timing sensitive and so should be observed as soon as possible. mLaunchObserver.onIntentStarted(intent); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } /** Loading @@ -1014,9 +1025,12 @@ class ActivityMetricsLogger { * intent being delivered to the top running activity. */ private void launchObserverNotifyIntentFailed() { if (mLaunchObserver != null) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyIntentFailed"); mLaunchObserver.onIntentFailed(); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } /** Loading @@ -1024,14 +1038,17 @@ class ActivityMetricsLogger { * has started. */ private void launchObserverNotifyActivityLaunched(WindowingModeTransitionInfo info) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyActivityLaunched"); @ActivityMetricsLaunchObserver.Temperature int temperature = convertTransitionTypeToLaunchObserverTemperature(getTransitionType(info)); if (mLaunchObserver != null) { // Beginning a launch is timing sensitive and so should be observed as soon as possible. mLaunchObserver.onActivityLaunched(info.launchedActivity, mLaunchObserver.onActivityLaunched(convertActivityRecordToProto(info.launchedActivity), temperature); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } /** Loading @@ -1039,11 +1056,15 @@ class ActivityMetricsLogger { * cancelled. */ private void launchObserverNotifyActivityLaunchCancelled(WindowingModeTransitionInfo info) { final ActivityRecord launchedActivity = info != null ? info.launchedActivity : null; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyActivityLaunchCancelled"); if (mLaunchObserver != null) { mLaunchObserver.onActivityLaunchCancelled(launchedActivity); } final @ActivityMetricsLaunchObserver.ActivityRecordProto byte[] activityRecordProto = info != null ? convertActivityRecordToProto(info.launchedActivity) : null; mLaunchObserver.onActivityLaunchCancelled(activityRecordProto); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } /** Loading @@ -1051,11 +1072,34 @@ class ActivityMetricsLogger { * has fully finished (successfully). */ private void launchObserverNotifyActivityLaunchFinished(WindowingModeTransitionInfo info) { final ActivityRecord launchedActivity = info.launchedActivity; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "MetricsLogger:launchObserverNotifyActivityLaunchFinished"); mLaunchObserver.onActivityLaunchFinished( convertActivityRecordToProto(info.launchedActivity)); if (mLaunchObserver != null) { mLaunchObserver.onActivityLaunchFinished(launchedActivity); 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.writeToProto(protoOutputStream); final byte[] bytes = protoOutputStream.getBytes(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); return bytes; } private static @ActivityMetricsLaunchObserver.Temperature int Loading
services/core/java/com/android/server/wm/ActivityRecord.java +10 −2 Original line number Diff line number Diff line Loading @@ -3215,8 +3215,11 @@ final class ActivityRecord extends ConfigurationContainer { proto.end(token); } public void writeToProto(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); /** * Write all fields to an {@code ActivityRecordProto}. This assumes the * {@code ActivityRecordProto} is the outer-most proto data. */ void writeToProto(ProtoOutputStream proto) { super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */); writeIdentifierToProto(proto, IDENTIFIER); proto.write(STATE, mState.toString()); Loading @@ -3226,6 +3229,11 @@ final class ActivityRecord extends ConfigurationContainer { proto.write(PROC_ID, app.getPid()); } proto.write(TRANSLUCENT, !fullscreen); } public void writeToProto(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); writeToProto(proto); proto.end(token); } }
services/core/java/com/android/server/wm/ActivityStackSupervisor.java +3 −1 Original line number Diff line number Diff line Loading @@ -434,7 +434,9 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mInitialized = true; mRunningTasks = createRunningTasks(); mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext, mHandler.getLooper()); mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext, mHandler.getLooper()); mKeyguardController = new KeyguardController(mService, this); mPersisterQueue = new PersisterQueue(); Loading