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