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