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.ons; 18 19 import android.annotation.TestApi; 20 import android.content.Context; 21 import android.net.ConnectivityManager; 22 import android.net.Network; 23 import android.net.NetworkCapabilities; 24 import android.net.NetworkRequest; 25 import android.os.Handler; 26 import android.os.Looper; 27 import android.os.Message; 28 import android.os.ParcelUuid; 29 import android.os.PersistableBundle; 30 import android.telephony.CarrierConfigManager; 31 import android.telephony.SubscriptionInfo; 32 import android.telephony.SubscriptionManager; 33 import android.telephony.TelephonyManager; 34 import android.telephony.euicc.EuiccManager; 35 import android.util.Log; 36 37 import com.android.internal.annotations.VisibleForTesting; 38 import com.android.ons.ONSProfileDownloader.DownloadRetryResultCode; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 import java.util.Random; 43 44 /** 45 * @class ONSProfileActivator 46 * @brief ONSProfileActivator makes sure that the CBRS profile is downloaded, activated and grouped 47 * when an opportunistic data enabled pSIM is inserted. 48 */ 49 public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfigListener, 50 ONSProfileDownloader.IONSProfileDownloaderListener { 51 52 private static final String TAG = ONSProfileActivator.class.getName(); 53 private final Context mContext; 54 private final SubscriptionManager mSubManager; 55 private final TelephonyManager mTelephonyManager; 56 private final CarrierConfigManager mCarrierConfigMgr; 57 private final EuiccManager mEuiccManager; 58 private final ONSProfileConfigurator mONSProfileConfig; 59 private final ONSProfileDownloader mONSProfileDownloader; 60 private final ConnectivityManager mConnectivityManager; 61 private final ONSStats mONSStats; 62 @VisibleForTesting protected boolean mIsInternetConnAvailable = false; 63 @VisibleForTesting protected boolean mRetryDownloadWhenNWConnected = false; 64 @VisibleForTesting protected int mDownloadRetryCount = 0; 65 66 @VisibleForTesting protected static final int REQUEST_CODE_DOWNLOAD_RETRY = 2; 67 ONSProfileActivator(Context context, ONSStats onsStats)68 public ONSProfileActivator(Context context, ONSStats onsStats) { 69 mContext = context; 70 mSubManager = mContext.getSystemService(SubscriptionManager.class); 71 mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 72 mCarrierConfigMgr = mContext.getSystemService(CarrierConfigManager.class); 73 mEuiccManager = mContext.getSystemService(EuiccManager.class); 74 mONSProfileConfig = new ONSProfileConfigurator(mContext, mSubManager, 75 mCarrierConfigMgr, mEuiccManager, this); 76 mONSProfileDownloader = new ONSProfileDownloader(mContext, mCarrierConfigMgr, 77 mEuiccManager, mONSProfileConfig, this); 78 79 //Monitor internet connection. 80 mConnectivityManager = context.getSystemService(ConnectivityManager.class); 81 mONSStats = onsStats; 82 NetworkRequest request = new NetworkRequest.Builder().addCapability( 83 NetworkCapabilities.NET_CAPABILITY_VALIDATED).build(); 84 mConnectivityManager.registerNetworkCallback(request, new NetworkCallback()); 85 } 86 87 /** 88 * This constructor is only for JUnit testing 89 */ 90 @TestApi ONSProfileActivator(Context mockContext, SubscriptionManager subscriptionManager, TelephonyManager telephonyManager, CarrierConfigManager carrierConfigMgr, EuiccManager euiccManager, ConnectivityManager connManager, ONSProfileConfigurator onsProfileConfigurator, ONSProfileDownloader onsProfileDownloader, ONSStats onsStats)91 ONSProfileActivator(Context mockContext, SubscriptionManager subscriptionManager, 92 TelephonyManager telephonyManager, CarrierConfigManager carrierConfigMgr, 93 EuiccManager euiccManager, ConnectivityManager connManager, 94 ONSProfileConfigurator onsProfileConfigurator, 95 ONSProfileDownloader onsProfileDownloader, ONSStats onsStats) { 96 mContext = mockContext; 97 mSubManager = subscriptionManager; 98 mTelephonyManager = telephonyManager; 99 mCarrierConfigMgr = carrierConfigMgr; 100 mEuiccManager = euiccManager; 101 mConnectivityManager = connManager; 102 mONSProfileConfig = onsProfileConfigurator; 103 mONSProfileDownloader = onsProfileDownloader; 104 mONSStats = onsStats; 105 } 106 getONSProfileConfigurator()107 ONSProfileConfigurator getONSProfileConfigurator() { 108 return mONSProfileConfig; 109 } 110 getONSProfileDownloader()111 ONSProfileDownloader getONSProfileDownloader() { 112 return mONSProfileDownloader; 113 } 114 115 private final Handler mHandler = new Handler(Looper.myLooper()) { 116 @Override 117 public void handleMessage(Message msg) { 118 switch (msg.what) { 119 case REQUEST_CODE_DOWNLOAD_RETRY: { 120 Result res = provisionCBRS(); 121 Log.d(TAG, res.toString()); 122 mONSStats.logEvent(new ONSStatsInfo().setProvisioningResult(res)); 123 } 124 break; 125 } 126 } 127 }; 128 129 /** 130 * Called when SIM state changes. Triggers CBRS Auto provisioning. 131 */ handleCarrierConfigChange()132 public Result handleCarrierConfigChange() { 133 Result res = provisionCBRS(); 134 Log.d(TAG, res.toString()); 135 mONSStats.logEvent(new ONSStatsInfo().setProvisioningResult(res)); 136 137 // Reset mDownloadRetryCount as carrier config change event is received. Either new SIM card 138 // is inserted or carrier config values are updated. 139 if (res == Result.DOWNLOAD_REQUESTED || res == Result.SUCCESS) { 140 mDownloadRetryCount = 0; 141 } 142 143 return res; 144 } 145 146 @Override onOppSubscriptionDeleted(int pSIMId)147 public void onOppSubscriptionDeleted(int pSIMId) { 148 Result res = provisionCBRS(); 149 Log.d(TAG, res.toString()); 150 mONSStats.logEvent(new ONSStatsInfo().setProvisioningResult(res)); 151 } 152 153 /** 154 * Checks if AutoProvisioning is enabled, MultiSIM and eSIM support, cbrs pSIM is inserted and 155 * makes sure device is in muti-SIM mode before triggering download of opportunistic eSIM. 156 * Once downloaded, groups with pSIM, sets opportunistic and activates. 157 */ provisionCBRS()158 private Result provisionCBRS() { 159 160 if (!isONSAutoProvisioningEnabled()) { 161 return Result.ERR_AUTO_PROVISIONING_DISABLED; 162 } 163 164 //Check if device supports eSIM 165 if (!isESIMSupported()) { 166 return Result.ERR_ESIM_NOT_SUPPORTED; 167 } 168 169 //Check if it's a multi SIM Phone. CBRS is not supported on Single SIM phone. 170 if (!isMultiSIMPhone()) { 171 return Result.ERR_MULTISIM_NOT_SUPPORTED; 172 } 173 174 //Check the number of active subscriptions. 175 List<SubscriptionInfo> activeSubInfos = mSubManager.getActiveSubscriptionInfoList(); 176 int activeSubCount = activeSubInfos.size(); 177 Log.d(TAG, "Active subscription count:" + activeSubCount); 178 179 if (activeSubCount <= 0) { 180 return Result.ERR_NO_SIM_INSERTED; 181 } else if (activeSubCount == 1) { 182 SubscriptionInfo pSubInfo = activeSubInfos.get(0); 183 if (pSubInfo.isOpportunistic()) { 184 //Only one SIM is active and its opportunistic SIM. 185 //Opportunistic eSIM shouldn't be used without pSIM. 186 return Result.ERR_SINGLE_ACTIVE_OPPORTUNISTIC_SIM; 187 } 188 189 //if pSIM is not a CBRS carrier 190 if (!isOppDataAutoProvisioningSupported( 191 pSubInfo.getSubscriptionId())) { 192 return Result.ERR_CARRIER_DOESNT_SUPPORT_CBRS; 193 } 194 195 if (isDeviceInSingleSIMMode()) { 196 if (!switchToMultiSIMMode()) { 197 return Result.ERR_CANNOT_SWITCH_TO_DUAL_SIM_MODE; 198 } 199 200 //Once device is Switched to Dual-SIM Mode, handleSimStateChange is triggered. 201 return Result.ERR_SWITCHING_TO_DUAL_SIM_MODE; 202 } 203 204 return downloadAndActivateOpportunisticSubscription(pSubInfo); 205 } else if (activeSubCount >= 2) { 206 //If all the SIMs are physical SIM then it's a sure case of DUAL Active Subscription. 207 boolean allPhysicalSIMs = true; 208 for (SubscriptionInfo subInfo : activeSubInfos) { 209 if (subInfo.isEmbedded()) { 210 allPhysicalSIMs = false; 211 break; 212 } 213 } 214 215 if (allPhysicalSIMs) { 216 return Result.ERR_DUAL_ACTIVE_SUBSCRIPTIONS; 217 } 218 219 //Check if one of the subscription is opportunistic but not marked. 220 //if one of the SIM is opportunistic and not grouped then group the subscription. 221 for (SubscriptionInfo subInfo : activeSubInfos) { 222 int pSubId = subInfo.getSubscriptionId(); 223 if (!subInfo.isEmbedded() && isOppDataAutoProvisioningSupported(pSubId)) { 224 225 Log.d(TAG, "CBRS pSIM found. SubId:" + pSubId); 226 227 //Check if other SIM is opportunistic based on carrier-id. 228 SubscriptionInfo oppSubInfo = mONSProfileConfig 229 .findOpportunisticSubscription(pSubId); 230 231 //If opportunistic eSIM is found and activated. 232 if (oppSubInfo != null) { 233 if (mSubManager.isActiveSubscriptionId(oppSubInfo.getSubscriptionId()) 234 && oppSubInfo.isOpportunistic()) { 235 //Already configured. No action required. 236 return Result.SUCCESS; 237 } 238 239 ParcelUuid pSIMGroupId = mONSProfileConfig.getPSIMGroupId(subInfo); 240 mONSProfileConfig.groupWithPSIMAndSetOpportunistic(oppSubInfo, pSIMGroupId); 241 return Result.SUCCESS; 242 } 243 } 244 } 245 246 return Result.ERR_DUAL_ACTIVE_SUBSCRIPTIONS; 247 } 248 249 return Result.ERR_UNKNOWN; 250 } 251 downloadAndActivateOpportunisticSubscription( SubscriptionInfo primaryCBRSSubInfo)252 private Result downloadAndActivateOpportunisticSubscription( 253 SubscriptionInfo primaryCBRSSubInfo) { 254 Log.d(TAG, "downloadAndActivateOpportunisticSubscription"); 255 256 //Check if pSIM is part of a group. If not then create a group. 257 ParcelUuid pSIMgroupId = mONSProfileConfig.getPSIMGroupId(primaryCBRSSubInfo); 258 259 //Check if opp eSIM is already downloaded but not grouped. 260 SubscriptionInfo oppSubInfo = mONSProfileConfig.findOpportunisticSubscription( 261 primaryCBRSSubInfo.getSubscriptionId()); 262 if (oppSubInfo != null) { 263 mONSProfileConfig.groupWithPSIMAndSetOpportunistic(oppSubInfo, pSIMgroupId); 264 return Result.SUCCESS; 265 } 266 267 if (!mIsInternetConnAvailable) { 268 Log.d(TAG, "No internet connection. Download will be attempted when " 269 + "connection is restored"); 270 mRetryDownloadWhenNWConnected = true; 271 return Result.ERR_WAITING_FOR_INTERNET_CONNECTION; 272 } 273 274 /* If download WiFi only flag is set and WiFi is not connected */ 275 if (getESIMDownloadViaWiFiOnlyFlag(primaryCBRSSubInfo.getSubscriptionId()) 276 && !isWiFiConnected()) { 277 Log.d(TAG, "Download via WiFi only flag is set but WiFi is not connected." 278 + "Download will be attempted when WiFi connection is restored"); 279 mRetryDownloadWhenNWConnected = true; 280 return Result.ERR_WAITING_FOR_WIFI_CONNECTION; 281 } 282 283 //Opportunistic subscription not found. Trigger Download. 284 ONSProfileDownloader.DownloadProfileResult res = mONSProfileDownloader.downloadProfile( 285 primaryCBRSSubInfo.getSubscriptionId()); 286 287 switch (res) { 288 case DUPLICATE_REQUEST: return Result.ERR_DUPLICATE_DOWNLOAD_REQUEST; 289 case INVALID_SMDP_ADDRESS: return Result.ERR_INVALID_CARRIER_CONFIG; 290 case SUCCESS: return Result.DOWNLOAD_REQUESTED; 291 } 292 293 return Result.ERR_UNKNOWN; 294 } 295 296 @Override onDownloadComplete(int primarySubId)297 public void onDownloadComplete(int primarySubId) { 298 mRetryDownloadWhenNWConnected = false; 299 SubscriptionInfo opportunisticESIM = mONSProfileConfig.findOpportunisticSubscription( 300 primarySubId); 301 if (opportunisticESIM == null) { 302 Log.e(TAG, "Downloaded Opportunistic eSIM not found. Unable to group with pSIM"); 303 mONSStats.logEvent(new ONSStatsInfo() 304 .setProvisioningResult(Result.ERR_DOWNLOADED_ESIM_NOT_FOUND) 305 .setPrimarySimSubId(primarySubId) 306 .setWifiConnected(isWiFiConnected())); 307 return; 308 } 309 310 SubscriptionInfo pSIMSubInfo = mSubManager.getActiveSubscriptionInfo(primarySubId); 311 if (pSIMSubInfo != null) { 312 // Group with same Primary SIM for which eSIM is downloaded. 313 mONSProfileConfig.groupWithPSIMAndSetOpportunistic( 314 opportunisticESIM, pSIMSubInfo.getGroupUuid()); 315 Log.d(TAG, "eSIM downloaded and configured successfully"); 316 mONSStats.logEvent(new ONSStatsInfo() 317 .setProvisioningResult(Result.SUCCESS) 318 .setRetryCount(mDownloadRetryCount) 319 .setWifiConnected(isWiFiConnected())); 320 } else { 321 Log.d(TAG, "ESIM downloaded but pSIM is not active or removed"); 322 mONSStats.logEvent(new ONSStatsInfo() 323 .setProvisioningResult(Result.ERR_PSIM_NOT_FOUND) 324 .setOppSimCarrierId(opportunisticESIM.getCarrierId()) 325 .setWifiConnected(isWiFiConnected())); 326 } 327 } 328 329 @Override onDownloadError(int pSIMSubId, DownloadRetryResultCode resultCode, int detailedErrorCode)330 public void onDownloadError(int pSIMSubId, DownloadRetryResultCode resultCode, 331 int detailedErrorCode) { 332 boolean logStats = true; 333 switch (resultCode) { 334 case ERR_MEMORY_FULL: { 335 //eUICC Memory full occurred while downloading opportunistic eSIM. 336 337 //First find and delete any opportunistic eSIMs from the operator same as the 338 // current primary SIM. 339 ArrayList<Integer> oppSubIds = mONSProfileConfig 340 .getOpportunisticSubIdsofPSIMOperator(pSIMSubId); 341 if (oppSubIds != null && oppSubIds.size() > 0) { 342 mONSProfileConfig.deleteSubscription(oppSubIds.get(0)); 343 } else { 344 //else, find the inactive opportunistic eSIMs (any operator) and delete one of 345 // them and retry download again. 346 mONSProfileConfig.deleteInactiveOpportunisticSubscriptions(pSIMSubId); 347 } 348 349 //Delete subscription -> onOppSubscriptionDeleted callback -> provisionCBRS -> 350 // triggers eSIM download again. 351 352 //Download retry will stop if there are no opportunistic eSIM profiles to delete. 353 } 354 break; 355 356 case ERR_INSTALL_ESIM_PROFILE_FAILED: { 357 //Since the installation of eSIM profile has failed there may be an issue with the 358 //format or profile data. We retry by first deleting existing eSIM profile from the 359 //operator same as the primary SIM and retry download opportunistic eSIM. 360 ArrayList<Integer> oppSubIds = mONSProfileConfig 361 .getOpportunisticSubIdsofPSIMOperator(pSIMSubId); 362 363 if (oppSubIds != null && oppSubIds.size() > 0) { 364 mONSProfileConfig.deleteSubscription(oppSubIds.get(0)); 365 } 366 367 //Download retry will stop if there are no opportunistic eSIM profiles to delete 368 // from the same operator. 369 } 370 break; 371 372 case ERR_RETRY_DOWNLOAD: { 373 if (startBackoffTimer(pSIMSubId)) { 374 // do not log the atom if download retry has not reached max limit. 375 logStats = false; 376 } 377 } 378 break; 379 default: { 380 // Stop download until SIM change or device reboot. 381 Log.e(TAG, "Download failed with cause=" + resultCode); 382 } 383 } 384 if (logStats) { 385 mONSStats.logEvent(new ONSStatsInfo() 386 .setDownloadResult(resultCode) 387 .setPrimarySimSubId(pSIMSubId) 388 .setRetryCount(mDownloadRetryCount) 389 .setDetailedErrCode(detailedErrorCode) 390 .setWifiConnected(isWiFiConnected())); 391 } 392 } 393 394 /** 395 * Called when eSIM download fails. Listener is called after a delay based on retry count with 396 * the error code: BACKOFF_TIMER_EXPIRED 397 * 398 * @param pSIMSubId Primary Subscription ID 399 * @return true if backoff timer starts; otherwise false. 400 */ 401 @VisibleForTesting startBackoffTimer(int pSIMSubId)402 protected boolean startBackoffTimer(int pSIMSubId) { 403 //retry logic 404 mDownloadRetryCount++; 405 Log.e(TAG, "Download retry count :" + mDownloadRetryCount); 406 407 //Stop download retry if number of retries exceeded max configured value. 408 if (mDownloadRetryCount > getDownloadRetryMaxAttemptsVal(pSIMSubId)) { 409 Log.e(TAG, "Max download retry attempted. Stopping retry"); 410 return false; 411 } 412 413 int backoffTimerVal = getDownloadRetryBackOffTimerVal(pSIMSubId); 414 int delay = calculateBackoffDelay(mDownloadRetryCount, backoffTimerVal); 415 416 Message retryMsg = new Message(); 417 retryMsg.what = REQUEST_CODE_DOWNLOAD_RETRY; 418 retryMsg.arg2 = pSIMSubId; 419 mHandler.sendMessageDelayed(retryMsg, delay); 420 421 Log.d(TAG, "Download failed. Retry after :" + delay + "MilliSecs"); 422 return true; 423 } 424 425 @VisibleForTesting calculateBackoffDelay(int retryCount, int backoffTimerVal)426 protected static int calculateBackoffDelay(int retryCount, int backoffTimerVal) { 427 /** 428 * Timer value is calculated using "Exponential Backoff retry" algorithm. 429 * When the first download failure occurs, retry download after 430 * BACKOFF_TIMER_VALUE [Carrier Configurable] seconds. 431 * 432 * If download fails again then, retry after either BACKOFF_TIMER_VALUE, 433 * 2xBACKOFF_TIMER_VALUE, or 3xBACKOFF_TIMER_VALUE seconds. 434 * 435 * In general after the cth failed attempt, retry after k * 436 * BACKOFF_TIMER_VALUE seconds, where k is a random integer between 1 and 437 * 2^c − 1. Max c value is KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT 438 * [Carrier configurable] 439 */ 440 Random random = new Random(); 441 //Calculate 2^c − 1 442 int maxTime = (int) Math.pow(2, retryCount) - 1; 443 444 //Random value between (1 & 2^c − 1) and convert to millisecond 445 return ((random.nextInt(maxTime) + 1)) * backoffTimerVal * 1000; 446 } 447 448 /** 449 * Retrieves maximum retry attempts from carrier configuration. After maximum attempts, further 450 * attempts will not be made until next device reboot. 451 * 452 * @param subscriptionId subscription Id of the primary SIM. 453 * @return integer value for maximum allowed retry attempts. 454 */ getDownloadRetryMaxAttemptsVal(int subscriptionId)455 private int getDownloadRetryMaxAttemptsVal(int subscriptionId) { 456 PersistableBundle config = mCarrierConfigMgr.getConfigForSubId(subscriptionId); 457 return config.getInt(CarrierConfigManager.KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT); 458 } 459 460 /** 461 * Retrieves backoff timer value (in seconds) from carrier configuration. Value is used to 462 * calculate delay before retrying profile download. 463 * 464 * @param subscriptionId subscription Id of the primary SIM. 465 * @return Backoff timer value in seconds. 466 */ getDownloadRetryBackOffTimerVal(int subscriptionId)467 private int getDownloadRetryBackOffTimerVal(int subscriptionId) { 468 PersistableBundle config = mCarrierConfigMgr.getConfigForSubId(subscriptionId); 469 return config.getInt(CarrierConfigManager.KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT); 470 } 471 472 473 /** 474 * Checks if device supports eSIM. 475 */ isESIMSupported()476 private boolean isESIMSupported() { 477 return (mEuiccManager != null && mEuiccManager.isEnabled()); 478 } 479 480 /** 481 * Fetches ONS auto provisioning enable flag from device configuration. 482 * ONS auto provisioning feature executes only when the flag is set to true in device 483 * configuration. 484 */ isONSAutoProvisioningEnabled()485 private boolean isONSAutoProvisioningEnabled() { 486 return mContext.getResources().getBoolean(R.bool.enable_ons_auto_provisioning); 487 } 488 489 /** 490 * Check if device support multiple active SIMs 491 */ isMultiSIMPhone()492 private boolean isMultiSIMPhone() { 493 return (mTelephonyManager.getSupportedModemCount() >= 2); 494 } 495 496 /** 497 * Check if the given subscription is a CBRS supported carrier. 498 */ isOppDataAutoProvisioningSupported(int pSIMSubId)499 private boolean isOppDataAutoProvisioningSupported(int pSIMSubId) { 500 PersistableBundle config = mCarrierConfigMgr.getConfigForSubId(pSIMSubId); 501 return config.getBoolean(CarrierConfigManager 502 .KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL); 503 } 504 505 /** 506 * Checks if device is in single SIM mode. 507 */ isDeviceInSingleSIMMode()508 private boolean isDeviceInSingleSIMMode() { 509 return (mTelephonyManager.getActiveModemCount() <= 1); 510 } 511 512 /** 513 * Switches device to multi SIM mode. Checks if reboot is required before switching and 514 * configuration is triggered only if reboot not required. 515 */ switchToMultiSIMMode()516 private boolean switchToMultiSIMMode() { 517 if (!mTelephonyManager.doesSwitchMultiSimConfigTriggerReboot()) { 518 mTelephonyManager.switchMultiSimConfig(2); 519 return true; 520 } 521 522 return false; 523 } 524 isWiFiConnected()525 private boolean isWiFiConnected() { 526 Network activeNetwork = mConnectivityManager.getActiveNetwork(); 527 if ((activeNetwork != null) && mConnectivityManager.getNetworkCapabilities(activeNetwork) 528 .hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { 529 return true; 530 } 531 532 return false; 533 } 534 535 /** 536 * Retrieves WiFi only eSIM Download flag the given subscription from carrier configuration. 537 * 538 * @param subscriptionId subscription Id of the primary SIM. 539 * @return download flag. 540 */ getESIMDownloadViaWiFiOnlyFlag(int subscriptionId)541 private boolean getESIMDownloadViaWiFiOnlyFlag(int subscriptionId) { 542 PersistableBundle config = mCarrierConfigMgr.getConfigForSubId(subscriptionId); 543 return config.getBoolean( 544 CarrierConfigManager.KEY_OPPORTUNISTIC_ESIM_DOWNLOAD_VIA_WIFI_ONLY_BOOL); 545 } 546 547 private class NetworkCallback extends ConnectivityManager.NetworkCallback { 548 @Override onAvailable(Network network)549 public void onAvailable(Network network) { 550 super.onAvailable(network); 551 Log.d(TAG, "Internet connection available"); 552 mIsInternetConnAvailable = true; 553 if (mRetryDownloadWhenNWConnected) { 554 Result res = provisionCBRS(); 555 Log.d(TAG, res.toString()); 556 mONSStats.logEvent(new ONSStatsInfo().setProvisioningResult(res)); 557 } 558 } 559 560 @Override onLost(Network network)561 public void onLost(Network network) { 562 super.onLost(network); 563 Log.d(TAG, "Internet connection lost"); 564 mIsInternetConnAvailable = false; 565 } 566 } 567 568 /** 569 * Enum to map the results of the CBRS provisioning. The order of the defined enums must be kept 570 * intact and new entries should be appended at the end of the list. 571 */ 572 public enum Result { 573 SUCCESS, 574 DOWNLOAD_REQUESTED, 575 ERR_SWITCHING_TO_DUAL_SIM_MODE, 576 ERR_AUTO_PROVISIONING_DISABLED, 577 ERR_ESIM_NOT_SUPPORTED, 578 ERR_MULTISIM_NOT_SUPPORTED, 579 ERR_CARRIER_DOESNT_SUPPORT_CBRS, 580 ERR_DUAL_ACTIVE_SUBSCRIPTIONS, 581 ERR_NO_SIM_INSERTED, 582 ERR_SINGLE_ACTIVE_OPPORTUNISTIC_SIM, 583 ERR_CANNOT_SWITCH_TO_DUAL_SIM_MODE, 584 ERR_WAITING_FOR_INTERNET_CONNECTION, 585 ERR_WAITING_FOR_WIFI_CONNECTION, 586 ERR_DUPLICATE_DOWNLOAD_REQUEST, 587 ERR_INVALID_CARRIER_CONFIG, 588 ERR_DOWNLOADED_ESIM_NOT_FOUND, 589 ERR_PSIM_NOT_FOUND, 590 ERR_UNKNOWN; 591 } 592 } 593