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