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