• 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.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