• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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