• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.content.Intent;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 
27 /**
28  * Observe activity manager launch sequences.
29  *
30  * The activity manager can have at most 1 concurrent launch sequences. Calls to this interface
31  * are ordered by a happens-before relation for each defined state transition (see below).
32  *
33  * When a new launch sequence is made, that sequence is in the {@code INTENT_STARTED} state which
34  * is communicated by the {@link #onIntentStarted} callback. This is a transient state.
35  *
36  * The intent can fail to launch the activity, in which case the sequence's state transitions to
37  * {@code INTENT_FAILED} via {@link #onIntentFailed}. This is a terminal state.
38  *
39  * If an activity is successfully started, the launch sequence's state will transition into
40  * {@code STARTED} via {@link #onActivityLaunched}. This is a transient state.
41  *
42  * It must then transition to either {@code CANCELLED} with {@link #onActivityLaunchCancelled},
43  * which is a terminal state or into {@code FINISHED} with {@link #onActivityLaunchFinished}.
44  *
45  * The {@code FINISHED} with {@link #onActivityLaunchFinished} then may transition to
46  * {@code FULLY_DRAWN} with {@link #onReportFullyDrawn}, which is a terminal state.
47  * Note this transition may not happen if the reportFullyDrawn event is not receivied,
48  * in which case {@code FINISHED} is terminal.
49  *
50  * Note that the {@code ActivityRecordProto} provided as a parameter to some state transitions isn't
51  * necessarily the same within a single launch sequence: it is only the top-most activity at the
52  * time (if any). Trampoline activities coalesce several activity starts into a single launch
53  * sequence.
54  *
55  * Upon reaching a terminal state, it is considered that there are no active launch sequences
56  * until a subsequent transition into {@code INTENT_STARTED} initiates a new launch sequence.
57  *
58  * <pre>
59  *        ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐     ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐     ┌--------------------------┐
60  *    ╴╴▶  INTENT_STARTED    ──▶      ACTIVITY_LAUNCHED        ──▶   ACTIVITY_LAUNCH_FINISHED
61  *        └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘     └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘     └--------------------------┘
62  *          :                      :                                 :
63  *          :                      :                                 :
64  *          ▼                      ▼                                 ▼
65  *        ╔════════════════╗     ╔═══════════════════════════╗     ╔═══════════════════════════╗
66  *        ║ INTENT_FAILED  ║     ║ ACTIVITY_LAUNCH_CANCELLED ║     ║    REPORT_FULLY_DRAWN     ║
67  *        ╚════════════════╝     ╚═══════════════════════════╝     ╚═══════════════════════════╝
68  * </pre>
69  */
70 public interface ActivityMetricsLaunchObserver {
71     /**
72      * The 'temperature' at which a launch sequence had started.
73      *
74      * The lower the temperature the more work has to be done during start-up.
75      * A 'cold' temperature means that a new process has been started and likely
76      * nothing is cached.
77      *
78      * A hot temperature means the existing activity is brought to the foreground.
79      * It may need to regenerate some objects as a result of {@code onTrimMemory}.
80      *
81      * A warm temperature is in the middle; an existing process is used, but the activity
82      * has to be created from scratch with {@code #onCreate}.
83      *
84      * @see https://developer.android.com/topic/performance/vitals/launch-time
85      */
86     @Retention(RetentionPolicy.SOURCE)
87     @IntDef({
88             TEMPERATURE_COLD,
89             TEMPERATURE_WARM,
90             TEMPERATURE_HOT
91     })
92     @interface Temperature {}
93 
94     /** Cold launch sequence: a new process has started. */
95     public static final int TEMPERATURE_COLD = 1;
96     /** Warm launch sequence: process reused, but activity has to be created. */
97     public static final int TEMPERATURE_WARM = 2;
98     /** Hot launch sequence: process reused, activity brought-to-top. */
99     public static final int TEMPERATURE_HOT = 3;
100 
101     /**
102      * Typedef marker that a {@code byte[]} actually contains an
103      * <a href="proto/android/server/activitymanagerservice.proto">ActivityRecordProto</a>
104      * in the protobuf format.
105      */
106     @Retention(RetentionPolicy.SOURCE)
107     @interface ActivityRecordProto {}
108 
109     /**
110      * Notifies the observer that a new launch sequence has begun as a result of a new intent.
111      *
112      * Once a launch sequence begins, the resolved activity will either subsequently start with
113      * {@link #onActivityLaunched} or abort early (for example due to a resolution error or due to
114      * a security error) with {@link #onIntentFailed}.
115      *
116      * Multiple calls to this method cannot occur without first terminating the current
117      * launch sequence.
118      */
onIntentStarted(@onNull Intent intent, long timestampNanos)119     public void onIntentStarted(@NonNull Intent intent, long timestampNanos);
120 
121     /**
122      * Notifies the observer that the current launch sequence has failed to launch an activity.
123      *
124      * This function call terminates the current launch sequence. The next method call, if any,
125      * must be {@link #onIntentStarted}.
126      *
127      * Examples of this happening:
128      *  - Failure to resolve to an activity
129      *  - Calling package did not have the security permissions to call the requested activity
130      *  - Resolved activity was already running and only needed to be brought to the top
131      *
132      * Multiple calls to this method cannot occur without first terminating the current
133      * launch sequence.
134      */
onIntentFailed()135     public void onIntentFailed();
136 
137     /**
138      * Notifies the observer that the current launch sequence had begun starting an activity.
139      *
140      * This is an intermediate state: once an activity begins starting, the entire launch sequence
141      * will later terminate by either finishing or cancelling.
142      *
143      * The initial activity is the first activity to be started as part of a launch sequence:
144      * it is represented by {@param activity} However, it isn't
145      * necessarily the activity which will be considered as displayed when the activity
146      * finishes launching (e.g. {@code activity} in {@link #onActivityLaunchFinished}).
147      *
148      * Multiple calls to this method cannot occur without first terminating the current
149      * launch sequence.
150      */
onActivityLaunched(@onNull @ctivityRecordProto byte[] activity, @Temperature int temperature)151     public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity,
152                                    @Temperature int temperature);
153 
154     /**
155      * Notifies the observer that the current launch sequence has been aborted.
156      *
157      * This function call terminates the current launch sequence. The next method call, if any,
158      * must be {@link #onIntentStarted}.
159      *
160      * This can happen for many reasons, for example the user switches away to another app
161      * prior to the launch sequence completing, or the application being killed.
162      *
163      * Multiple calls to this method cannot occur without first terminating the current
164      * launch sequence.
165      *
166      * @param abortingActivity the last activity that had the top-most window during abort
167      *                         (this can be {@code null} in rare situations its unknown).
168      *
169      * @apiNote The aborting activity isn't necessarily the same as the starting activity;
170      *          in the case of a trampoline, multiple activities could've been started
171      *          and only the latest activity is reported here.
172      */
onActivityLaunchCancelled(@ullable @ctivityRecordProto byte[] abortingActivity)173     public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] abortingActivity);
174 
175     /**
176      * Notifies the observer that the current launch sequence has been successfully finished.
177      *
178      * This function call terminates the current launch sequence. The next method call, if any,
179      * must be {@link #onIntentStarted}.
180      *
181      * A launch sequence is considered to be successfully finished when a frame is fully
182      * drawn for the first time: the top-most activity at the time is what's reported here.
183      *
184      * @param finalActivity the top-most activity whose windows were first to fully draw
185      * @param timestampNanos the timestamp of ActivityLaunchFinished event in nanoseconds.
186      *        To compute the TotalTime duration, deduct the timestamp {@link #onIntentStarted}
187      *        from {@code timestampNanos}.
188      *
189      * Multiple calls to this method cannot occur without first terminating the current
190      * launch sequence.
191      *
192      * @apiNote The finishing activity isn't necessarily the same as the starting activity;
193      *          in the case of a trampoline, multiple activities could've been started
194      *          and only the latest activity that was top-most during first-frame drawn
195      *          is reported here.
196      */
onActivityLaunchFinished(@onNull @ctivityRecordProto byte[] finalActivity, long timestampNanos)197     public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] finalActivity,
198                                          long timestampNanos);
199 
200     /**
201      * Notifies the observer that the application self-reported itself as being fully drawn.
202      *
203      * @param activity the activity that triggers the ReportFullyDrawn event.
204      * @param timestampNanos the timestamp of ReportFullyDrawn event in nanoseconds.
205      *        To compute the duration, deduct the deduct the timestamp {@link #onIntentStarted}
206      *        from {@code timestampNanos}.
207      *
208      * @apiNote The behavior of ReportFullyDrawn mostly depends on the app.
209      *          It is used as an accurate estimate of meanfully app startup time.
210      *          This event may be missing for many apps.
211      */
onReportFullyDrawn(@onNull @ctivityRecordProto byte[] activity, long timestampNanos)212     public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity,
213         long timestampNanos);
214 
215 }
216