1 /* 2 * Copyright (C) 2024 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 package android.os; 17 18 import android.annotation.FlaggedApi; 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.os.profiling.Flags; 22 23 import java.lang.annotation.Retention; 24 import java.lang.annotation.RetentionPolicy; 25 26 /** 27 * Encapsulates a single profiling trigger. 28 */ 29 @FlaggedApi(Flags.FLAG_SYSTEM_TRIGGERED_PROFILING_NEW) 30 public final class ProfilingTrigger { 31 32 /** No trigger. Used in {@link ProfilingResult} for non trigger caused results. */ 33 public static final int TRIGGER_TYPE_NONE = 0; 34 35 /** Trigger occurs after {@link Activity#reportFullyDrawn} is called for a cold start. */ 36 public static final int TRIGGER_TYPE_APP_FULLY_DRAWN = 1; 37 38 /** 39 * Trigger occurs after an ANR has been identified, but before the system would attempt to kill 40 * the app. The trigger does not necessarily indicate that the app was killed due to the ANR. 41 */ 42 public static final int TRIGGER_TYPE_ANR = 2; 43 44 /** @hide */ 45 @IntDef(value = { 46 TRIGGER_TYPE_NONE, 47 TRIGGER_TYPE_APP_FULLY_DRAWN, 48 TRIGGER_TYPE_ANR, 49 }) 50 @Retention(RetentionPolicy.SOURCE) 51 @interface TriggerType {} 52 53 /** @see #getTriggerType */ 54 private final @TriggerType int mTriggerType; 55 56 /** @see #getRateLimitingPeriodHours */ 57 private final int mRateLimitingPeriodHours; 58 ProfilingTrigger(@riggerType int triggerType, int rateLimitingPeriodHours)59 private ProfilingTrigger(@TriggerType int triggerType, int rateLimitingPeriodHours) { 60 mTriggerType = triggerType; 61 mRateLimitingPeriodHours = rateLimitingPeriodHours; 62 } 63 64 /** 65 * Builder class to create a {@link ProfilingTrigger} object. 66 */ 67 @FlaggedApi(Flags.FLAG_SYSTEM_TRIGGERED_PROFILING_NEW) 68 public static final class Builder { 69 // Trigger type has to be set, so make it an object and set to null. 70 private int mBuilderTriggerType; 71 72 // Rate limiter period default is 0 which will make it do nothing. 73 private int mBuilderRateLimitingPeriodHours = 0; 74 75 /** 76 * Create a new builder instance to create a {@link ProfilingTrigger} object. 77 * 78 * Requires a trigger type. An app can only have one registered trigger per trigger type. 79 * Adding a new trigger with the same type will override the previously set one. 80 * 81 * @throws IllegalArgumentException if the trigger type is not valid. 82 */ Builder(@riggerType int triggerType)83 public Builder(@TriggerType int triggerType) { 84 if (!isValidRequestTriggerType(triggerType)) { 85 throw new IllegalArgumentException("Invalid trigger type."); 86 } 87 88 mBuilderTriggerType = triggerType; 89 } 90 91 /** Build the {@link ProfilingTrigger} object. */ 92 @NonNull build()93 public ProfilingTrigger build() { 94 return new ProfilingTrigger(mBuilderTriggerType, 95 mBuilderRateLimitingPeriodHours); 96 } 97 98 /** 99 * Set a rate limiting period in hours. 100 * 101 * The period is the minimum time the system should wait before providing another 102 * profiling result for the same trigger; actual time between events may be longer. 103 * 104 * If the rate limiting period is not provided or set to 0, no app-provided rate limiting 105 * will be used. 106 * 107 * This rate limiting is in addition to any system level rate limiting that may be applied. 108 * 109 * @throws IllegalArgumentException if the value is less than 0. 110 */ 111 @NonNull setRateLimitingPeriodHours(int rateLimitingPeriodHours)112 public Builder setRateLimitingPeriodHours(int rateLimitingPeriodHours) { 113 if (rateLimitingPeriodHours < 0) { 114 throw new IllegalArgumentException("Hours can't be negative. Try again."); 115 } 116 117 mBuilderRateLimitingPeriodHours = rateLimitingPeriodHours; 118 return this; 119 } 120 } 121 122 /** The trigger type indicates which event should trigger the requested profiling. */ getTriggerType()123 public @TriggerType int getTriggerType() { 124 return mTriggerType; 125 } 126 127 /** 128 * The requester set rate limiting period in hours. 129 * 130 * The period is the minimum time the system should wait before providing another 131 * profiling result for the same trigger; actual time between events may be longer. 132 * 133 * If the rate limiting period is set to 0, no app-provided rate limiting will be used. 134 * 135 * This rate limiting is in addition to any system level rate limiting that may be applied. 136 */ getRateLimitingPeriodHours()137 public int getRateLimitingPeriodHours() { 138 return mRateLimitingPeriodHours; 139 } 140 141 /** 142 * Convert to value parcel. Used for binder. 143 * 144 * @hide 145 */ toValueParcel()146 public ProfilingTriggerValueParcel toValueParcel() { 147 ProfilingTriggerValueParcel valueParcel = new ProfilingTriggerValueParcel(); 148 149 valueParcel.triggerType = mTriggerType; 150 valueParcel.rateLimitingPeriodHours = mRateLimitingPeriodHours; 151 152 return valueParcel; 153 } 154 155 /** 156 * Check whether the trigger type is valid for request use. Note that this means that a value of 157 * {@link TRIGGER_TYPE_NONE} will return false. 158 * 159 * @hide 160 */ isValidRequestTriggerType(int triggerType)161 public static boolean isValidRequestTriggerType(int triggerType) { 162 return triggerType == TRIGGER_TYPE_APP_FULLY_DRAWN 163 || triggerType == TRIGGER_TYPE_ANR; 164 } 165 166 } 167