1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.telephony.data; 18 19 import android.annotation.ElapsedRealtimeLong; 20 import android.annotation.IntDef; 21 import android.annotation.NonNull; 22 import android.annotation.SuppressLint; 23 import android.annotation.SystemApi; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.os.SystemClock; 27 import android.telephony.AccessNetworkConstants; 28 import android.telephony.Annotation; 29 30 import java.util.Objects; 31 32 /** 33 * Status information regarding the throttle status of an APN type. 34 * 35 * @hide 36 */ 37 @SystemApi 38 public final class ThrottleStatus implements Parcelable { 39 /** 40 * The APN type is not throttled. 41 */ 42 public static final int THROTTLE_TYPE_NONE = 1; 43 44 /** 45 * The APN type is throttled until {@link android.os.SystemClock#elapsedRealtime()} 46 * has reached {@link ThrottleStatus#getThrottleExpiryTimeMillis} 47 */ 48 public static final int THROTTLE_TYPE_ELAPSED_TIME = 2; 49 50 /** {@hide} */ 51 @IntDef(flag = true, prefix = {"THROTTLE_TYPE_"}, value = { 52 ThrottleStatus.THROTTLE_TYPE_NONE, 53 ThrottleStatus.THROTTLE_TYPE_ELAPSED_TIME, 54 }) 55 public @interface ThrottleType { 56 } 57 58 /** 59 * The framework will not retry the APN type. 60 */ 61 public static final int RETRY_TYPE_NONE = 1; 62 63 /** 64 * The next time the framework retries, it will attempt to establish a new connection. 65 */ 66 public static final int RETRY_TYPE_NEW_CONNECTION = 2; 67 68 /** 69 * The next time the framework retires, it will retry to handover. 70 */ 71 public static final int RETRY_TYPE_HANDOVER = 3; 72 73 /** {@hide} */ 74 @IntDef(flag = true, prefix = {"RETRY_TYPE_"}, value = { 75 ThrottleStatus.RETRY_TYPE_NONE, 76 ThrottleStatus.RETRY_TYPE_NEW_CONNECTION, 77 ThrottleStatus.RETRY_TYPE_HANDOVER, 78 }) 79 public @interface RetryType { 80 } 81 82 private final int mSlotIndex; 83 private final @AccessNetworkConstants.TransportType int mTransportType; 84 private final @Annotation.ApnType int mApnType; 85 private final long mThrottleExpiryTimeMillis; 86 private final @RetryType int mRetryType; 87 private final @ThrottleType int mThrottleType; 88 89 /** 90 * The slot index that the status applies to. 91 * 92 * @return the slot index 93 */ getSlotIndex()94 public int getSlotIndex() { 95 return mSlotIndex; 96 } 97 98 /** 99 * The type of transport that the status applies to. 100 * 101 * @return the transport type 102 */ 103 @AccessNetworkConstants.TransportType getTransportType()104 public int getTransportType() { 105 return mTransportType; 106 } 107 108 /** 109 * The APN type that the status applies to. 110 * 111 * @return the apn type 112 */ 113 @Annotation.ApnType getApnType()114 public int getApnType() { 115 return mApnType; 116 } 117 118 /** 119 * The type of throttle applied to the APN type. 120 * 121 * @return the throttle type 122 */ 123 @ThrottleType getThrottleType()124 public int getThrottleType() { 125 return mThrottleType; 126 } 127 128 /** 129 * Indicates the type of request that the framework will make the next time it retries 130 * to call {@link IDataService#setupDataCall}. 131 * 132 * @return the retry type 133 */ 134 @RetryType getRetryType()135 public int getRetryType() { 136 return mRetryType; 137 } 138 139 /** 140 * Gets the time at which the throttle expires. The value is based off of 141 * {@link SystemClock#elapsedRealtime}. 142 * 143 * This value only applies when the throttle type is set to 144 * {@link ThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}. 145 * 146 * A value of {@link Long#MAX_VALUE} implies that the APN type is throttled indefinitely. 147 * 148 * @return the time at which the throttle expires 149 */ 150 @ElapsedRealtimeLong getThrottleExpiryTimeMillis()151 public long getThrottleExpiryTimeMillis() { 152 return mThrottleExpiryTimeMillis; 153 } 154 ThrottleStatus(int slotIndex, @AccessNetworkConstants.TransportType int transportType, @Annotation.ApnType int apnTypes, @ThrottleType int throttleType, long throttleExpiryTimeMillis, @RetryType int retryType)155 private ThrottleStatus(int slotIndex, 156 @AccessNetworkConstants.TransportType int transportType, 157 @Annotation.ApnType int apnTypes, 158 @ThrottleType int throttleType, 159 long throttleExpiryTimeMillis, 160 @RetryType int retryType) { 161 mSlotIndex = slotIndex; 162 mTransportType = transportType; 163 mApnType = apnTypes; 164 mThrottleType = throttleType; 165 mThrottleExpiryTimeMillis = throttleExpiryTimeMillis; 166 mRetryType = retryType; 167 } 168 ThrottleStatus(@onNull Parcel source)169 private ThrottleStatus(@NonNull Parcel source) { 170 mSlotIndex = source.readInt(); 171 mTransportType = source.readInt(); 172 mApnType = source.readInt(); 173 mThrottleExpiryTimeMillis = source.readLong(); 174 mRetryType = source.readInt(); 175 mThrottleType = source.readInt(); 176 } 177 178 @Override writeToParcel(@onNull Parcel dest, int flags)179 public void writeToParcel(@NonNull Parcel dest, int flags) { 180 dest.writeInt(mSlotIndex); 181 dest.writeInt(mTransportType); 182 dest.writeInt(mApnType); 183 dest.writeLong(mThrottleExpiryTimeMillis); 184 dest.writeInt(mRetryType); 185 dest.writeInt(mThrottleType); 186 } 187 188 public static final @NonNull Parcelable.Creator<ThrottleStatus> CREATOR = 189 new Parcelable.Creator<ThrottleStatus>() { 190 @Override 191 public ThrottleStatus createFromParcel(@NonNull Parcel source) { 192 return new ThrottleStatus(source); 193 } 194 195 @Override 196 public ThrottleStatus[] newArray(int size) { 197 return new ThrottleStatus[size]; 198 } 199 }; 200 201 @Override describeContents()202 public int describeContents() { 203 return 0; 204 } 205 206 @Override hashCode()207 public int hashCode() { 208 return Objects.hash(mSlotIndex, mApnType, mRetryType, mThrottleType, 209 mThrottleExpiryTimeMillis, mTransportType); 210 } 211 212 @Override equals(Object obj)213 public boolean equals(Object obj) { 214 if (obj == null) { 215 return false; 216 } else if (obj instanceof ThrottleStatus) { 217 ThrottleStatus other = (ThrottleStatus) obj; 218 return this.mSlotIndex == other.mSlotIndex 219 && this.mApnType == other.mApnType 220 && this.mRetryType == other.mRetryType 221 && this.mThrottleType == other.mThrottleType 222 && this.mThrottleExpiryTimeMillis == other.mThrottleExpiryTimeMillis 223 && this.mTransportType == other.mTransportType; 224 } else { 225 return false; 226 } 227 } 228 229 @Override toString()230 public String toString() { 231 return "ThrottleStatus{" 232 + "mSlotIndex=" + mSlotIndex 233 + ", mTransportType=" + mTransportType 234 + ", mApnType=" + ApnSetting.getApnTypeString(mApnType) 235 + ", mThrottleExpiryTimeMillis=" + mThrottleExpiryTimeMillis 236 + ", mRetryType=" + mRetryType 237 + ", mThrottleType=" + mThrottleType 238 + '}'; 239 } 240 241 /** 242 * Provides a convenient way to set the fields of an {@link ThrottleStatus} when creating a 243 * new instance. 244 * 245 * <p>The example below shows how you might create a new {@code ThrottleStatus}: 246 * 247 * <pre><code> 248 * 249 * ThrottleStatus = new ThrottleStatus.Builder() 250 * .setSlotIndex(1) 251 * .setApnType({@link ApnSetting#TYPE_EMERGENCY}) 252 * .setNoThrottle() 253 * .setRetryType({@link ThrottleStatus#RETRY_TYPE_NEW_CONNECTION}) 254 * .build(); 255 * </code></pre> 256 */ 257 public static final class Builder { 258 private int mSlotIndex; 259 private @AccessNetworkConstants.TransportType int mTransportType; 260 private @Annotation.ApnType int mApnType; 261 private long mThrottleExpiryTimeMillis; 262 private @RetryType int mRetryType; 263 private @ThrottleType int mThrottleType; 264 265 /** 266 * @hide 267 */ 268 public static final long NO_THROTTLE_EXPIRY_TIME = 269 DataCallResponse.RETRY_DURATION_UNDEFINED; 270 271 /** 272 * Default constructor for the Builder. 273 */ Builder()274 public Builder() { 275 } 276 277 /** 278 * Set the slot index. 279 * 280 * @param slotIndex the slot index. 281 * @return The same instance of the builder. 282 */ 283 @NonNull setSlotIndex(int slotIndex)284 public Builder setSlotIndex(int slotIndex) { 285 this.mSlotIndex = slotIndex; 286 return this; 287 } 288 289 /** 290 * Set the transport type. 291 * 292 * @param transportType the transport type. 293 * @return The same instance of the builder. 294 */ 295 @NonNull setTransportType(@ccessNetworkConstants.TransportType int transportType)296 public Builder setTransportType(@AccessNetworkConstants.TransportType 297 int transportType) { 298 this.mTransportType = transportType; 299 return this; 300 } 301 302 /** 303 * Set the APN type. 304 * 305 * @param apnType the APN type. 306 * @return The same instance of the builder. 307 */ 308 @NonNull setApnType(@nnotation.ApnType int apnType)309 public Builder setApnType(@Annotation.ApnType int apnType) { 310 this.mApnType = apnType; 311 return this; 312 } 313 314 /** 315 * Sets the time at which the throttle will expire. The value is based off of 316 * {@link SystemClock#elapsedRealtime}. 317 * 318 * When setting this value, the throttle type is set to 319 * {@link ThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}. 320 * 321 * A value of {@link Long#MAX_VALUE} implies that the APN type is throttled indefinitely. 322 * 323 * @param throttleExpiryTimeMillis The elapsed time at which the throttle expires. 324 * Throws {@link IllegalArgumentException} for values less 325 * than 0. 326 * @return The same instance of the builder. 327 */ 328 @NonNull setThrottleExpiryTimeMillis( @lapsedRealtimeLong long throttleExpiryTimeMillis)329 public Builder setThrottleExpiryTimeMillis( 330 @ElapsedRealtimeLong long throttleExpiryTimeMillis) { 331 if (throttleExpiryTimeMillis >= 0) { 332 this.mThrottleExpiryTimeMillis = throttleExpiryTimeMillis; 333 this.mThrottleType = THROTTLE_TYPE_ELAPSED_TIME; 334 } else { 335 throw new IllegalArgumentException("throttleExpiryTimeMillis must be greater than " 336 + "or equal to 0"); 337 } 338 return this; 339 } 340 341 /** 342 * Sets the status of the APN type as not being throttled. 343 * 344 * When setting this value, the throttle type is set to 345 * {@link ThrottleStatus#THROTTLE_TYPE_NONE} and the expiry time is set to 346 * {@link Builder#NO_THROTTLE_EXPIRY_TIME}. 347 * 348 * @return The same instance of the builder. 349 */ 350 @SuppressLint("MissingGetterMatchingBuilder") 351 @NonNull setNoThrottle()352 public Builder setNoThrottle() { 353 mThrottleType = THROTTLE_TYPE_NONE; 354 mThrottleExpiryTimeMillis = NO_THROTTLE_EXPIRY_TIME; 355 return this; 356 } 357 358 /** 359 * Set the type of request that the framework will make the next time it retries 360 * to call {@link IDataService#setupDataCall}. 361 * 362 * @param retryType the type of request 363 * @return The same instance of the builder. 364 */ 365 @NonNull setRetryType(@etryType int retryType)366 public Builder setRetryType(@RetryType int retryType) { 367 this.mRetryType = retryType; 368 return this; 369 } 370 371 /** 372 * Build the {@link ThrottleStatus} 373 * 374 * @return the {@link ThrottleStatus} object 375 */ 376 @NonNull build()377 public ThrottleStatus build() { 378 return new ThrottleStatus( 379 mSlotIndex, 380 mTransportType, 381 mApnType, 382 mThrottleType, 383 mThrottleExpiryTimeMillis, 384 mRetryType); 385 } 386 } 387 } 388