1 /*
2  * Copyright 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 androidx.webkit;
18 
19 import androidx.annotation.IntDef;
20 import androidx.annotation.RestrictTo;
21 
22 import org.jspecify.annotations.NonNull;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.List;
30 
31 /**
32  * Holds tracing configuration information and predefined settings
33  * for {@link TracingController}.
34  * <p>
35  * This class is functionally equivalent to {@link android.webkit.TracingConfig}.
36  */
37 public class TracingConfig {
38     @RestrictTo(RestrictTo.Scope.LIBRARY)
39     @IntDef(flag = true, value = {CATEGORIES_NONE, CATEGORIES_ALL, CATEGORIES_ANDROID_WEBVIEW,
40             CATEGORIES_WEB_DEVELOPER, CATEGORIES_INPUT_LATENCY, CATEGORIES_RENDERING,
41             CATEGORIES_JAVASCRIPT_AND_RENDERING, CATEGORIES_FRAME_VIEWER})
42     @Retention(RetentionPolicy.SOURCE)
43     public @interface PredefinedCategories {}
44 
45     /**
46      * Indicates that there are no predefined categories.
47      */
48     public static final int CATEGORIES_NONE = android.webkit.TracingConfig.CATEGORIES_NONE;
49 
50     /**
51      * Predefined set of categories, includes all categories enabled by default in chromium.
52      * Use with caution: this setting may produce large trace output.
53      */
54     public static final int CATEGORIES_ALL = android.webkit.TracingConfig.CATEGORIES_ALL;
55 
56     /**
57      * Predefined set of categories typically useful for analyzing WebViews.
58      * Typically includes "android_webview" and "Java" categories.
59      */
60     public static final int CATEGORIES_ANDROID_WEBVIEW =
61             android.webkit.TracingConfig.CATEGORIES_ANDROID_WEBVIEW;
62 
63     /**
64      * Predefined set of categories typically useful for web developers.
65      * Typically includes "blink", "compositor", "renderer.scheduler" and "v8" categories.
66      */
67     public static final int CATEGORIES_WEB_DEVELOPER =
68             android.webkit.TracingConfig.CATEGORIES_WEB_DEVELOPER;
69 
70     /**
71      * Predefined set of categories for analyzing input latency issues.
72      * Typically includes "input", "renderer.scheduler" categories..
73      */
74     public static final int CATEGORIES_INPUT_LATENCY =
75             android.webkit.TracingConfig.CATEGORIES_INPUT_LATENCY;
76 
77     /**
78      * Predefined set of categories for analyzing rendering issues.
79      * Typically includes "blink", "compositor" and "gpu" categories.
80      */
81     public static final int CATEGORIES_RENDERING =
82             android.webkit.TracingConfig.CATEGORIES_RENDERING;
83 
84     /**
85      * Predefined set of categories for analyzing javascript and rendering issues.
86      * Typically includes "blink", "compositor", "gpu", "renderer.scheduler" and "v8" categories.
87      */
88     public static final int CATEGORIES_JAVASCRIPT_AND_RENDERING =
89             android.webkit.TracingConfig.CATEGORIES_JAVASCRIPT_AND_RENDERING;
90 
91     /**
92      * Predefined set of categories for studying difficult rendering performance problems.
93      * Typically includes "blink", "compositor", "gpu", "renderer.scheduler", "v8" and
94      * some other compositor categories which are disabled by default.
95      */
96     public static final int CATEGORIES_FRAME_VIEWER =
97             android.webkit.TracingConfig.CATEGORIES_FRAME_VIEWER;
98 
99     @RestrictTo(RestrictTo.Scope.LIBRARY)
100     @IntDef({RECORD_UNTIL_FULL, RECORD_CONTINUOUSLY})
101     @Retention(RetentionPolicy.SOURCE)
102     public @interface TracingMode {}
103 
104     /**
105      * Record trace events until the internal tracing buffer is full.
106      * <p>
107      * Typically the buffer memory usage is larger than {@link #RECORD_CONTINUOUSLY}.
108      * Depending on the implementation typically allows up to 256k events to be stored.
109      */
110     public static final int RECORD_UNTIL_FULL = android.webkit.TracingConfig.RECORD_UNTIL_FULL;
111 
112     /**
113      * Record trace events continuously using an internal ring buffer. Default tracing mode.
114      * <p>
115      * Overwrites old events if they exceed buffer capacity. Uses less memory than the
116      * {@link #RECORD_UNTIL_FULL} mode. Depending on the implementation typically allows
117      * up to 64k events to be stored.
118      */
119     public static final int RECORD_CONTINUOUSLY = android.webkit.TracingConfig.RECORD_CONTINUOUSLY;
120 
121     private final @PredefinedCategories int mPredefinedCategories;
122     private final List<String> mCustomIncludedCategories = new ArrayList<>();
123     private final @TracingMode int mTracingMode;
124 
125     @RestrictTo(RestrictTo.Scope.LIBRARY)
TracingConfig(@redefinedCategories int predefinedCategories, @NonNull List<String> customIncludedCategories, @TracingMode int tracingMode)126     public TracingConfig(@PredefinedCategories int predefinedCategories,
127                          @NonNull List<String> customIncludedCategories,
128                          @TracingMode int tracingMode) {
129         mPredefinedCategories = predefinedCategories;
130         mCustomIncludedCategories.addAll(customIncludedCategories);
131         mTracingMode = tracingMode;
132     }
133 
134     /**
135      * Returns a bitmask of the predefined category sets of this configuration.
136      *
137      * @return Bitmask of predefined category sets.
138      */
139     @PredefinedCategories
getPredefinedCategories()140     public int getPredefinedCategories() {
141         return mPredefinedCategories;
142     }
143 
144     /**
145      * Returns the list of included custom category patterns for this configuration.
146      *
147      * @return Empty list if no custom category patterns are specified.
148      */
getCustomIncludedCategories()149     public @NonNull List<String> getCustomIncludedCategories() {
150         return mCustomIncludedCategories;
151     }
152 
153     /**
154      * Returns the tracing mode of this configuration.
155      *
156      * @return The tracing mode of this configuration.
157      */
158     @TracingMode
getTracingMode()159     public int getTracingMode() {
160         return mTracingMode;
161     }
162 
163     /**
164      * Builder used to create {@link TracingConfig} objects.
165      * <p>
166      * Examples:
167      * <pre class="prettyprint">
168      *   // Create a configuration with default options: {@link #CATEGORIES_NONE},
169      *   // {@link #RECORD_CONTINUOUSLY}.
170      *   <code>new TracingConfig.Builder().build()</code>
171      * <p>
172      *   // Record trace events from the "web developer" predefined category sets.
173      *   // Uses a ring buffer (the default {@link #RECORD_CONTINUOUSLY} mode) for
174      *   // internal storage during tracing.
175      *   <code>new TracingConfig.Builder().addCategories(CATEGORIES_WEB_DEVELOPER).build()</code>
176      * <p>
177      *   // Record trace events from the "rendering" and "input latency" predefined
178      *   // category sets.
179      *   <code>new TracingConfig.Builder().addCategories(CATEGORIES_RENDERING,
180      *                                     CATEGORIES_INPUT_LATENCY).build()</code>
181      * <p>
182      *   // Record only the trace events from the "browser" category.
183      *   <code>new TracingConfig.Builder().addCategories("browser").build()</code>
184      * <p>
185      *   // Record only the trace events matching the "blink*" and "renderer*" patterns
186      *   // (e.g. "blink.animations", "renderer_host" and "renderer.scheduler" categories).
187      *   <code>new TracingConfig.Builder().addCategories("blink*","renderer*").build()</code>
188      * <p>
189      *   // Record events from the "web developer" predefined category set and events from
190      *   // the "disabled-by-default-v8.gc" category to understand where garbage collection
191      *   // is being triggered. Uses a limited size buffer for internal storage during tracing.
192      *   <code>new TracingConfig.Builder().addCategories(CATEGORIES_WEB_DEVELOPER)
193      *                              .addCategories("disabled-by-default-v8.gc")
194      *                              .setTracingMode(RECORD_UNTIL_FULL).build()</code>
195      * </pre>
196      */
197     public static class Builder {
198         private @PredefinedCategories int mPredefinedCategories = CATEGORIES_NONE;
199         private final List<String> mCustomIncludedCategories = new ArrayList<>();
200         private @TracingMode int mTracingMode = RECORD_CONTINUOUSLY;
201 
202         /**
203          * Default constructor for Builder.
204          */
Builder()205         public Builder() {
206         }
207 
208         /**
209          * Build {@link TracingConfig} using the current settings.
210          *
211          * @return The {@link TracingConfig} with the current settings.
212          */
build()213         public @NonNull TracingConfig build() {
214             return new TracingConfig(mPredefinedCategories, mCustomIncludedCategories,
215                     mTracingMode);
216         }
217 
218         /**
219          * Adds predefined sets of categories to be included in the trace output.
220          * <p>
221          * A predefined category set can be one of
222          * {@link TracingConfig#CATEGORIES_NONE},
223          * {@link TracingConfig#CATEGORIES_ALL},
224          * {@link TracingConfig#CATEGORIES_ANDROID_WEBVIEW},
225          * {@link TracingConfig#CATEGORIES_WEB_DEVELOPER},
226          * {@link TracingConfig#CATEGORIES_INPUT_LATENCY},
227          * {@link TracingConfig#CATEGORIES_RENDERING},
228          * {@link TracingConfig#CATEGORIES_JAVASCRIPT_AND_RENDERING} or
229          * {@link TracingConfig#CATEGORIES_FRAME_VIEWER}.
230          *
231          * @param predefinedCategories A list or bitmask of predefined category sets.
232          * @return The builder to facilitate chaining.
233          */
addCategories( @redefinedCategories int @NonNull ... predefinedCategories)234         public @NonNull Builder addCategories(
235                 @PredefinedCategories int @NonNull ... predefinedCategories) {
236             for (int categorySet : predefinedCategories) {
237                 mPredefinedCategories |= categorySet;
238             }
239             return this;
240         }
241 
242         /**
243          * Adds custom categories to be included in trace output.
244          * <p>
245          * Note that the categories are defined by the currently-in-use version of WebView. They
246          * live in chromium code and are not part of the Android API.
247          * See <a href="https://www.chromium.org/developers/how-tos/trace-event-profiling-tool">
248          * chromium documentation on tracing</a> for more details.
249          *
250          * @param categories A list of category patterns. A category pattern can contain wildcards,
251          *        e.g. "blink*" or full category name e.g. "renderer.scheduler".
252          * @return The builder to facilitate chaining.
253          */
addCategories(String @onNull .... categories)254         public @NonNull Builder addCategories(String @NonNull ... categories) {
255             mCustomIncludedCategories.addAll(Arrays.asList(categories));
256             return this;
257         }
258 
259         /**
260          * Adds custom categories to be included in trace output.
261          * <p>
262          * Same as {@link #addCategories(String...)} but allows to pass a Collection as a parameter.
263          *
264          * @param categories A list of category patterns.
265          * @return The builder to facilitate chaining.
266          */
addCategories(@onNull Collection<String> categories)267         public @NonNull Builder addCategories(@NonNull Collection<String> categories) {
268             mCustomIncludedCategories.addAll(categories);
269             return this;
270         }
271 
272         /**
273          * Sets the tracing mode for this configuration.
274          * When tracingMode is not set explicitly,
275          * the default is {@link android.webkit.TracingConfig#RECORD_CONTINUOUSLY}.
276          *
277          * @param tracingMode The tracing mode to use, one of
278          *                    {@link TracingConfig#RECORD_UNTIL_FULL} or
279          *                    {@link TracingConfig#RECORD_CONTINUOUSLY}.
280          * @return The builder to facilitate chaining.
281          */
setTracingMode(@racingMode int tracingMode)282         public @NonNull Builder setTracingMode(@TracingMode int tracingMode) {
283             mTracingMode = tracingMode;
284             return this;
285         }
286     }
287 }
288