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