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 * or into {@code FINISHED} with {@link #onActivityLaunchFinished}. These are terminal states. 44 * 45 * Note that the {@code ActivityRecordProto} provided as a parameter to some state transitions isn't 46 * necessarily the same within a single launch sequence: it is only the top-most activity at the 47 * time (if any). Trampoline activities coalesce several activity starts into a single launch 48 * sequence. 49 * 50 * Upon reaching a terminal state, it is considered that there are no active launch sequences 51 * until a subsequent transition into {@code INTENT_STARTED} initiates a new launch sequence. 52 * 53 * <pre> 54 * ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐ ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐ ╔══════════════════════════╗ 55 * ╴╴▶ ⋮ INTENT_STARTED ⋮ ──▶ ⋮ ACTIVITY_LAUNCHED ⋮ ──▶ ║ ACTIVITY_LAUNCH_FINISHED ║ 56 * └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘ └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘ ╚══════════════════════════╝ 57 * : : 58 * : : 59 * ▼ ▼ 60 * ╔════════════════╗ ╔═══════════════════════════╗ 61 * ║ INTENT_FAILED ║ ║ ACTIVITY_LAUNCH_CANCELLED ║ 62 * ╚════════════════╝ ╚═══════════════════════════╝ 63 * </pre> 64 */ 65 public interface ActivityMetricsLaunchObserver { 66 /** 67 * The 'temperature' at which a launch sequence had started. 68 * 69 * The lower the temperature the more work has to be done during start-up. 70 * A 'cold' temperature means that a new process has been started and likely 71 * nothing is cached. 72 * 73 * A hot temperature means the existing activity is brought to the foreground. 74 * It may need to regenerate some objects as a result of {@code onTrimMemory}. 75 * 76 * A warm temperature is in the middle; an existing process is used, but the activity 77 * has to be created from scratch with {@code #onCreate}. 78 * 79 * @see https://developer.android.com/topic/performance/vitals/launch-time 80 */ 81 @Retention(RetentionPolicy.SOURCE) 82 @IntDef({ 83 TEMPERATURE_COLD, 84 TEMPERATURE_WARM, 85 TEMPERATURE_HOT 86 }) 87 @interface Temperature {} 88 89 /** Cold launch sequence: a new process has started. */ 90 public static final int TEMPERATURE_COLD = 1; 91 /** Warm launch sequence: process reused, but activity has to be created. */ 92 public static final int TEMPERATURE_WARM = 2; 93 /** Hot launch sequence: process reused, activity brought-to-top. */ 94 public static final int TEMPERATURE_HOT = 3; 95 96 /** 97 * Typedef marker that a {@code byte[]} actually contains an 98 * <a href="proto/android/server/activitymanagerservice.proto">ActivityRecordProto</a> 99 * in the protobuf format. 100 */ 101 @Retention(RetentionPolicy.SOURCE) 102 @interface ActivityRecordProto {} 103 104 /** 105 * Notifies the observer that a new launch sequence has begun as a result of a new intent. 106 * 107 * Once a launch sequence begins, the resolved activity will either subsequently start with 108 * {@link #onActivityLaunched} or abort early (for example due to a resolution error or due to 109 * a security error) with {@link #onIntentFailed}. 110 * 111 * Multiple calls to this method cannot occur without first terminating the current 112 * launch sequence. 113 */ onIntentStarted(@onNull Intent intent)114 public void onIntentStarted(@NonNull Intent intent); 115 116 /** 117 * Notifies the observer that the current launch sequence has failed to launch an activity. 118 * 119 * This function call terminates the current launch sequence. The next method call, if any, 120 * must be {@link #onIntentStarted}. 121 * 122 * Examples of this happening: 123 * - Failure to resolve to an activity 124 * - Calling package did not have the security permissions to call the requested activity 125 * - Resolved activity was already running and only needed to be brought to the top 126 * 127 * Multiple calls to this method cannot occur without first terminating the current 128 * launch sequence. 129 */ onIntentFailed()130 public void onIntentFailed(); 131 132 /** 133 * Notifies the observer that the current launch sequence had begun starting an activity. 134 * 135 * This is an intermediate state: once an activity begins starting, the entire launch sequence 136 * will later terminate by either finishing or cancelling. 137 * 138 * The initial activity is the first activity to be started as part of a launch sequence: 139 * it is represented by {@param activity} However, it isn't 140 * necessarily the activity which will be considered as displayed when the activity 141 * finishes launching (e.g. {@code activity} in {@link #onActivityLaunchFinished}). 142 * 143 * Multiple calls to this method cannot occur without first terminating the current 144 * launch sequence. 145 */ onActivityLaunched(@onNull @ctivityRecordProto byte[] activity, @Temperature int temperature)146 public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity, 147 @Temperature int temperature); 148 149 /** 150 * Notifies the observer that the current launch sequence has been aborted. 151 * 152 * This function call terminates the current launch sequence. The next method call, if any, 153 * must be {@link #onIntentStarted}. 154 * 155 * This can happen for many reasons, for example the user switches away to another app 156 * prior to the launch sequence completing, or the application being killed. 157 * 158 * Multiple calls to this method cannot occur without first terminating the current 159 * launch sequence. 160 * 161 * @param abortingActivity the last activity that had the top-most window during abort 162 * (this can be {@code null} in rare situations its unknown). 163 * 164 * @apiNote The aborting activity isn't necessarily the same as the starting activity; 165 * in the case of a trampoline, multiple activities could've been started 166 * and only the latest activity is reported here. 167 */ onActivityLaunchCancelled(@ullable @ctivityRecordProto byte[] abortingActivity)168 public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] abortingActivity); 169 170 /** 171 * Notifies the observer that the current launch sequence has been successfully finished. 172 * 173 * This function call terminates the current launch sequence. The next method call, if any, 174 * must be {@link #onIntentStarted}. 175 * 176 * A launch sequence is considered to be successfully finished when a frame is fully 177 * drawn for the first time: the top-most activity at the time is what's reported here. 178 * 179 * @param finalActivity the top-most activity whose windows were first to fully draw 180 * 181 * Multiple calls to this method cannot occur without first terminating the current 182 * launch sequence. 183 * 184 * @apiNote The finishing activity isn't necessarily the same as the starting activity; 185 * in the case of a trampoline, multiple activities could've been started 186 * and only the latest activity that was top-most during first-frame drawn 187 * is reported here. 188 */ onActivityLaunchFinished(@onNull @ctivityRecordProto byte[] finalActivity)189 public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] finalActivity); 190 } 191