1 /* 2 * Copyright (C) 2021 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 com.android.internal.telephony.data; 18 19 import android.annotation.CurrentTimeMillisLong; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.telephony.TelephonyManager; 23 import android.telephony.data.DataProfile; 24 25 import com.android.internal.annotations.VisibleForTesting; 26 27 import java.util.ArrayList; 28 import java.util.HashSet; 29 import java.util.List; 30 import java.util.Set; 31 32 /** 33 * The class to describe a data evaluation for whether allowing or disallowing certain operations 34 * like setup a data network, sustaining existing data networks, or handover between IWLAN and 35 * cellular. 36 */ 37 public class DataEvaluation { 38 /** The reason for this evaluation */ 39 @NonNull 40 private final DataEvaluationReason mDataEvaluationReason; 41 42 /** Data disallowed reasons. There could be multiple reasons for not allowing data. */ 43 @NonNull 44 private final Set<DataDisallowedReason> mDataDisallowedReasons = new HashSet<>(); 45 46 /** Data allowed reason. It is intended to only have one allowed reason. */ 47 @NonNull 48 private DataAllowedReason mDataAllowedReason = DataAllowedReason.NONE; 49 50 @Nullable 51 private DataProfile mCandidateDataProfile = null; 52 53 /** The timestamp of evaluation time */ 54 @CurrentTimeMillisLong 55 private long mEvaluatedTime = 0; 56 57 /** 58 * Constructor 59 * 60 * @param reason The reason for this evaluation. 61 */ DataEvaluation(@onNull DataEvaluationReason reason)62 public DataEvaluation(@NonNull DataEvaluationReason reason) { 63 mDataEvaluationReason = reason; 64 } 65 66 /** 67 * Add a data disallowed reason. Note that adding a disallowed reason will clean up the 68 * allowed reason because they are mutual exclusive. 69 * 70 * @param reason Disallowed reason. 71 */ addDataDisallowedReason(DataDisallowedReason reason)72 public void addDataDisallowedReason(DataDisallowedReason reason) { 73 mDataAllowedReason = DataAllowedReason.NONE; 74 mDataDisallowedReasons.add(reason); 75 mEvaluatedTime = System.currentTimeMillis(); 76 } 77 78 /** 79 * Remove a data disallowed reason if one exists. 80 * 81 * @param reason Disallowed reason. 82 */ removeDataDisallowedReason(DataDisallowedReason reason)83 public void removeDataDisallowedReason(DataDisallowedReason reason) { 84 mDataDisallowedReasons.remove(reason); 85 mEvaluatedTime = System.currentTimeMillis(); 86 } 87 88 /** 89 * Add a data allowed reason. Note that adding an allowed reason will clean up the disallowed 90 * reasons because they are mutual exclusive. 91 * 92 * @param reason Allowed reason. 93 */ addDataAllowedReason(DataAllowedReason reason)94 public void addDataAllowedReason(DataAllowedReason reason) { 95 mDataDisallowedReasons.clear(); 96 97 // Only higher priority allowed reason can overwrite the old one. See 98 // DataAllowedReason for the oder. 99 if (reason.ordinal() > mDataAllowedReason.ordinal()) { 100 mDataAllowedReason = reason; 101 } 102 mEvaluatedTime = System.currentTimeMillis(); 103 } 104 105 /** 106 * @return List of data disallowed reasons. 107 */ 108 @NonNull getDataDisallowedReasons()109 public List<DataDisallowedReason> getDataDisallowedReasons() { 110 return new ArrayList<>(mDataDisallowedReasons); 111 } 112 113 /** 114 * @return The data allowed reason. 115 */ 116 @NonNull getDataAllowedReason()117 public DataAllowedReason getDataAllowedReason() { 118 return mDataAllowedReason; 119 } 120 121 /** 122 * Set the candidate data profile for setup data network. 123 * 124 * @param dataProfile The candidate data profile. 125 */ setCandidateDataProfile(@onNull DataProfile dataProfile)126 public void setCandidateDataProfile(@NonNull DataProfile dataProfile) { 127 mCandidateDataProfile = dataProfile; 128 } 129 130 /** 131 * @return The candidate data profile for setup data network. 132 */ 133 @Nullable getCandidateDataProfile()134 public DataProfile getCandidateDataProfile() { 135 return mCandidateDataProfile; 136 } 137 138 /** 139 * @return {@code true} if the evaluation contains disallowed reasons. 140 */ containsDisallowedReasons()141 public boolean containsDisallowedReasons() { 142 return !mDataDisallowedReasons.isEmpty(); 143 } 144 145 /** 146 * Check if it contains a certain disallowed reason. 147 * 148 * @param reason The disallowed reason to check. 149 * @return {@code true} if the provided reason matches one of the disallowed reasons. 150 */ contains(DataDisallowedReason reason)151 public boolean contains(DataDisallowedReason reason) { 152 return mDataDisallowedReasons.contains(reason); 153 } 154 155 /** 156 * Check if only one disallowed reason prevent data connection. 157 * 158 * @param reason The given reason to check 159 * @return {@code true} if the given reason is the only one that prevents data connection 160 */ containsOnly(DataDisallowedReason reason)161 public boolean containsOnly(DataDisallowedReason reason) { 162 return mDataDisallowedReasons.size() == 1 && contains(reason); 163 } 164 165 /** 166 * Check if all the disallowed reasons are a subset of the given reason. 167 * 168 * @param reasons The given reason to check 169 * @return {@code true} if it doesn't contain any disallowed reasons other than the given 170 * reasons. 171 */ isSubsetOf(DataDisallowedReason... reasons)172 public boolean isSubsetOf(DataDisallowedReason... reasons) { 173 int matched = 0; 174 for (DataDisallowedReason requestedReason : reasons) { 175 if (mDataDisallowedReasons.contains(requestedReason)) matched++; 176 } 177 return matched == mDataDisallowedReasons.size(); 178 } 179 180 /** 181 * Check if the any of the disallowed reasons match one of the provided reason. 182 * 183 * @param reasons The given reasons to check. 184 * @return {@code true} if any of the given reasons matches one of the disallowed reasons. 185 */ containsAny(DataDisallowedReason... reasons)186 public boolean containsAny(DataDisallowedReason... reasons) { 187 for (DataDisallowedReason reason : reasons) { 188 if (mDataDisallowedReasons.contains(reason)) return true; 189 } 190 return false; 191 } 192 193 /** 194 * Check if the allowed reason is the specified reason. 195 * 196 * @param reason The allowed reason. 197 * @return {@code true} if the specified reason matches the allowed reason. 198 */ contains(DataAllowedReason reason)199 public boolean contains(DataAllowedReason reason) { 200 return reason == mDataAllowedReason; 201 } 202 203 /** 204 * @return {@code true} if the disallowed reasons contains hard reasons. 205 */ containsHardDisallowedReasons()206 public boolean containsHardDisallowedReasons() { 207 for (DataDisallowedReason reason : mDataDisallowedReasons) { 208 if (reason.isHardReason()) { 209 return true; 210 } 211 } 212 return false; 213 } 214 215 /** 216 * The reason for evaluating unsatisfied network requests, existing data networks, and handover. 217 */ 218 @VisibleForTesting 219 public enum DataEvaluationReason { 220 /** New request from the apps. */ 221 NEW_REQUEST(false), 222 /** Data config changed. */ 223 DATA_CONFIG_CHANGED(true), 224 /** SIM is loaded. */ 225 SIM_LOADED(true), 226 /** SIM is removed. */ 227 SIM_REMOVAL(true), 228 /** Data profiles changed. */ 229 DATA_PROFILES_CHANGED(true), 230 /** When service state changes.(For now only considering data RAT and data registration). */ 231 DATA_SERVICE_STATE_CHANGED(true), 232 /** When data is enabled or disabled (by user, carrier, thermal, etc...) */ 233 DATA_ENABLED_CHANGED(true), 234 /** When data enabled overrides are changed (MMS always allowed, data on non-DDS sub). */ 235 DATA_ENABLED_OVERRIDE_CHANGED(true), 236 /** When data roaming is enabled or disabled. */ 237 ROAMING_ENABLED_CHANGED(true), 238 /** When voice call ended (for concurrent voice/data not supported RAT). */ 239 VOICE_CALL_ENDED(true), 240 /** When network restricts or no longer restricts mobile data. */ 241 DATA_RESTRICTED_CHANGED(true), 242 /** Network capabilities changed. The unsatisfied requests might have chances to attach. */ 243 DATA_NETWORK_CAPABILITIES_CHANGED(true), 244 /** When emergency call started or ended. */ 245 EMERGENCY_CALL_CHANGED(true), 246 /** When data disconnected, re-evaluate later to see if data could be brought up again. */ 247 RETRY_AFTER_DISCONNECTED(true), 248 /** Data setup retry. */ 249 DATA_RETRY(false), 250 /** For handover evaluation, or for network tearing down after handover succeeds/fails. */ 251 DATA_HANDOVER(true), 252 /** Preferred transport changed. */ 253 PREFERRED_TRANSPORT_CHANGED(true), 254 /** Slice config changed. */ 255 SLICE_CONFIG_CHANGED(true), 256 /** SRVCC state changed. */ 257 SRVCC_STATE_CHANGED(true), 258 /** 259 * Single data network arbitration. On certain RATs, only one data network is allowed at the 260 * same time. 261 */ 262 SINGLE_DATA_NETWORK_ARBITRATION(true), 263 /** Query from {@link TelephonyManager#isDataConnectivityPossible()}. */ 264 EXTERNAL_QUERY(false), 265 /** Tracking area code changed. */ 266 TAC_CHANGED(true), 267 /** Unsatisfied network request detached. */ 268 UNSATISFIED_REQUEST_DETACHED(true), 269 /** track bootstrap sim data usage */ 270 CHECK_DATA_USAGE(false); 271 272 /** 273 * {@code true} if the evaluation is due to environmental changes (i.e. SIM removal, 274 * registration state changes, etc.... 275 */ 276 private final boolean mIsConditionBased; 277 278 /** 279 * @return {@code true} if the evaluation is due to environmental changes (i.e. SIM removal, 280 * registration state changes, etc.... 281 */ isConditionBased()282 public boolean isConditionBased() { 283 return mIsConditionBased; 284 } 285 286 /** 287 * Constructor 288 * 289 * @param isConditionBased {@code true} if the evaluation is due to environmental changes 290 * (i.e. SIM removal, registration state changes, etc....) 291 */ DataEvaluationReason(boolean isConditionBased)292 DataEvaluationReason(boolean isConditionBased) { 293 mIsConditionBased = isConditionBased; 294 } 295 } 296 297 /** Disallowed reasons. There could be multiple reasons if it is not allowed. */ 298 public enum DataDisallowedReason { 299 // Soft failure reasons. A soft reason means that in certain conditions, data is still 300 // allowed. Normally those reasons are due to users settings. 301 /** Data is disabled by the user or policy. */ 302 DATA_DISABLED(false), 303 /** Data roaming is disabled by the user. */ 304 ROAMING_DISABLED(false), 305 /** Default data not selected. */ 306 DEFAULT_DATA_UNSELECTED(false), 307 308 // Belows are all hard failure reasons. A hard reason means no matter what the data should 309 // not be allowed. 310 /** Data registration state is not in service. */ 311 NOT_IN_SERVICE(true), 312 /** Data config is not ready. */ 313 DATA_CONFIG_NOT_READY(true), 314 /** SIM is not ready. */ 315 SIM_NOT_READY(true), 316 /** Concurrent voice and data is not allowed. */ 317 CONCURRENT_VOICE_DATA_NOT_ALLOWED(true), 318 /** Service option not supported. */ 319 SERVICE_OPTION_NOT_SUPPORTED(true), 320 /** Carrier notified data should be restricted. */ 321 DATA_RESTRICTED_BY_NETWORK(true), 322 /** Radio power is off (i.e. airplane mode on) */ 323 RADIO_POWER_OFF(true), 324 /** Data setup now allowed due to pending tear down all networks. */ 325 PENDING_TEAR_DOWN_ALL(true), 326 /** Airplane mode is forcibly turned on by the carrier. */ 327 RADIO_DISABLED_BY_CARRIER(true), 328 /** Underlying data service is not bound. */ 329 DATA_SERVICE_NOT_READY(true), 330 /** Unable to find a suitable data profile. */ 331 NO_SUITABLE_DATA_PROFILE(true), 332 /** Current data network type not allowed. */ 333 DATA_NETWORK_TYPE_NOT_ALLOWED(true), 334 /** Device is currently in CDMA ECBM. */ 335 CDMA_EMERGENCY_CALLBACK_MODE(true), 336 /** There is already a retry setup/handover scheduled. */ 337 RETRY_SCHEDULED(true), 338 /** Network has explicitly request to throttle setup attempt. */ 339 DATA_THROTTLED(true), 340 /** Data profile becomes invalid. (could be removed by the user, or SIM refresh, etc..) */ 341 DATA_PROFILE_INVALID(true), 342 /** Data profile not preferred (i.e. users switch preferred profile in APN editor.) */ 343 DATA_PROFILE_NOT_PREFERRED(true), 344 /** Handover is not allowed by policy. */ 345 NOT_ALLOWED_BY_POLICY(true), 346 /** Data network is not in the right state. */ 347 ILLEGAL_STATE(true), 348 /** VoPS is not supported by the network. */ 349 VOPS_NOT_SUPPORTED(true), 350 /** Only one data network is allowed at one time. */ 351 ONLY_ALLOWED_SINGLE_NETWORK(true), 352 /** Data enabled settings are not ready. */ 353 DATA_SETTINGS_NOT_READY(true), 354 /** Handover max retry stopped but network is not on the preferred transport. */ 355 HANDOVER_RETRY_STOPPED(true), 356 /** BootStrap sim data limit reached. */ 357 DATA_LIMIT_REACHED(true), 358 /** Data network connectivity transport not allowed. */ 359 DATA_NETWORK_TRANSPORT_NOT_ALLOWED(true); 360 361 private final boolean mIsHardReason; 362 363 /** 364 * @return {@code true} if the disallowed reason is a hard reason. 365 */ isHardReason()366 public boolean isHardReason() { 367 return mIsHardReason; 368 } 369 370 /** 371 * Constructor 372 * 373 * @param isHardReason {@code true} if the disallowed reason is a hard reason. A hard reason 374 * means no matter what the data should not be allowed. A soft reason means that in certain 375 * conditions, data is still allowed. 376 */ DataDisallowedReason(boolean isHardReason)377 DataDisallowedReason(boolean isHardReason) { 378 mIsHardReason = isHardReason; 379 } 380 } 381 382 /** 383 * Data allowed reasons. There will be only one reason if data is allowed. 384 */ 385 public enum DataAllowedReason { 386 // Note that unlike disallowed reasons, we only have one allowed reason every time 387 // when we check data is allowed or not. The order of these allowed reasons is very 388 // important. The lower ones take precedence over the upper ones. 389 /** 390 * None. This is the initial value. 391 */ 392 NONE, 393 /** 394 * The normal reason. This is the most common case. 395 */ 396 NORMAL, 397 /** 398 * Data is allowed because an ongoing VoPS call depends on this network 399 */ 400 IN_VOICE_CALL, 401 /** 402 * The network brought up by this network request is unmetered. Should allowed no matter 403 * the user enables or disables data. 404 */ 405 UNMETERED_USAGE, 406 /** 407 * The network request supports MMS and MMS is always allowed. 408 */ 409 MMS_REQUEST, 410 /** 411 * The network request is restricted (i.e. Only privilege apps can access the network.) 412 */ 413 RESTRICTED_REQUEST, 414 /** 415 * SUPL is allowed while emergency call is ongoing. 416 */ 417 EMERGENCY_SUPL, 418 /** 419 * Data is allowed because the network request is for emergency. This should be always at 420 * the bottom (i.e. highest priority) 421 */ 422 EMERGENCY_REQUEST, 423 } 424 425 @Override toString()426 public String toString() { 427 StringBuilder evaluationStr = new StringBuilder(); 428 evaluationStr.append("Data evaluation: evaluation reason:") 429 .append(mDataEvaluationReason).append(", "); 430 if (!mDataDisallowedReasons.isEmpty()) { 431 evaluationStr.append("Data disallowed reasons:"); 432 for (DataDisallowedReason reason : mDataDisallowedReasons) { 433 evaluationStr.append(" ").append(reason); 434 } 435 } else { 436 evaluationStr.append("Data allowed reason:"); 437 evaluationStr.append(" ").append(mDataAllowedReason); 438 } 439 evaluationStr.append(", candidate profile=").append(mCandidateDataProfile); 440 evaluationStr.append(", time=").append(DataUtils.systemTimeToString(mEvaluatedTime)); 441 return evaluationStr.toString(); 442 } 443 444 } 445