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 android.content.Context;
20 
21 import androidx.annotation.AnyThread;
22 import androidx.annotation.RequiresFeature;
23 import androidx.annotation.RestrictTo;
24 import androidx.webkit.internal.TracingControllerImpl;
25 
26 import org.jspecify.annotations.NonNull;
27 import org.jspecify.annotations.Nullable;
28 
29 import java.io.OutputStream;
30 import java.util.concurrent.Executor;
31 
32 /**
33  * Manages tracing of WebViews. In particular provides functionality for the app
34  * to enable/disable tracing of parts of code and to collect tracing data.
35  * This is useful for profiling performance issues, debugging and memory usage
36  * analysis in production and real life scenarios.
37  * <p>
38  * The resulting trace data is sent back as a byte sequence in json format. This
39  * file can be loaded in "chrome://tracing" for further analysis.
40  * <p>
41  * Example usage:
42  * <pre class="prettyprint">
43  * TracingController tracingController = TracingController.getInstance();
44  * tracingController.start(new TracingConfig.Builder()
45  *                  .addCategories(CATEGORIES_WEB_DEVELOPER).build());
46  * ...
47  * tracingController.stop(new FileOutputStream("trace.json"),
48  *                        Executors.newSingleThreadExecutor());
49  * </pre>
50  */
51 @AnyThread
52 public abstract class TracingController {
53     /**
54      *
55      */
56     @RestrictTo(RestrictTo.Scope.LIBRARY)
TracingController()57     public TracingController() {}
58 
59     /**
60      * Returns the default {@link TracingController} instance. At present there is
61      * only one TracingController instance for all WebView instances.
62      *
63      * <p>
64      * This method should only be called if {@link WebViewFeature#isFeatureSupported(String)}
65      * returns {@code true} for {@link WebViewFeature#TRACING_CONTROLLER_BASIC_USAGE}.
66      *
67      */
68     @RequiresFeature(name = WebViewFeature.TRACING_CONTROLLER_BASIC_USAGE,
69             enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
getInstance()70     public static @NonNull TracingController getInstance() {
71         return LAZY_HOLDER.INSTANCE;
72     }
73 
74     private static class LAZY_HOLDER {
75         static final TracingController INSTANCE = new TracingControllerImpl();
76     }
77 
78     /**
79      * Starts tracing all WebViews. Depending on the trace mode in traceConfig
80      * specifies how the trace events are recorded.
81      *
82      * <p>
83      * For tracing modes {@link android.webkit.TracingConfig#RECORD_UNTIL_FULL} and
84      * {@link android.webkit.TracingConfig#RECORD_CONTINUOUSLY} the events are recorded
85      * using an internal buffer and flushed to the outputStream when
86      * {@link #stop(OutputStream, Executor)} is called.
87      *
88      * <p>
89      * This method should only be called if {@link WebViewFeature#isFeatureSupported(String)}
90      * returns {@code true} for {@link WebViewFeature#TRACING_CONTROLLER_BASIC_USAGE}.
91      *
92      * @param tracingConfig Configuration options to use for tracing.
93      *
94      * @throws IllegalStateException If the system is already tracing.
95      * @throws IllegalArgumentException If the configuration is invalid (e.g.
96      *         invalid category pattern or invalid tracing mode).
97      */
start(@onNull TracingConfig tracingConfig)98     public abstract void start(@NonNull TracingConfig tracingConfig);
99 
100     /**
101      * Stops tracing and flushes tracing data to the specified outputStream.
102      * <p>
103      * The data is sent to the specified output stream in json format typically in chunks
104      * by invoking {@link OutputStream#write(byte[])}.
105      * On completion the {@link OutputStream#close()} method is called.
106      *
107      * <p>
108      * This method should only be called if {@link WebViewFeature#isFeatureSupported(String)}
109      * returns {@code true} for {@link WebViewFeature#TRACING_CONTROLLER_BASIC_USAGE}.
110      *
111      * @param outputStream The output stream the tracing data will be sent to.
112      *                     If {@code null} the tracing data will be discarded.
113      * @param executor The Executor on which the outputStream {@link OutputStream#write(byte[])} and
114      *                 {@link OutputStream#close()} methods will be invoked.
115      * <p>
116      *                 Callback and listener events are dispatched through this Executor,
117      *                 providing an easy way to control which thread is used.
118      *                 To dispatch events through the main thread of your application,
119      *                 you can use {@link Context#getMainExecutor()}.
120      *                 To dispatch events through a shared thread pool,
121      *                 you can use {@link android.os.AsyncTask#THREAD_POOL_EXECUTOR}.
122      *
123      * @return {@code false} if the WebView framework was not tracing at the time of the call,
124      * {@code true} otherwise.
125      */
stop(@ullable OutputStream outputStream, @NonNull Executor executor)126     public abstract boolean stop(@Nullable OutputStream outputStream, @NonNull Executor executor);
127 
128     /**
129      * Returns whether the WebView framework is tracing.
130      *
131      * @return True if tracing is enabled.
132      */
isTracing()133     public abstract boolean isTracing();
134 }
135