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.IntDef; 8 import android.annotation.SuppressLint; 9 10 import androidx.annotation.NonNull; 11 import androidx.annotation.Nullable; 12 13 import java.lang.annotation.Retention; 14 import java.lang.annotation.RetentionPolicy; 15 import java.nio.ByteBuffer; 16 import java.util.List; 17 import java.util.Map; 18 import java.util.concurrent.Executor; 19 20 /** 21 * Class for bidirectional sending and receiving of data over HTTP/2 or QUIC connections. Created by 22 * {@link Builder}. 23 * 24 * Note: There are ordering restrictions on methods of {@link BidirectionalStream}; 25 * please see individual methods for description of restrictions. 26 */ 27 public abstract class BidirectionalStream { 28 /** 29 * Lowest stream priority. Passed to {@link Builder#setPriority}. 30 */ 31 public static final int STREAM_PRIORITY_IDLE = 0; 32 /** 33 * Very low stream priority. Passed to {@link Builder#setPriority}. 34 */ 35 public static final int STREAM_PRIORITY_LOWEST = 1; 36 /** 37 * Low stream priority. Passed to {@link Builder#setPriority}. 38 */ 39 public static final int STREAM_PRIORITY_LOW = 2; 40 /** 41 * Medium stream priority. Passed to {@link Builder#setPriority}. This is the 42 * default priority given to the stream. 43 */ 44 public static final int STREAM_PRIORITY_MEDIUM = 3; 45 /** 46 * Highest stream priority. Passed to {@link Builder#setPriority}. 47 */ 48 public static final int STREAM_PRIORITY_HIGHEST = 4; 49 50 /** @hide */ 51 @Retention(RetentionPolicy.SOURCE) 52 @IntDef({ 53 BidirectionalStream.STREAM_PRIORITY_IDLE, 54 BidirectionalStream.STREAM_PRIORITY_LOWEST, 55 BidirectionalStream.STREAM_PRIORITY_LOW, 56 BidirectionalStream.STREAM_PRIORITY_MEDIUM, 57 BidirectionalStream.STREAM_PRIORITY_HIGHEST}) 58 public @interface BidirectionalStreamPriority {} 59 60 61 /** 62 * Builder for {@link BidirectionalStream}s. Allows configuring stream before constructing 63 * it via {@link Builder#build}. 64 */ 65 // SuppressLint: Builder can not be final since this is abstract and inherited 66 @SuppressLint("StaticFinalBuilder") 67 public abstract static class Builder { 68 /** 69 * Sets the HTTP method for the request. Returns builder to facilitate chaining. 70 * 71 * @param method the method to use for request. Default is 'POST' 72 * @return the builder to facilitate chaining 73 */ 74 @NonNull setHttpMethod(@onNull String method)75 public abstract Builder setHttpMethod(@NonNull String method); 76 77 /** 78 * Adds a request header. Returns builder to facilitate chaining. 79 * 80 * @param header the header name 81 * @param value the header value 82 * @return the builder to facilitate chaining 83 */ 84 @NonNull addHeader(@onNull String header, @NonNull String value)85 public abstract Builder addHeader(@NonNull String header, @NonNull String value); 86 87 /** 88 * Sets priority of the stream which should be one of the {@link #STREAM_PRIORITY_IDLE 89 * STREAM_PRIORITY_*} values. The stream is given {@link #STREAM_PRIORITY_MEDIUM} priority 90 * if this method is not called. 91 * 92 * @param priority priority of the stream which should be one of the {@link 93 * #STREAM_PRIORITY_IDLE STREAM_PRIORITY_*} values. 94 * @return the builder to facilitate chaining. 95 */ 96 @NonNull setPriority(@idirectionalStreamPriority int priority)97 public abstract Builder setPriority(@BidirectionalStreamPriority int priority); 98 99 /** 100 * Sets whether to delay sending request headers until {@link BidirectionalStream#flush()} 101 * is called. This flag is currently only respected when QUIC is negotiated. 102 * When true, QUIC will send request header frame along with data frame(s) 103 * as a single packet when possible. 104 * 105 * @param delayRequestHeadersUntilFirstFlush if true, sending request headers will be 106 * delayed 107 * until flush() is called. 108 * @return the builder to facilitate chaining. 109 */ 110 @NonNull setDelayRequestHeadersUntilFirstFlushEnabled( boolean delayRequestHeadersUntilFirstFlush)111 public abstract Builder setDelayRequestHeadersUntilFirstFlushEnabled( 112 boolean delayRequestHeadersUntilFirstFlush); 113 114 /** 115 * Sets {@link android.net.TrafficStats} tag to use when accounting socket traffic caused by 116 * this request. See {@link android.net.TrafficStats} for more information. If no tag is 117 * set (e.g. this method isn't called), then Android accounts for the socket traffic caused 118 * by this request as if the tag value were set to 0. 119 * <p> 120 * <b>NOTE:</b>Setting a tag disallows sharing of sockets with requests 121 * with other tags, which may adversely effect performance by prohibiting 122 * connection sharing. In other words use of multiplexed sockets (e.g. HTTP/2 123 * and QUIC) will only be allowed if all requests have the same socket tag. 124 * 125 * @param tag the tag value used to when accounting for socket traffic caused by this 126 * request. Tags between 0xFFFFFF00 and 0xFFFFFFFF are reserved and used 127 * internally by system services like {@link android.app.DownloadManager} when 128 * performing traffic on behalf of an application. 129 * @return the builder to facilitate chaining. 130 */ 131 @NonNull setTrafficStatsTag(int tag)132 public abstract Builder setTrafficStatsTag(int tag); 133 134 /** 135 * Sets specific UID to use when accounting socket traffic caused by this request. See 136 * {@link android.net.TrafficStats} for more information. Designed for use when performing 137 * an operation on behalf of another application. Caller must hold 138 * {@code android.Manifest.permission#MODIFY_NETWORK_ACCOUNTING} permission. By default 139 * traffic is attributed to UID of caller. 140 * <p> 141 * <b>NOTE:</b>Setting a UID disallows sharing of sockets with requests 142 * with other UIDs, which may adversely effect performance by prohibiting 143 * connection sharing. In other words use of multiplexed sockets (e.g. HTTP/2 144 * and QUIC) will only be allowed if all requests have the same UID set. 145 * 146 * @param uid the UID to attribute socket traffic caused by this request. 147 * @return the builder to facilitate chaining. 148 */ 149 @NonNull setTrafficStatsUid(int uid)150 public abstract Builder setTrafficStatsUid(int uid); 151 152 153 /** 154 * Creates a {@link BidirectionalStream} using configuration from this {@link Builder}. The 155 * returned {@code BidirectionalStream} can then be started by calling {@link 156 * BidirectionalStream#start}. 157 * 158 * @return constructed {@link BidirectionalStream} using configuration from this {@link 159 * Builder} 160 */ 161 @NonNull build()162 public abstract BidirectionalStream build(); 163 } 164 165 /** 166 * Callback interface used to receive callbacks from a {@link BidirectionalStream}. 167 */ 168 public interface Callback { 169 /** 170 * Invoked when the stream is ready for reading and writing. Consumer may call {@link 171 * BidirectionalStream#read read()} to start reading data. Consumer may call {@link 172 * BidirectionalStream#write write()} to start writing data. 173 * 174 * @param stream the stream that is ready. <strong>This is not guaranteed to be the same 175 * object as the one received by other callbacks, nor is it guaranteed to be the one 176 * returned by {@link BidirectionalStream.Builder#build}.</strong> However, method 177 * calls on this object will have the same effects as calls on the original 178 * {@link BidirectionalStream}. 179 */ onStreamReady(@onNull BidirectionalStream stream)180 void onStreamReady(@NonNull BidirectionalStream stream); 181 182 /** 183 * Invoked when initial response headers are received. Headers are available from {@code 184 * info.}{@link UrlResponseInfo#getHeaders getHeaders()}. Consumer may call {@link 185 * BidirectionalStream#read read()} to start reading. Consumer may call {@link 186 * BidirectionalStream#write write()} to start writing or close the stream. 187 * 188 * @param stream the stream on which response headers were received. <strong>This is not 189 * guaranteed to be the same object as the one received by other callbacks, nor is 190 * it guaranteed to be the one returned by {@link BidirectionalStream.Builder#build}. 191 * </strong> However, method calls on this object will have the same effects as 192 * calls on the original {@link BidirectionalStream}. 193 * @param info the response information. 194 */ onResponseHeadersReceived(@onNull BidirectionalStream stream, @NonNull UrlResponseInfo info)195 void onResponseHeadersReceived(@NonNull BidirectionalStream stream, 196 @NonNull UrlResponseInfo info); 197 198 /** 199 * Invoked when data is read into the buffer passed to {@link BidirectionalStream#read 200 * read()}. Only part of the buffer may be populated. To continue reading, call {@link 201 * BidirectionalStream#read read()}. It may be invoked after {@code 202 * onResponseTrailersReceived()}, if there was pending read data before trailers were 203 * received. 204 * 205 * @param stream the stream on which the read completed. <strong>This is not guaranteed to 206 * be the same object as the one received by other callbacks, nor is it guaranteed 207 * to be the one returned by {@link BidirectionalStream.Builder#build}.</strong> 208 * However, method calls on this object will have the same effects as calls on the 209 * original {@link BidirectionalStream}. 210 * @param info the response information 211 * @param buffer the buffer that was passed to {@link BidirectionalStream#read read()}, now 212 * set to the end of the received data. If position is not updated, it means the remote side 213 * has signaled that it will send no more data. 214 * @param endOfStream if true, this is the last read data, remote will not send more data, 215 * and 216 * the read side is closed. 217 */ onReadCompleted(@onNull BidirectionalStream stream, @NonNull UrlResponseInfo info, @NonNull ByteBuffer buffer, boolean endOfStream)218 void onReadCompleted(@NonNull BidirectionalStream stream, @NonNull UrlResponseInfo info, 219 @NonNull ByteBuffer buffer, boolean endOfStream); 220 221 /** 222 * Invoked when the entire ByteBuffer passed to {@link BidirectionalStream#write write()} is 223 * sent. The buffer's position is updated to be the same as the buffer's limit. The buffer's 224 * limit is not changed. To continue writing, call {@link BidirectionalStream#write 225 * write()}. 226 * 227 * @param stream the stream on which the write completed. <strong>This is not guaranteed to 228 * be the same object as the one received by other callbacks, nor is it guaranteed 229 * to be the one returned by {@link BidirectionalStream.Builder#build}.</strong> 230 * However, method calls on this object will have the same effects as calls on the 231 * original {@link BidirectionalStream}. 232 * @param info the response information 233 * @param buffer the buffer that was passed to {@link BidirectionalStream#write write()}. 234 * The 235 * buffer's position is set to the buffer's limit. The buffer's limit is not changed. 236 * @param endOfStream the endOfStream flag that was passed to the corresponding {@link 237 * BidirectionalStream#write write()}. If true, the write side is closed. 238 */ onWriteCompleted(@onNull BidirectionalStream stream, @NonNull UrlResponseInfo info, @NonNull ByteBuffer buffer, boolean endOfStream)239 void onWriteCompleted(@NonNull BidirectionalStream stream, @NonNull UrlResponseInfo info, 240 @NonNull ByteBuffer buffer, boolean endOfStream); 241 242 /** 243 * Invoked when trailers are received before closing the stream. Only invoked when server 244 * sends trailers, which it may not. May be invoked while there is read data remaining in 245 * local buffer. 246 * 247 * Default implementation takes no action. 248 * 249 * @param stream the stream on which response trailers were received. <strong>This is not 250 * guaranteed to be the same object as the one received by other callbacks, nor is 251 * it guaranteed to be the one returned by {@link BidirectionalStream.Builder#build}. 252 * </strong> However, method calls on this object will have the same effects as calls 253 * on the original {@link BidirectionalStream}. 254 * @param info the response information 255 * @param trailers the trailers received 256 */ onResponseTrailersReceived(@onNull BidirectionalStream stream, @NonNull UrlResponseInfo info, @NonNull HeaderBlock trailers)257 void onResponseTrailersReceived(@NonNull BidirectionalStream stream, 258 @NonNull UrlResponseInfo info, @NonNull HeaderBlock trailers); 259 260 /** 261 * Invoked when there is no data to be read or written and the stream is closed successfully 262 * remotely and locally. Once invoked, no further {@link BidirectionalStream.Callback} 263 * methods will be invoked. 264 * 265 * @param stream the stream which is closed successfully. <strong>This is not guaranteed to 266 * be the same object as the one received by other callbacks, nor is it guaranteed 267 * to be the one returned by {@link BidirectionalStream.Builder#build}.</strong> 268 * However, method calls on this object will have the same effects as calls on the 269 * original {@link BidirectionalStream}. 270 * @param info the response information 271 */ onSucceeded(@onNull BidirectionalStream stream, @NonNull UrlResponseInfo info)272 void onSucceeded(@NonNull BidirectionalStream stream, @NonNull UrlResponseInfo info); 273 274 /** 275 * Invoked if the stream failed for any reason after {@link BidirectionalStream#start}. 276 * <a href="https://tools.ietf.org/html/rfc7540#section-7">HTTP/2 error codes</a> are 277 * mapped to {@link NetworkException#getErrorCode} codes. Once invoked, 278 * no further {@link BidirectionalStream.Callback} methods will be invoked. 279 * 280 * @param stream the stream which has failed. <strong>This is not guaranteed to 281 * be the same object as the one received by other callbacks, nor is it guaranteed 282 * to be the one returned by {@link BidirectionalStream.Builder#build}.</strong> 283 * However, method calls on this object will have the same effects as calls on the 284 * original {@link BidirectionalStream}. 285 * @param info the response information. May be {@code null} if no response was received. 286 * @param error information about the failure 287 */ onFailed(@onNull BidirectionalStream stream, @Nullable UrlResponseInfo info, @NonNull HttpException error)288 void onFailed(@NonNull BidirectionalStream stream, @Nullable UrlResponseInfo info, 289 @NonNull HttpException error); 290 291 /** 292 * Invoked if the stream was canceled via {@link BidirectionalStream#cancel}. Once invoked, 293 * no further {@link BidirectionalStream.Callback} methods will be invoked. Default 294 * implementation takes no action. 295 * 296 * @param stream the stream that was canceled. <strong>This is not guaranteed to 297 * be the same object as the one received by other callbacks, nor is it guaranteed 298 * to be the one returned by {@link BidirectionalStream.Builder#build}.</strong> 299 * However, method calls on this object will have the same effects as calls on the 300 * original {@link BidirectionalStream}. 301 * @param info the response information. May be {@code null} if no response was received. 302 */ onCanceled(@onNull BidirectionalStream stream, @Nullable UrlResponseInfo info)303 void onCanceled(@NonNull BidirectionalStream stream, @Nullable UrlResponseInfo info); 304 } 305 306 /** 307 * See {@link BidirectionalStream.Builder#setHttpMethod(String)}. 308 */ 309 @NonNull getHttpMethod()310 public abstract String getHttpMethod(); 311 312 /** 313 * See {@link BidirectionalStream.Builder#setTrafficStatsTag(int)} 314 */ hasTrafficStatsTag()315 public abstract boolean hasTrafficStatsTag(); 316 317 /** 318 * See {@link BidirectionalStream.Builder#setTrafficStatsTag(int)} 319 */ getTrafficStatsTag()320 public abstract int getTrafficStatsTag(); 321 322 /** 323 * See {@link BidirectionalStream.Builder#setTrafficStatsUid(int)} 324 */ hasTrafficStatsUid()325 public abstract boolean hasTrafficStatsUid(); 326 327 /** 328 * See {@link BidirectionalStream.Builder#setTrafficStatsUid(int)} 329 */ getTrafficStatsUid()330 public abstract int getTrafficStatsUid(); 331 332 /** 333 * See {@link Builder#addHeader(String, String)} 334 */ 335 @NonNull getHeaders()336 public abstract HeaderBlock getHeaders(); 337 338 /** 339 * See {@link Builder#setPriority(int)} 340 */ getPriority()341 public abstract @BidirectionalStreamPriority int getPriority(); 342 343 /** 344 * See {@link Builder#setDelayRequestHeadersUntilFirstFlushEnabled(boolean)} 345 */ isDelayRequestHeadersUntilFirstFlushEnabled()346 public abstract boolean isDelayRequestHeadersUntilFirstFlushEnabled(); 347 348 /** 349 * Starts the stream, all callbacks go to the {@code callback} argument passed to {@link 350 * BidirectionalStream.Builder}'s constructor. Should only be called once. 351 */ start()352 public abstract void start(); 353 354 /** 355 * Reads data from the stream into the provided buffer. Can only be called at most once in 356 * response to each invocation of the {@link Callback#onStreamReady onStreamReady()}/ {@link 357 * Callback#onResponseHeadersReceived onResponseHeadersReceived()} and {@link 358 * Callback#onReadCompleted onReadCompleted()} methods of the {@link Callback}. Each call will 359 * result in an invocation of one of the {@link Callback Callback}'s {@link 360 * Callback#onReadCompleted onReadCompleted()} method if data is read, or its {@link 361 * Callback#onFailed onFailed()} method if there's an error. 362 * 363 * An attempt to read data into {@code buffer} starting at {@code buffer.position()} is begun. 364 * At most {@code buffer.remaining()} bytes are read. {@code buffer.position()} is updated upon 365 * invocation of {@link Callback#onReadCompleted onReadCompleted()} to indicate how much data 366 * was read. 367 * 368 * @param buffer the {@link ByteBuffer} to read data into. Must be a direct ByteBuffer. The 369 * embedder must not read or modify buffer's position, limit, or data between its position and 370 * limit until {@link Callback#onReadCompleted onReadCompleted()}, {@link Callback#onCanceled 371 * onCanceled()}, or {@link Callback#onFailed onFailed()} are invoked. 372 */ read(@onNull ByteBuffer buffer)373 public abstract void read(@NonNull ByteBuffer buffer); 374 375 /** 376 * Attempts to write data from the provided buffer into the stream. If auto flush is disabled, 377 * data will be sent only after {@link #flush flush()} is called. Each call will result in an 378 * invocation of one of the {@link Callback Callback}'s {@link Callback#onWriteCompleted 379 * onWriteCompleted()} method if data is sent, or its {@link Callback#onFailed onFailed()} 380 * method if there's an error. 381 * 382 * An attempt to write data from {@code buffer} starting at {@code buffer.position()} is begun. 383 * {@code buffer.remaining()} bytes will be written. {@link Callback#onWriteCompleted 384 * onWriteCompleted()} will be invoked only when the full ByteBuffer is written. 385 * 386 * @param buffer the {@link ByteBuffer} to write data from. Must be a direct ByteBuffer. The 387 * embedder must not read or modify buffer's position, limit, or data between its position and 388 * limit until {@link Callback#onWriteCompleted onWriteCompleted()}, {@link Callback#onCanceled 389 * onCanceled()}, or {@link Callback#onFailed onFailed()} are invoked. Can be empty when {@code 390 * endOfStream} is {@code true}. 391 * @param endOfStream if {@code true}, then {@code buffer} is the last buffer to be written, and 392 * once written, stream is closed from the client side, resulting in half-closed stream or a 393 * fully closed stream if the remote side has already closed. 394 */ write(@onNull ByteBuffer buffer, boolean endOfStream)395 public abstract void write(@NonNull ByteBuffer buffer, boolean endOfStream); 396 397 /** 398 * Flushes pending writes. This method should not be invoked before {@link 399 * Callback#onStreamReady onStreamReady()}. For previously delayed {@link #write write()}s, a 400 * corresponding {@link Callback#onWriteCompleted onWriteCompleted()} will be invoked when the 401 * buffer is sent. 402 */ flush()403 public abstract void flush(); 404 405 /** 406 * Cancels the stream. Can be called at any time after {@link #start}. {@link 407 * Callback#onCanceled onCanceled()} will be invoked when cancelation is complete and no further 408 * callback methods will be invoked. If the stream has completed or has not started, calling 409 * {@code cancel()} has no effect and {@code onCanceled()} will not be invoked. If the {@link 410 * Executor} passed in during 411 * {@code BidirectionalStream} construction runs tasks on a single thread, and {@code cancel()} 412 * is called on that thread, no listener methods (besides {@code onCanceled()}) will be invoked 413 * after 414 * {@code cancel()} is called. Otherwise, at most one callback method may be invoked after 415 * {@code cancel()} has completed. 416 */ cancel()417 public abstract void cancel(); 418 419 /** 420 * Returns {@code true} if the stream was successfully started and is now done (succeeded, 421 * canceled, or failed). 422 * 423 * @return {@code true} if the stream was successfully started and is now done (completed, 424 * canceled, or failed), otherwise returns {@code false} to indicate stream is not yet started 425 * or is in progress. 426 */ isDone()427 public abstract boolean isDone(); 428 } 429