• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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.time.Duration;
16 
17 /**
18  * A class configuring the HTTP connection migration functionality.
19  *
20  * <p>Connection migration stops open connections to servers from being destroyed when the
21  * client device switches its L4 connectivity (typically the IP address as a result of using
22  * a different network). This is particularly common with mobile devices losing
23  * wifi connectivity and switching to cellular data, or vice versa (a.k.a. the parking lot
24  * problem). QUIC uses connection identifiers which are independent of the underlying
25  * transport layer to make this possible. If the client connects to a new network and wants
26  * to preserve the existing connection, they can do so by using a connection identifier the server
27  * knows to be a continuation of the existing connection.
28  *
29  * <p>The features are only available for QUIC connections and the server needs to support
30  * connection migration.
31  *
32  * @see <a href="https://www.rfc-editor.org/rfc/rfc9000.html#section-9">Connection
33  *     Migration specification</a>
34  */
35 // SuppressLint to be consistent with other cronet code
36 @SuppressLint("UserHandleName")
37 public class ConnectionMigrationOptions {
38     private final @MigrationOptionState int mEnableDefaultNetworkMigration;
39     private final @MigrationOptionState int mEnablePathDegradationMigration;
40     @Nullable
41     private final Boolean mAllowServerMigration;
42     @Nullable
43     private final Boolean mMigrateIdleConnections;
44     @Nullable
45     private final Duration mIdleMigrationPeriod;
46     private final @MigrationOptionState int mAllowNonDefaultNetworkUsage;
47     @Nullable
48     private final Duration mMaxTimeOnNonDefaultNetwork;
49     @Nullable
50     private final Integer mMaxWriteErrorNonDefaultNetworkMigrationsCount;
51     @Nullable
52     private final Integer mMaxPathDegradingNonDefaultMigrationsCount;
53 
54     /**
55      * Option is unspecified, platform default value will be used.
56      */
57     public static final int MIGRATION_OPTION_UNSPECIFIED = 0;
58 
59     /**
60      * Option is enabled.
61      */
62     public static final int MIGRATION_OPTION_ENABLED = 1;
63 
64     /**
65      * Option is disabled.
66      */
67     public static final int MIGRATION_OPTION_DISABLED = 2;
68 
69     /** @hide */
70     @Retention(RetentionPolicy.SOURCE)
71     @IntDef(flag = false, prefix = "MIGRATION_OPTION_", value = {
72             MIGRATION_OPTION_UNSPECIFIED,
73             MIGRATION_OPTION_ENABLED,
74             MIGRATION_OPTION_DISABLED,
75     })
76     public @interface MigrationOptionState {}
77 
78     /**
79      * See {@link Builder#setDefaultNetworkMigration(int)}
80      */
getDefaultNetworkMigration()81     public @MigrationOptionState int getDefaultNetworkMigration() {
82         return mEnableDefaultNetworkMigration;
83     }
84 
85     /**
86      * See {@link Builder#setPathDegradationMigration(int)}
87      */
getPathDegradationMigration()88     public @MigrationOptionState int getPathDegradationMigration() {
89         return mEnablePathDegradationMigration;
90     }
91 
92     /**
93      * See {@link Builder#setAllowNonDefaultNetworkUsage(int)}
94      */
getAllowNonDefaultNetworkUsage()95     public @MigrationOptionState int getAllowNonDefaultNetworkUsage() {
96         return mAllowNonDefaultNetworkUsage;
97     }
98 
ConnectionMigrationOptions(@onNull Builder builder)99     ConnectionMigrationOptions(@NonNull Builder builder) {
100         this.mEnableDefaultNetworkMigration = builder.mEnableDefaultNetworkMigration;
101         this.mEnablePathDegradationMigration = builder.mEnablePathDegradationMigration;
102         this.mAllowServerMigration = builder.mAllowServerMigration;
103         this.mMigrateIdleConnections = builder.mMigrateIdleConnections;
104         this.mIdleMigrationPeriod = builder.mIdleConnectionMigrationPeriod;
105         this.mAllowNonDefaultNetworkUsage = builder.mAllowNonDefaultNetworkUsage;
106         this.mMaxTimeOnNonDefaultNetwork = builder.mMaxTimeOnNonDefaultNetwork;
107         this.mMaxWriteErrorNonDefaultNetworkMigrationsCount = builder.mMaxWriteErrorNonDefaultNetworkMigrationsCount;
108         this.mMaxPathDegradingNonDefaultMigrationsCount = builder.mMaxPathDegradingNonDefaultMigrationsCount;
109     }
110 
111     /**
112      * Builder for {@link ConnectionMigrationOptions}.
113      */
114     public static final class Builder {
115         private @MigrationOptionState int mEnableDefaultNetworkMigration;
116         private @MigrationOptionState int mEnablePathDegradationMigration;
117         @Nullable
118         private Boolean mAllowServerMigration;
119         @Nullable
120         private Boolean mMigrateIdleConnections;
121         @Nullable
122         private Duration mIdleConnectionMigrationPeriod;
123         private @MigrationOptionState int mAllowNonDefaultNetworkUsage;
124         @Nullable
125         private Duration mMaxTimeOnNonDefaultNetwork;
126         @Nullable
127         private Integer mMaxWriteErrorNonDefaultNetworkMigrationsCount;
128         @Nullable
129         private Integer mMaxPathDegradingNonDefaultMigrationsCount;
130 
Builder()131         public Builder() {}
132 
133         /**
134          * Sets whether to enable the possibility of migrating connections on default network
135          * change. If enabled, active QUIC connections will be migrated onto the new network when
136          * the platform indicates that the default network is changing.
137          *
138          * @see <a href="https://developer.android.com/training/basics/network-ops/reading-network-state#listening-events">Android
139          *     Network State</a>
140          *
141          * @param state one of the MIGRATION_OPTION_* values
142          * @return this builder for chaining
143          */
144         @NonNull
setDefaultNetworkMigration(@igrationOptionState int state)145         public Builder setDefaultNetworkMigration(@MigrationOptionState int state) {
146             this.mEnableDefaultNetworkMigration = state;
147             return this;
148         }
149 
150         /**
151          * Sets whether to enable the possibility of migrating connections if the current path is
152          * performing poorly.
153          *
154          * <p>Depending on other configuration, this can result to migrating the connections within
155          * the same default network, or to a non-default network.
156          *
157          * @param state one of the MIGRATION_OPTION_* values
158          * @return this builder for chaining
159          */
160         @NonNull
setPathDegradationMigration(@igrationOptionState int state)161         public Builder setPathDegradationMigration(@MigrationOptionState int state) {
162             this.mEnablePathDegradationMigration = state;
163             return this;
164         }
165 
166         /**
167          * Sets whether connections can be migrated to an alternate network when Cronet detects
168          * a degradation of the path currently in use. Requires setting
169          * {@link #setPathDegradationMigration(int)} to {@link #MIGRATION_OPTION_ENABLED} to
170          * have any effect.
171          *
172          * <p>Note: This setting can result in requests being sent on non-default metered networks,
173          * eating into the users' data budgets and incurring extra costs. Make sure you're using
174          * metered networks sparingly.
175          *
176          * @param state one of the MIGRATION_OPTION_* values
177          * @return this builder for chaining
178          */
179         @Experimental
180         @NonNull
setAllowNonDefaultNetworkUsage(@igrationOptionState int state)181         public Builder setAllowNonDefaultNetworkUsage(@MigrationOptionState int state) {
182             this.mAllowNonDefaultNetworkUsage = state;
183             return this;
184         }
185 
186         /**
187          * Creates and returns the final {@link ConnectionMigrationOptions} instance, based on the
188          * values in this builder.
189          */
190         @NonNull
build()191         public ConnectionMigrationOptions build() {
192             return new ConnectionMigrationOptions(this);
193         }
194     }
195 
196     /**
197      * Creates a new builder for {@link ConnectionMigrationOptions}.
198      *
199      * {@hide}
200      */
201     @NonNull
builder()202     public static Builder builder() {
203         return new Builder();
204     }
205 
206     /**
207      * An annotation for APIs which are not considered stable yet.
208      *
209      * <p>Applications using experimental APIs must acknowledge that they're aware of using APIs
210      * that are not considered stable. The APIs might change functionality, break or cease to exist
211      * without notice.
212      *
213      * <p>It's highly recommended to reach out to Cronet maintainers ({@code net-dev@chromium.org})
214      * before using one of the APIs annotated as experimental outside of debugging
215      * and proof-of-concept code. Be ready to help to help polishing the API, or for a "sorry,
216      * really not production ready yet".
217      *
218      * <p>If you still want to use an experimental API in production, you're doing so at your
219      * own risk. You have been warned.
220      *
221      * {@hide}
222      */
223     public @interface Experimental {}
224 }
225