• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package android.net.http;
6 
7 import android.annotation.SuppressLint;
8 import android.content.Context;
9 import android.net.Network;
10 
11 import androidx.annotation.NonNull;
12 import androidx.annotation.Nullable;
13 
14 import com.android.internal.annotations.VisibleForTesting;
15 
16 import java.io.IOException;
17 import java.lang.reflect.InvocationTargetException;
18 import java.lang.reflect.Method;
19 import java.net.URL;
20 import java.net.URLConnection;
21 import java.net.URLStreamHandlerFactory;
22 import java.time.Instant;
23 import java.util.Set;
24 import java.util.concurrent.Executor;
25 
26 import javax.net.ssl.HttpsURLConnection;
27 
28 /**
29  * An engine to process {@link UrlRequest}s, which uses the best HTTP stack available on the current
30  * platform. An instance of this class can be created using {@link Builder}.
31  */
32 // SuppressLint: Making the HttpEngine AutoCloseable indicates to the developers that it's
33 // expected to be used in a try-with-resource clause. This in turn promotes local, narrowly
34 // scoped instances of HttpEngine. That's the exact opposite of how HttpEngine is supposed
35 // to be used - it should live in an application-wide scope and be reused multiple times across
36 // the lifespan of the app.
37 @SuppressLint("NotCloseable")
38 public abstract class HttpEngine {
39 
40     /**
41      * {@hide}
42      */
HttpEngine()43     protected HttpEngine() {}
44 
45     /**
46      * Returns a new {@link Builder} object that facilitates creating a {@link HttpEngine}.
47      *
48      * {@hide}
49      */
50     @NonNull
builder(@onNull Context context)51     public static Builder builder(@NonNull Context context) {
52         return new Builder(context);
53     }
54 
55     /**
56      * The value of the active request count is unknown
57      *
58      * {@hide}
59      */
60     public static final int ACTIVE_REQUEST_COUNT_UNKNOWN = -1;
61 
62     /**
63      * The value of a connection metric is unknown.
64      *
65      * {@hide}
66      */
67     public static final int CONNECTION_METRIC_UNKNOWN = -1;
68 
69     /**
70      * The estimate of the effective connection type is unknown.
71      *
72      * {@hide}
73      *
74      * @see #getEffectiveConnectionType
75      */
76     public static final int EFFECTIVE_CONNECTION_TYPE_UNKNOWN = 0;
77 
78     /**
79      * The device is offline.
80      *
81      * @see #getEffectiveConnectionType
82      *
83      * {@hide}
84      */
85     public static final int EFFECTIVE_CONNECTION_TYPE_OFFLINE = 1;
86 
87     /**
88      * The estimate of the effective connection type is slow 2G.
89      *
90      * @see #getEffectiveConnectionType
91      *
92      * {@hide}
93      */
94     public static final int EFFECTIVE_CONNECTION_TYPE_SLOW_2G = 2;
95 
96     /**
97      * The estimate of the effective connection type is 2G.
98      *
99      * @see #getEffectiveConnectionType
100      *
101      * {@hide}
102      */
103     public static final int EFFECTIVE_CONNECTION_TYPE_2G = 3;
104 
105     /**
106      * The estimate of the effective connection type is 3G.
107      *
108      * @see #getEffectiveConnectionType
109      *
110      * {@hide}
111      */
112     public static final int EFFECTIVE_CONNECTION_TYPE_3G = 4;
113 
114     /**
115      * The estimate of the effective connection type is 4G.
116      *
117      * @see #getEffectiveConnectionType
118      *
119      * {@hide}
120      */
121     public static final int EFFECTIVE_CONNECTION_TYPE_4G = 5;
122 
123     /**
124      * A builder for {@link HttpEngine}s, which allows runtime configuration of
125      * {@link HttpEngine}. Configuration options are set on the builder and
126      * then {@link #build} is called to create the {@link HttpEngine}.
127      */
128     // NOTE(kapishnikov): In order to avoid breaking the existing API clients, all future methods
129     // added to this class and other API classes must have default implementation.
130     // SuppressLint: Builder can not be final since ExperimentalHttpEngine.Builder inherit this
131     // Builder.
132     @SuppressLint("StaticFinalBuilder")
133     public static class Builder {
134 
135         /**
136          * Reference to the actual builder implementation. {@hide exclude from JavaDoc}.
137          */
138         protected final IHttpEngineBuilder mBuilderDelegate;
139 
140         /**
141          * Constructs a {@link Builder} object that facilitates creating a
142          * {@link HttpEngine}. The default configuration enables HTTP/2 and
143          * QUIC, but disables the HTTP cache.
144          *
145          * @param context Android {@link Context}, which is used by {@link Builder} to retrieve the
146          * application context. A reference to only the application context will be kept, so as to
147          * avoid extending the lifetime of {@code context} unnecessarily.
148          */
Builder(@onNull Context context)149         public Builder(@NonNull Context context) {
150             this(createBuilderDelegate(context));
151         }
152 
153         /**
154          * Constructs {@link Builder} with a given delegate that provides the actual implementation
155          * of the {@code Builder} methods. This constructor is used only by the internal
156          * implementation.
157          *
158          * @param builderDelegate delegate that provides the actual implementation.
159          *
160          * {@hide}
161          */
162         @VisibleForTesting
Builder(@onNull IHttpEngineBuilder builderDelegate)163         public Builder(@NonNull IHttpEngineBuilder builderDelegate) {
164             if (builderDelegate instanceof ExperimentalOptionsTranslatingHttpEngineBuilder) {
165                 // Already wrapped at the top level, no need to do it again
166                 mBuilderDelegate = builderDelegate;
167             } else {
168                 mBuilderDelegate =
169                         new ExperimentalOptionsTranslatingHttpEngineBuilder(builderDelegate);
170             }
171         }
172 
173         /**
174          * Constructs a default User-Agent string including the system build version, model and id,
175          * and the HTTP stack version.
176          *
177          * @return User-Agent string.
178          */
179         // SuppressLint: API to get default user agent that could include system build version,
180         // model, Id, and Cronet version.
181         @NonNull @SuppressLint("GetterOnBuilder")
getDefaultUserAgent()182         public String getDefaultUserAgent() {
183             return mBuilderDelegate.getDefaultUserAgent();
184         }
185 
186         /**
187          * Overrides the User-Agent header for all requests. An explicitly set User-Agent header
188          * (set using {@link UrlRequest.Builder#addHeader}) will override a value set using this
189          * function.
190          *
191          * @param userAgent the User-Agent string to use for all requests.
192          * @return the builder to facilitate chaining.
193          */
194         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
195         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
setUserAgent(@onNull String userAgent)196         public Builder setUserAgent(@NonNull String userAgent) {
197             mBuilderDelegate.setUserAgent(userAgent);
198             return this;
199         }
200 
201         /**
202          * Sets directory for HTTP Cache and Cookie Storage. The directory must
203          * exist.
204          * <p>
205          * <b>NOTE:</b> Do not use the same storage directory with more than one
206          * {@link HttpEngine} at a time. Access to the storage directory does
207          * not support concurrent access by multiple {@link HttpEngine} instances.
208          *
209          * @param value path to existing directory.
210          * @return the builder to facilitate chaining.
211          */
212         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
213         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
setStoragePath(@onNull String value)214         public Builder setStoragePath(@NonNull String value) {
215             mBuilderDelegate.setStoragePath(value);
216             return this;
217         }
218 
219         /**
220          * Sets whether <a href="https://www.chromium.org/quic">QUIC</a> protocol
221          * is enabled. Defaults to enabled.
222          *
223          * @param value {@code true} to enable QUIC, {@code false} to disable.
224          * @return the builder to facilitate chaining.
225          */
226         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
227         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
setEnableQuic(boolean value)228         public Builder setEnableQuic(boolean value) {
229             mBuilderDelegate.enableQuic(value);
230             return this;
231         }
232 
233         /**
234          * Sets whether <a href="https://tools.ietf.org/html/rfc7540">HTTP/2</a> protocol is
235          * enabled. Defaults to enabled.
236          *
237          * @param value {@code true} to enable HTTP/2, {@code false} to disable.
238          * @return the builder to facilitate chaining.
239          */
240         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
241         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
setEnableHttp2(boolean value)242         public Builder setEnableHttp2(boolean value) {
243             mBuilderDelegate.enableHttp2(value);
244             return this;
245         }
246 
247         /**
248          * Sets whether <a href="https://tools.ietf.org/html/rfc7932">Brotli</a> compression is
249          * enabled. If enabled, Brotli will be advertised in Accept-Encoding request headers.
250          * Defaults to disabled.
251          *
252          * @param value {@code true} to enable Brotli, {@code false} to disable.
253          * @return the builder to facilitate chaining.
254          */
255         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
256         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
setEnableBrotli(boolean value)257         public Builder setEnableBrotli(boolean value) {
258             mBuilderDelegate.enableBrotli(value);
259             return this;
260         }
261 
262         /**
263          * Setting to disable HTTP cache. Some data may still be temporarily stored in memory.
264          * Passed to {@link #setEnableHttpCache}.
265          */
266         public static final int HTTP_CACHE_DISABLED = 0;
267 
268         /**
269          * Setting to enable in-memory HTTP cache, including HTTP data.
270          * Passed to {@link #setEnableHttpCache}.
271          */
272         public static final int HTTP_CACHE_IN_MEMORY = 1;
273 
274         /**
275          * Setting to enable on-disk cache, excluding HTTP data.
276          * {@link #setStoragePath} must be called prior to passing this constant to
277          * {@link #setEnableHttpCache}.
278          */
279         public static final int HTTP_CACHE_DISK_NO_HTTP = 2;
280 
281         /**
282          * Setting to enable on-disk cache, including HTTP data.
283          * {@link #setStoragePath} must be called prior to passing this constant to
284          * {@link #setEnableHttpCache}.
285          */
286         public static final int HTTP_CACHE_DISK = 3;
287 
288         /**
289          * Enables or disables caching of HTTP data and other information like QUIC server
290          * information.
291          *
292          * @param cacheMode control location and type of cached data. Must be one of {@link
293          * #HTTP_CACHE_DISABLED HTTP_CACHE_*}.
294          * @param maxSize maximum size in bytes used to cache data (advisory and maybe exceeded at
295          * times).
296          * @return the builder to facilitate chaining.
297          */
298         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
299         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
setEnableHttpCache(int cacheMode, long maxSize)300         public Builder setEnableHttpCache(int cacheMode, long maxSize) {
301             mBuilderDelegate.enableHttpCache(cacheMode, maxSize);
302             return this;
303         }
304 
305         /**
306          * Adds hint that {@code host} supports QUIC.
307          * Note that {@link #setEnableHttpCache enableHttpCache}
308          * ({@link #HTTP_CACHE_DISK}) is needed to take advantage of 0-RTT
309          * connection establishment between sessions.
310          *
311          * @param host hostname of the server that supports QUIC.
312          * @param port host of the server that supports QUIC.
313          * @param alternatePort alternate port to use for QUIC.
314          * @return the builder to facilitate chaining.
315          */
316         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
317         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
addQuicHint(@onNull String host, int port, int alternatePort)318         public Builder addQuicHint(@NonNull String host, int port, int alternatePort) {
319             mBuilderDelegate.addQuicHint(host, port, alternatePort);
320             return this;
321         }
322 
323         /**
324          * Pins a set of public keys for a given host. By pinning a set of public keys, {@code
325          * pinsSha256}, communication with {@code hostName} is required to authenticate with a
326          * certificate with a public key from the set of pinned ones. An app can pin the public key
327          * of the root certificate, any of the intermediate certificates or the end-entry
328          * certificate. Authentication will fail and secure communication will not be established if
329          * none of the public keys is present in the host's certificate chain, even if the host
330          * attempts to authenticate with a certificate allowed by the device's trusted store of
331          * certificates.
332          *
333          * <p>Calling this method multiple times with the same host name overrides the previously
334          * set pins for the host.
335          *
336          * <p>More information about the public key pinning can be found in <a
337          * href="https://tools.ietf.org/html/rfc7469">RFC 7469</a>.
338          *
339          * @param hostName name of the host to which the public keys should be pinned. A host that
340          * consists only of digits and the dot character is treated as invalid.
341          * @param pinsSha256 a set of pins. Each pin is the SHA-256 cryptographic hash of the
342          * DER-encoded ASN.1 representation of the Subject Public Key Info (SPKI) of the host's
343          * X.509 certificate. Use {@link java.security.cert.Certificate#getPublicKey()
344          * Certificate.getPublicKey()} and {@link java.security.Key#getEncoded() Key.getEncoded()}
345          * to obtain DER-encoded ASN.1 representation of the SPKI. Although, the method does not
346          * mandate the presence of the backup pin that can be used if the control of the primary
347          * private key has been lost, it is highly recommended to supply one.
348          * @param includeSubdomains indicates whether the pinning policy should be applied to
349          *                          subdomains of {@code hostName}.
350          * @param expirationInstant specifies the expiration instant for the pins.
351          * @return the builder to facilitate chaining.
352          * @throws NullPointerException if any of the input parameters are {@code null}.
353          * @throws IllegalArgumentException if the given host name is invalid or {@code pinsSha256}
354          * contains a byte array that does not represent a valid SHA-256 hash.
355          */
356         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
357         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
addPublicKeyPins(@onNull String hostName, @NonNull Set<byte[]> pinsSha256, boolean includeSubdomains, @NonNull Instant expirationInstant)358         public Builder addPublicKeyPins(@NonNull String hostName, @NonNull Set<byte[]> pinsSha256,
359                 boolean includeSubdomains, @NonNull Instant expirationInstant) {
360             mBuilderDelegate.addPublicKeyPins(
361                     hostName, pinsSha256, includeSubdomains, expirationInstant);
362             return this;
363         }
364 
365         /**
366          * Enables or disables public key pinning bypass for local trust anchors. Disabling the
367          * bypass for local trust anchors is highly discouraged since it may prohibit the app from
368          * communicating with the pinned hosts. E.g., a user may want to send all traffic through an
369          * SSL enabled proxy by changing the device proxy settings and adding the proxy certificate
370          * to the list of local trust anchor. Disabling the bypass will most likely prevent the app
371          * from sending any traffic to the pinned hosts. For more information see 'How does key
372          * pinning interact with local proxies and filters?' at
373          * https://www.chromium.org/Home/chromium-security/security-faq
374          *
375          * @param value {@code true} to enable the bypass, {@code false} to disable.
376          * @return the builder to facilitate chaining.
377          */
378         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
379         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
setEnablePublicKeyPinningBypassForLocalTrustAnchors(boolean value)380         public Builder setEnablePublicKeyPinningBypassForLocalTrustAnchors(boolean value) {
381             mBuilderDelegate.enablePublicKeyPinningBypassForLocalTrustAnchors(value);
382             return this;
383         }
384 
385         /**
386          * Configures the behavior of the HTTP stack when using QUIC. For more details, see
387          * documentation of {@link QuicOptions} and the individual methods
388          * of {@link QuicOptions.Builder}.
389          *
390          * <p>Only relevant if {@link #setEnableQuic(boolean)} is enabled.
391          *
392          * @return the builder to facilitate chaining.
393          */
394         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
395         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
396         @QuicOptions.Experimental
setQuicOptions(@onNull QuicOptions quicOptions)397         public Builder setQuicOptions(@NonNull QuicOptions quicOptions) {
398             mBuilderDelegate.setQuicOptions(quicOptions);
399             return this;
400         }
401 
402         /**
403          * @see #setQuicOptions(QuicOptions)
404          *
405          * {@hide}
406          */
407         @NonNull
408         @QuicOptions.Experimental
setQuicOptions(@onNull QuicOptions.Builder quicOptionsBuilder)409         public Builder setQuicOptions(@NonNull QuicOptions.Builder quicOptionsBuilder) {
410             return setQuicOptions(quicOptionsBuilder.build());
411         }
412 
413         /**
414          * Configures the behavior of hostname lookup. For more details, see documentation
415          * of {@link DnsOptions} and the individual methods of {@link DnsOptions.Builder}.
416          *
417          * <p>Only relevant if {@link #setEnableQuic(boolean)} is enabled.
418          *
419          * @return the builder to facilitate chaining.
420          */
421         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
422         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
423         @DnsOptions.Experimental
setDnsOptions(@onNull DnsOptions dnsOptions)424         public Builder setDnsOptions(@NonNull DnsOptions dnsOptions) {
425             mBuilderDelegate.setDnsOptions(dnsOptions);
426             return this;
427         }
428 
429         /**
430          * @see #setDnsOptions(DnsOptions)
431          *
432          * {@hide}
433          */
434         @NonNull
435         @DnsOptions.Experimental
setDnsOptions(@onNull DnsOptions.Builder dnsOptions)436         public Builder setDnsOptions(@NonNull DnsOptions.Builder dnsOptions) {
437             return setDnsOptions(dnsOptions.build());
438         }
439 
440         /**
441          * Configures the behavior of connection migration. For more details, see documentation
442          * of {@link ConnectionMigrationOptions} and the individual methods of {@link
443          * ConnectionMigrationOptions.Builder}.
444          *
445          * <p>Only relevant if {@link #setEnableQuic(boolean)} is enabled.
446          *
447          * @return the builder to facilitate chaining.
448          */
449         // SuppressLint: Value is passed to JNI code and maintained by JNI code after build
450         @NonNull @SuppressLint("MissingGetterMatchingBuilder")
451         @ConnectionMigrationOptions.Experimental
setConnectionMigrationOptions( @onNull ConnectionMigrationOptions connectionMigrationOptions)452         public Builder setConnectionMigrationOptions(
453                 @NonNull ConnectionMigrationOptions connectionMigrationOptions) {
454             mBuilderDelegate.setConnectionMigrationOptions(connectionMigrationOptions);
455             return this;
456         }
457 
458         /**
459          * @see #setConnectionMigrationOptions(ConnectionMigrationOptions)
460          *
461          * {@hide}
462          */
463         @NonNull
464         @ConnectionMigrationOptions.Experimental
setConnectionMigrationOptions( @onNull ConnectionMigrationOptions.Builder connectionMigrationOptionsBuilder)465         public Builder setConnectionMigrationOptions(
466                 @NonNull ConnectionMigrationOptions.Builder connectionMigrationOptionsBuilder) {
467             return setConnectionMigrationOptions(connectionMigrationOptionsBuilder.build());
468         }
469 
470         /**
471          * Sets the thread priority of Cronet's internal thread.
472          *
473          * @param priority the thread priority of Cronet's internal thread. A Linux priority level,
474          *         from
475          * -20 for highest scheduling priority to 19 for lowest scheduling priority. For more
476          * information on values, see {@link android.os.Process#setThreadPriority(int, int)} and
477          * {@link android.os.Process#THREAD_PRIORITY_DEFAULT THREAD_PRIORITY_*} values.
478          * @return the builder to facilitate chaining.
479          *
480          * {@hide}
481          */
setThreadPriority(int priority)482         public Builder setThreadPriority(int priority) {
483             mBuilderDelegate.setThreadPriority(priority);
484             return this;
485         }
486 
487         /**
488          * Enables the network quality estimator, which collects and reports measurements of round
489          * trip time (RTT) and downstream throughput at various layers of the network stack. After
490          * enabling the estimator, listeners of RTT and throughput can be added with {@link
491          * #addRttListener} and
492          * {@link #addThroughputListener} and removed with {@link #removeRttListener} and {@link
493          * #removeThroughputListener}. The estimator uses memory and CPU only when enabled.
494          *
495          * @param value {@code true} to enable network quality estimator, {@code false} to disable.
496          * @return the builder to facilitate chaining.
497          *
498          * {@hide}
499          */
enableNetworkQualityEstimator(boolean value)500         public Builder enableNetworkQualityEstimator(boolean value) {
501             mBuilderDelegate.enableNetworkQualityEstimator(value);
502             return this;
503         }
504 
505         /**
506          * Build a {@link HttpEngine} using this builder's configuration.
507          * @return constructed {@link HttpEngine}.
508          */
509         @NonNull
build()510         public HttpEngine build() {
511             return mBuilderDelegate.build();
512         }
513 
514         /**
515          * Creates an implementation of {@link IHttpEngineBuilder} that can be used
516          * to delegate the builder calls to.
517          *
518          * @param context Android Context to use.
519          * @return the created {@link IHttpEngineBuilder}.
520          */
createBuilderDelegate(Context context)521         private static IHttpEngineBuilder createBuilderDelegate(Context context) {
522             try {
523                 Class<?> clazz = context.getClassLoader().loadClass(
524                         "android.net.connectivity.org.chromium.net.impl.NativeCronetEngineBuilderImpl");
525 
526                 return (IHttpEngineBuilder) clazz.getConstructor(Context.class).newInstance(
527                         context);
528             } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
529                 throw new IllegalArgumentException(e);
530             }
531         }
532     }
533 
534     /**
535      * @return a human-readable version string of the engine.
536      */
537     @NonNull
getVersionString()538     public static String getVersionString() {
539         return ApiVersion.getCronetVersion();
540     }
541 
542     /**
543      * Shuts down the {@link HttpEngine} if there are no active requests,
544      * otherwise throws an exception.
545      *
546      * Cannot be called on network thread - the thread the HTTP stack calls into
547      * Executor on (which is different from the thread the Executor invokes
548      * callbacks on). May block until all the {@link HttpEngine} resources have been cleaned up.
549      */
shutdown()550     public abstract void shutdown();
551 
552     /**
553      * Starts NetLog logging to a file. The NetLog will contain events emitted
554      * by all live {@link HttpEngine} instances. The NetLog is useful for debugging.
555      * The file can be viewed using a Chrome browser navigated to
556      * chrome://net-internals/#import
557      * @param fileName the complete file path. It must not be empty. If the file
558      *            exists, it is truncated before starting. If actively logging,
559      *            this method is ignored.
560      * @param logAll {@code true} to include basic events, user cookies,
561      *            credentials and all transferred bytes in the log. This option presents
562      *            a privacy risk, since it exposes the user's credentials, and should
563      *            only be used with the user's consent and in situations where the log
564      *            won't be public.
565      *            {@code false} to just include basic events.
566      *
567      * {@hide}
568      */
startNetLogToFile(@onNull String fileName, boolean logAll)569     public void startNetLogToFile(@NonNull String fileName, boolean logAll) {}
570 
571     /**
572      * Stops NetLog logging and flushes file to disk. If a logging session is
573      * not in progress, this call is ignored.
574      *
575      * {@hide}
576      */
stopNetLog()577     public void stopNetLog() {}
578 
579     /**
580      * Returns differences in metrics collected by Cronet since the last call to
581      * this method.
582      * <p>
583      * Cronet collects these metrics globally. This means deltas returned by
584      * {@code getGlobalMetricsDeltas()} will include measurements of requests
585      * processed by other {@link HttpEngine} instances. Since this function
586      * returns differences in metrics collected since the last call, and these
587      * metrics are collected globally, a call to any {@code CronetEngine}
588      * instance's {@code getGlobalMetricsDeltas()} method will affect the deltas
589      * returned by any other {@code CronetEngine} instance's
590      * {@code getGlobalMetricsDeltas()}.
591      * <p>
592      * Cronet starts collecting these metrics after the first call to
593      * {@code getGlobalMetricsDeltras()}, so the first call returns no
594      * useful data as no metrics have yet been collected.
595      *
596      * @return differences in metrics collected by Cronet, since the last call
597      *         to {@code getGlobalMetricsDeltas()}, serialized as a
598      *         <a href=https://developers.google.com/protocol-buffers>protobuf
599      *         </a>, or an empty array if collecting metrics is not supported.
600      *
601      * {@hide}
602      */
603     @NonNull
getGlobalMetricsDeltas()604     public byte[] getGlobalMetricsDeltas() {
605         return new byte[0];
606     }
607 
608     /**
609      * Binds the engine to the specified network. All requests created through this engine
610      * will use the network associated to this handle. If this network disconnects all requests will
611      * fail, the exact error will depend on the stage of request processing when the network
612      * disconnects.
613      *
614      * @param network the network to bind the engine to. Specify {@code null} to unbind.
615      */
bindToNetwork(@ullable Network network)616     public void bindToNetwork(@Nullable Network network) {}
617 
618     /**
619      * Establishes a new connection to the resource specified by the {@link URL} {@code url}.
620      * <p>
621      * <b>Note:</b> This {@link java.net.HttpURLConnection} implementation is subject to certain
622      * limitations, see {@link #createUrlStreamHandlerFactory} for details.
623      *
624      * @param url URL of resource to connect to.
625      * @return an {@link java.net.HttpURLConnection} instance implemented
626      *     by this {@link HttpEngine}.
627      * @throws IOException if an error occurs while opening the connection.
628      */
629     // SuppressLint since this is for interface parity with j.n.URLConnection
630     @SuppressLint("AndroidUri") @NonNull
openConnection( @uppressLint"AndroidUri") @onNull URL url)631     public abstract URLConnection openConnection(
632             @SuppressLint("AndroidUri") @NonNull URL url) throws IOException;
633 
634     /**
635      * Creates a {@link URLStreamHandlerFactory} to handle HTTP and HTTPS
636      * traffic. An instance of this class can be installed via
637      * {@link URL#setURLStreamHandlerFactory} thus using this {@link HttpEngine} by default for
638      * all requests created via {@link URL#openConnection}.
639      * <p>
640      * This {@link java.net.HttpURLConnection} implementation does not implement all features
641      * offered by the API:
642      * <ul>
643      * <li>the HTTP cache installed via
644      *     {@link HttpResponseCache#install(java.io.File, long) HttpResponseCache.install()}</li>
645      * <li>the HTTP authentication method installed via
646      *     {@link java.net.Authenticator#setDefault}</li>
647      * <li>the HTTP cookie storage installed via {@link java.net.CookieHandler#setDefault}</li>
648      * </ul>
649      * <p>
650      * While we support and encourages requests using the HTTPS protocol, we don't provide support
651      * for the {@link HttpsURLConnection} API. This lack of support also includes not using certain
652      * HTTPS features provided via {@link HttpsURLConnection}:
653      * <ul>
654      * <li>the HTTPS hostname verifier installed via {@link
655      *   HttpsURLConnection#setDefaultHostnameVerifier(javax.net.ssl.HostnameVerifier)
656      *     HttpsURLConnection.setDefaultHostnameVerifier()}</li>
657      * <li>the HTTPS socket factory installed via {@link
658      *   HttpsURLConnection#setDefaultSSLSocketFactory(javax.net.ssl.SSLSocketFactory)
659      *     HttpsURLConnection.setDefaultSSLSocketFactory()}</li>
660      * </ul>
661      *
662      * @return an {@link URLStreamHandlerFactory} instance implemented by this
663      *         {@link HttpEngine}.
664      */
665     // SuppressLint since this is for interface parity with j.n.URLStreamHandlerFactory
666     @SuppressLint("AndroidUri") @NonNull
createUrlStreamHandlerFactory()667     public abstract URLStreamHandlerFactory createUrlStreamHandlerFactory();
668 
669     /**
670      * Creates a builder for {@link UrlRequest}. All callbacks for
671      * generated {@link UrlRequest} objects will be invoked on
672      * {@code executor}'s threads. {@code executor} must not run tasks on the
673      * thread calling {@link Executor#execute} to prevent blocking networking
674      * operations and causing exceptions during shutdown.
675      *
676      * @param url URL for the generated requests.
677      * @param executor {@link Executor} on which all callbacks will be invoked.
678      * @param callback callback object that gets invoked on different events.
679      */
680     @NonNull
newUrlRequestBuilder( @onNull String url, @NonNull Executor executor, @NonNull UrlRequest.Callback callback)681     public abstract UrlRequest.Builder newUrlRequestBuilder(
682             @NonNull String url, @NonNull Executor executor, @NonNull UrlRequest.Callback callback);
683 
684     /**
685      * Creates a builder for {@link UrlRequest}. All callbacks for generated {@link UrlRequest}
686      * objects will be invoked on {@code executor}'s threads. {@code executor} must not run tasks on
687      * the thread calling {@link Executor#execute} to prevent blocking networking operations and
688      * causing exceptions during shutdown.
689      *
690      * @param url URL for the generated requests.
691      * @param callback callback object that gets invoked on different events.
692      * @param executor {@link Executor} on which all callbacks will be invoked.
693      *
694      * @hide
695      */
696     // This API is kept for the backward compatibility in upstream
697     @NonNull
newUrlRequestBuilder(@onNull String url, @NonNull UrlRequest.Callback callback, @NonNull Executor executor)698     public UrlRequest.Builder newUrlRequestBuilder(@NonNull String url,
699             @NonNull UrlRequest.Callback callback, @NonNull Executor executor) {
700         return newUrlRequestBuilder(url, executor, callback);
701     }
702 
703     /**
704      * Creates a builder for {@link BidirectionalStream} objects. All callbacks for
705      * generated {@code BidirectionalStream} objects will be invoked on
706      * {@code executor}. {@code executor} must not run tasks on the
707      * current thread, otherwise the networking operations may block and exceptions
708      * may be thrown at shutdown time.
709      *
710      * @param url URL for the generated streams.
711      * @param executor the {@link Executor} on which {@code callback} methods will be invoked.
712      * @param callback the {@link BidirectionalStream.Callback} object that gets invoked upon
713      * different events occurring.
714      *
715      * @return the created builder.
716      */
717     @NonNull
newBidirectionalStreamBuilder( @onNull String url, @NonNull Executor executor, @NonNull BidirectionalStream.Callback callback)718     public abstract BidirectionalStream.Builder newBidirectionalStreamBuilder(
719             @NonNull String url, @NonNull Executor executor,
720             @NonNull BidirectionalStream.Callback callback);
721 
722     /**
723      * Creates a builder for {@link BidirectionalStream} objects. All callbacks for
724      * generated {@code BidirectionalStream} objects will be invoked on
725      * {@code executor}. {@code executor} must not run tasks on the
726      * current thread, otherwise the networking operations may block and exceptions
727      * may be thrown at shutdown time.
728      *
729      * @param url URL for the generated streams.
730      * @param callback the {@link BidirectionalStream.Callback} object that gets invoked upon
731      * different events occurring.
732      * @param executor the {@link Executor} on which {@code callback} methods will be invoked.
733      *
734      * @return the created builder.
735      *
736      * @hide
737      */
738     // This API is kept for the backward compatibility in upstream
739     @NonNull
newBidirectionalStreamBuilder( @onNull String url, @NonNull BidirectionalStream.Callback callback, @NonNull Executor executor)740     public BidirectionalStream.Builder newBidirectionalStreamBuilder(
741             @NonNull String url, @NonNull BidirectionalStream.Callback callback,
742             @NonNull Executor executor) {
743         return newBidirectionalStreamBuilder(url, executor, callback);
744     }
745 
746     /**
747      * Returns the number of in-flight requests.
748      * <p>
749      * A request is in-flight if its start() method has been called but it hasn't reached a final
750      * state yet. A request reaches the final state when one of the following callbacks has been
751      * called:
752      * <ul>
753      *    <li>onSucceeded</li>
754      *    <li>onCanceled</li>
755      *    <li>onFailed</li>
756      * </ul>
757      *
758      * <a href="https://developer.android.com/guide/topics/connectivity/cronet/lifecycle">Cronet
759      *         requests's lifecycle</a> for more information.
760      *
761      * {@hide}
762      */
getActiveRequestCount()763     public int getActiveRequestCount() {
764         return ACTIVE_REQUEST_COUNT_UNKNOWN;
765     }
766 
767     /**
768      * Registers a listener that gets called after the end of each request with the request info.
769      *
770      * <p>The listener is called on an {@link java.util.concurrent.Executor} provided by the
771      * listener.
772      *
773      * @param listener the listener for finished requests.
774      *
775      * {@hide}
776      */
addRequestFinishedListener(RequestFinishedInfo.Listener listener)777     public void addRequestFinishedListener(RequestFinishedInfo.Listener listener) {}
778 
779     /**
780      * Removes a finished request listener.
781      *
782      * @param listener the listener to remove.
783      *
784      * {@hide}
785      */
removeRequestFinishedListener(RequestFinishedInfo.Listener listener)786     public void removeRequestFinishedListener(RequestFinishedInfo.Listener listener) {}
787 
788     /**
789      * Returns the HTTP RTT estimate (in milliseconds) computed by the network quality estimator.
790      * Set to {@link #CONNECTION_METRIC_UNKNOWN} if the value is unavailable. This must be called
791      * after
792      * {@link Builder#enableNetworkQualityEstimator}, and will throw an exception otherwise.
793      *
794      * @return Estimate of the HTTP RTT in milliseconds.
795      *
796      * {@hide}
797      */
getHttpRttMs()798     public int getHttpRttMs() {
799         return CONNECTION_METRIC_UNKNOWN;
800     }
801 
802     /**
803      * Returns the transport RTT estimate (in milliseconds) computed by the network quality
804      * estimator. Set to {@link #CONNECTION_METRIC_UNKNOWN} if the value is unavailable. This must
805      * be called after {@link Builder#enableNetworkQualityEstimator}, and will throw an exception
806      * otherwise.
807      *
808      * @return Estimate of the transport RTT in milliseconds.
809      *
810      * {@hide}
811      */
getTransportRttMs()812     public int getTransportRttMs() {
813         return CONNECTION_METRIC_UNKNOWN;
814     }
815 
816     /**
817      * Returns the downstream throughput estimate (in kilobits per second) computed by the network
818      * quality estimator. Set to {@link #CONNECTION_METRIC_UNKNOWN} if the value is unavailable.
819      * This must be called after {@link Builder#enableNetworkQualityEstimator}, and will throw an
820      * exception otherwise.
821      *
822      * @return Estimate of the downstream throughput in kilobits per second.
823      *
824      * {@hide}
825      */
getDownstreamThroughputKbps()826     public int getDownstreamThroughputKbps() {
827         return CONNECTION_METRIC_UNKNOWN;
828     }
829 
830     /**
831      * Starts NetLog logging to a specified directory with a bounded size. The NetLog will contain
832      * events emitted by all live CronetEngines. The NetLog is useful for debugging. Once logging
833      * has stopped {@link #stopNetLog}, the data will be written to netlog.json in {@code dirPath}.
834      * If logging is interrupted, you can stitch the files found in .inprogress subdirectory
835      * manually using:
836      * https://chromium.googlesource.com/chromium/src/+/main/net/tools/stitch_net_log_files.py. The
837      * log can be viewed using a Chrome browser navigated to chrome://net-internals/#import.
838      *
839      * @param dirPath the directory where the netlog.json file will be created. dirPath must already
840      * exist. NetLog files must not exist in the directory. If actively logging, this method is
841      * ignored.
842      * @param logAll {@code true} to include basic events, user cookies, credentials and all
843      * transferred bytes in the log. This option presents a privacy risk, since it exposes the
844      * user's credentials, and should only be used with the user's consent and in situations where
845      * the log won't be public. {@code false} to just include basic events.
846      * @param maxSize the maximum total disk space in bytes that should be used by NetLog. Actual
847      *         disk
848      * space usage may exceed this limit slightly.
849      *
850      * {@hide}
851      */
startNetLogToDisk(String dirPath, boolean logAll, int maxSize)852     public void startNetLogToDisk(String dirPath, boolean logAll, int maxSize) {}
853 
854     /**
855      * Returns an estimate of the effective connection type computed by the network quality
856      * estimator. Call {@link Builder#enableNetworkQualityEstimator} to begin computing this value.
857      *
858      * @return the estimated connection type. The returned value is one of {@link
859      * #EFFECTIVE_CONNECTION_TYPE_UNKNOWN EFFECTIVE_CONNECTION_TYPE_* }.
860      *
861      * {@hide}
862      */
getEffectiveConnectionType()863     public int getEffectiveConnectionType() {
864         return EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
865     }
866 
867     /**
868      * Configures the network quality estimator for testing. This must be called before round trip
869      * time and throughput listeners are added, and after the network quality estimator has been
870      * enabled.
871      *
872      * @param useLocalHostRequests include requests to localhost in estimates.
873      * @param useSmallerResponses include small responses in throughput estimates.
874      * @param disableOfflineCheck when set to true, disables the device offline checks when
875      *         computing
876      * the effective connection type or when writing the prefs.
877      *
878      * {@hide}
879      */
880     @VisibleForTesting
configureNetworkQualityEstimatorForTesting(boolean useLocalHostRequests, boolean useSmallerResponses, boolean disableOfflineCheck)881     public void configureNetworkQualityEstimatorForTesting(boolean useLocalHostRequests,
882             boolean useSmallerResponses, boolean disableOfflineCheck) {}
883 
884     /**
885      * Registers a listener that gets called whenever the network quality estimator witnesses a
886      * sample round trip time. This must be called after {@link
887      * Builder#enableNetworkQualityEstimator}, and with throw an exception otherwise. Round trip
888      * times may be recorded at various layers of the network stack, including TCP, QUIC, and at the
889      * URL request layer. The listener is called on the
890      * {@link java.util.concurrent.Executor} that is passed to {@link
891      * Builder#enableNetworkQualityEstimator}.
892      *
893      * @param listener the listener of round trip times.
894      *
895      * {@hide}
896      */
addRttListener(NetworkQualityRttListener listener)897     public void addRttListener(NetworkQualityRttListener listener) {}
898 
899     /**
900      * Removes a listener of round trip times if previously registered with {@link #addRttListener}.
901      * This should be called after a {@link NetworkQualityRttListener} is added in order to stop
902      * receiving observations.
903      *
904      * @param listener the listener of round trip times.
905      *
906      * {@hide}
907      */
removeRttListener(NetworkQualityRttListener listener)908     public void removeRttListener(NetworkQualityRttListener listener) {}
909 
910     /**
911      * Registers a listener that gets called whenever the network quality estimator witnesses a
912      * sample throughput measurement. This must be called after {@link
913      * Builder#enableNetworkQualityEstimator}. Throughput observations are computed by measuring
914      * bytes read over the active network interface at times when at least one URL response is being
915      * received. The listener is called on the {@link java.util.concurrent.Executor} that is passed
916      * to {@link Builder#enableNetworkQualityEstimator}.
917      *
918      * @param listener the listener of throughput.
919      *
920      * {@hide}
921      */
addThroughputListener(NetworkQualityThroughputListener listener)922     public void addThroughputListener(NetworkQualityThroughputListener listener) {}
923 
924     /**
925      * Removes a listener of throughput. This should be called after a {@link
926      * NetworkQualityThroughputListener} is added with {@link #addThroughputListener} in order to
927      * stop receiving observations.
928      *
929      * @param listener the listener of throughput.
930      *
931      * {@hide}
932      */
removeThroughputListener(NetworkQualityThroughputListener listener)933     public void removeThroughputListener(NetworkQualityThroughputListener listener) {}
934 }
935