1 /* 2 * Copyright 2022 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.subscription; 18 19 import android.annotation.CallbackExecutor; 20 import android.annotation.ColorInt; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.UserIdInt; 24 import android.content.ContentValues; 25 import android.content.Context; 26 import android.database.Cursor; 27 import android.net.Uri; 28 import android.os.Handler; 29 import android.os.Looper; 30 import android.os.ParcelUuid; 31 import android.provider.Telephony; 32 import android.provider.Telephony.SimInfo; 33 import android.telephony.SubscriptionInfo; 34 import android.telephony.SubscriptionManager; 35 import android.telephony.SubscriptionManager.DataRoamingMode; 36 import android.telephony.SubscriptionManager.DeviceToDeviceStatusSharingPreference; 37 import android.telephony.SubscriptionManager.ProfileClass; 38 import android.telephony.SubscriptionManager.SimDisplayNameSource; 39 import android.telephony.SubscriptionManager.SubscriptionType; 40 import android.telephony.SubscriptionManager.UsageSetting; 41 import android.telephony.TelephonyManager; 42 import android.telephony.UiccAccessRule; 43 import android.telephony.ims.ImsMmTelManager; 44 import android.text.TextUtils; 45 import android.util.Base64; 46 import android.util.IndentingPrintWriter; 47 import android.util.LocalLog; 48 49 import com.android.internal.annotations.GuardedBy; 50 import com.android.internal.annotations.VisibleForTesting; 51 import com.android.internal.telephony.flags.FeatureFlags; 52 import com.android.internal.telephony.uicc.UiccController; 53 import com.android.internal.util.function.TriConsumer; 54 import com.android.telephony.Rlog; 55 56 import java.io.FileDescriptor; 57 import java.io.PrintWriter; 58 import java.util.AbstractMap; 59 import java.util.ArrayList; 60 import java.util.Arrays; 61 import java.util.HashMap; 62 import java.util.List; 63 import java.util.Map; 64 import java.util.Objects; 65 import java.util.Set; 66 import java.util.concurrent.Executor; 67 import java.util.concurrent.locks.ReadWriteLock; 68 import java.util.concurrent.locks.ReentrantReadWriteLock; 69 import java.util.function.BiFunction; 70 import java.util.function.Function; 71 import java.util.function.Predicate; 72 import java.util.stream.Collectors; 73 74 /** 75 * The subscription database manager is the wrapper of {@link SimInfo} 76 * table. It's a full memory cache of the entire subscription database, and the update can be 77 * asynchronously or synchronously. The database's cache allows multi threads to read 78 * simultaneously, if no write is ongoing. 79 * 80 * Note that from Android 14, directly writing into the subscription database through content 81 * resolver with {@link SimInfo#CONTENT_URI} will cause cache/db out of sync. All the read/write 82 * to the database should go through {@link SubscriptionManagerService}. 83 */ 84 public class SubscriptionDatabaseManager extends Handler { 85 private static final String LOG_TAG = "SDMGR"; 86 87 /** Whether enabling verbose debugging message or not. */ 88 private static final boolean VDBG = false; 89 90 /** Invalid database row index. */ 91 private static final int INVALID_ROW_INDEX = -1; 92 93 /** The mapping from {@link SimInfo} table to {@link SubscriptionInfoInternal} get methods. */ 94 private static final Map<String, Function<SubscriptionInfoInternal, ?>> 95 SUBSCRIPTION_GET_METHOD_MAP = Map.ofEntries( 96 new AbstractMap.SimpleImmutableEntry<>( 97 SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID, 98 SubscriptionInfoInternal::getSubscriptionId), 99 new AbstractMap.SimpleImmutableEntry<>( 100 SimInfo.COLUMN_ICC_ID, 101 SubscriptionInfoInternal::getIccId), 102 new AbstractMap.SimpleImmutableEntry<>( 103 SimInfo.COLUMN_SIM_SLOT_INDEX, 104 SubscriptionInfoInternal::getSimSlotIndex), 105 new AbstractMap.SimpleImmutableEntry<>( 106 SimInfo.COLUMN_DISPLAY_NAME, 107 SubscriptionInfoInternal::getDisplayName), 108 new AbstractMap.SimpleImmutableEntry<>( 109 SimInfo.COLUMN_CARRIER_NAME, 110 SubscriptionInfoInternal::getCarrierName), 111 new AbstractMap.SimpleImmutableEntry<>( 112 SimInfo.COLUMN_NAME_SOURCE, 113 SubscriptionInfoInternal::getDisplayNameSource), 114 new AbstractMap.SimpleImmutableEntry<>( 115 SimInfo.COLUMN_COLOR, 116 SubscriptionInfoInternal::getIconTint), 117 new AbstractMap.SimpleImmutableEntry<>( 118 SimInfo.COLUMN_NUMBER, 119 SubscriptionInfoInternal::getNumber), 120 new AbstractMap.SimpleImmutableEntry<>( 121 SimInfo.COLUMN_DATA_ROAMING, 122 SubscriptionInfoInternal::getDataRoaming), 123 new AbstractMap.SimpleImmutableEntry<>( 124 SimInfo.COLUMN_MCC_STRING, 125 SubscriptionInfoInternal::getMcc), 126 new AbstractMap.SimpleImmutableEntry<>( 127 SimInfo.COLUMN_MNC_STRING, 128 SubscriptionInfoInternal::getMnc), 129 new AbstractMap.SimpleImmutableEntry<>( 130 SimInfo.COLUMN_EHPLMNS, 131 SubscriptionInfoInternal::getEhplmns), 132 new AbstractMap.SimpleImmutableEntry<>( 133 SimInfo.COLUMN_HPLMNS, 134 SubscriptionInfoInternal::getHplmns), 135 new AbstractMap.SimpleImmutableEntry<>( 136 SimInfo.COLUMN_IS_EMBEDDED, 137 SubscriptionInfoInternal::getEmbedded), 138 new AbstractMap.SimpleImmutableEntry<>( 139 SimInfo.COLUMN_CARD_ID, 140 SubscriptionInfoInternal::getCardString), 141 new AbstractMap.SimpleImmutableEntry<>( 142 SimInfo.COLUMN_ACCESS_RULES, 143 SubscriptionInfoInternal::getNativeAccessRules), 144 new AbstractMap.SimpleImmutableEntry<>( 145 SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS, 146 SubscriptionInfoInternal::getCarrierConfigAccessRules), 147 new AbstractMap.SimpleImmutableEntry<>( 148 SimInfo.COLUMN_IS_REMOVABLE, 149 SubscriptionInfoInternal::getRemovableEmbedded), 150 new AbstractMap.SimpleImmutableEntry<>( 151 SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT, 152 SubscriptionInfoInternal::getCellBroadcastExtremeThreatAlertEnabled), 153 new AbstractMap.SimpleImmutableEntry<>( 154 SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT, 155 SubscriptionInfoInternal::getCellBroadcastSevereThreatAlertEnabled), 156 new AbstractMap.SimpleImmutableEntry<>( 157 SimInfo.COLUMN_CB_AMBER_ALERT, 158 SubscriptionInfoInternal::getCellBroadcastAmberAlertEnabled), 159 new AbstractMap.SimpleImmutableEntry<>( 160 SimInfo.COLUMN_CB_EMERGENCY_ALERT, 161 SubscriptionInfoInternal::getCellBroadcastEmergencyAlertEnabled), 162 new AbstractMap.SimpleImmutableEntry<>( 163 SimInfo.COLUMN_CB_ALERT_SOUND_DURATION, 164 SubscriptionInfoInternal::getCellBroadcastAlertSoundDuration), 165 new AbstractMap.SimpleImmutableEntry<>( 166 SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL, 167 SubscriptionInfoInternal::getCellBroadcastAlertReminderInterval), 168 new AbstractMap.SimpleImmutableEntry<>( 169 SimInfo.COLUMN_CB_ALERT_VIBRATE, 170 SubscriptionInfoInternal::getCellBroadcastAlertVibrationEnabled), 171 new AbstractMap.SimpleImmutableEntry<>( 172 SimInfo.COLUMN_CB_ALERT_SPEECH, 173 SubscriptionInfoInternal::getCellBroadcastAlertSpeechEnabled), 174 new AbstractMap.SimpleImmutableEntry<>( 175 SimInfo.COLUMN_CB_ETWS_TEST_ALERT, 176 SubscriptionInfoInternal::getCellBroadcastEtwsTestAlertEnabled), 177 new AbstractMap.SimpleImmutableEntry<>( 178 SimInfo.COLUMN_CB_CHANNEL_50_ALERT, 179 SubscriptionInfoInternal::getCellBroadcastAreaInfoMessageEnabled), 180 new AbstractMap.SimpleImmutableEntry<>( 181 SimInfo.COLUMN_CB_CMAS_TEST_ALERT, 182 SubscriptionInfoInternal::getCellBroadcastTestAlertEnabled), 183 new AbstractMap.SimpleImmutableEntry<>( 184 SimInfo.COLUMN_CB_OPT_OUT_DIALOG, 185 SubscriptionInfoInternal::getCellBroadcastOptOutDialogEnabled), 186 new AbstractMap.SimpleImmutableEntry<>( 187 SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED, 188 SubscriptionInfoInternal::getEnhanced4GModeEnabled), 189 new AbstractMap.SimpleImmutableEntry<>( 190 SimInfo.COLUMN_VT_IMS_ENABLED, 191 SubscriptionInfoInternal::getVideoTelephonyEnabled), 192 new AbstractMap.SimpleImmutableEntry<>( 193 SimInfo.COLUMN_WFC_IMS_ENABLED, 194 SubscriptionInfoInternal::getWifiCallingEnabled), 195 new AbstractMap.SimpleImmutableEntry<>( 196 SimInfo.COLUMN_WFC_IMS_MODE, 197 SubscriptionInfoInternal::getWifiCallingMode), 198 new AbstractMap.SimpleImmutableEntry<>( 199 SimInfo.COLUMN_WFC_IMS_ROAMING_MODE, 200 SubscriptionInfoInternal::getWifiCallingModeForRoaming), 201 new AbstractMap.SimpleImmutableEntry<>( 202 SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED, 203 SubscriptionInfoInternal::getWifiCallingEnabledForRoaming), 204 new AbstractMap.SimpleImmutableEntry<>( 205 SimInfo.COLUMN_IS_OPPORTUNISTIC, 206 SubscriptionInfoInternal::getOpportunistic), 207 new AbstractMap.SimpleImmutableEntry<>( 208 SimInfo.COLUMN_GROUP_UUID, 209 SubscriptionInfoInternal::getGroupUuid), 210 new AbstractMap.SimpleImmutableEntry<>( 211 SimInfo.COLUMN_ISO_COUNTRY_CODE, 212 SubscriptionInfoInternal::getCountryIso), 213 new AbstractMap.SimpleImmutableEntry<>( 214 SimInfo.COLUMN_CARRIER_ID, 215 SubscriptionInfoInternal::getCarrierId), 216 new AbstractMap.SimpleImmutableEntry<>( 217 SimInfo.COLUMN_PROFILE_CLASS, 218 SubscriptionInfoInternal::getProfileClass), 219 new AbstractMap.SimpleImmutableEntry<>( 220 SimInfo.COLUMN_SUBSCRIPTION_TYPE, 221 SubscriptionInfoInternal::getSubscriptionType), 222 new AbstractMap.SimpleImmutableEntry<>( 223 SimInfo.COLUMN_GROUP_OWNER, 224 SubscriptionInfoInternal::getGroupOwner), 225 new AbstractMap.SimpleImmutableEntry<>( 226 SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES, 227 SubscriptionInfoInternal::getEnabledMobileDataPolicies), 228 new AbstractMap.SimpleImmutableEntry<>( 229 SimInfo.COLUMN_IMSI, 230 SubscriptionInfoInternal::getImsi), 231 new AbstractMap.SimpleImmutableEntry<>( 232 SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED, 233 SubscriptionInfoInternal::getUiccApplicationsEnabled), 234 new AbstractMap.SimpleImmutableEntry<>( 235 SimInfo.COLUMN_IMS_RCS_UCE_ENABLED, 236 SubscriptionInfoInternal::getRcsUceEnabled), 237 new AbstractMap.SimpleImmutableEntry<>( 238 SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED, 239 SubscriptionInfoInternal::getCrossSimCallingEnabled), 240 new AbstractMap.SimpleImmutableEntry<>( 241 SimInfo.COLUMN_RCS_CONFIG, 242 SubscriptionInfoInternal::getRcsConfig), 243 new AbstractMap.SimpleImmutableEntry<>( 244 SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS, 245 SubscriptionInfoInternal::getAllowedNetworkTypesForReasons), 246 new AbstractMap.SimpleImmutableEntry<>( 247 SimInfo.COLUMN_D2D_STATUS_SHARING, 248 SubscriptionInfoInternal::getDeviceToDeviceStatusSharingPreference), 249 new AbstractMap.SimpleImmutableEntry<>( 250 SimInfo.COLUMN_VOIMS_OPT_IN_STATUS, 251 SubscriptionInfoInternal::getVoImsOptInEnabled), 252 new AbstractMap.SimpleImmutableEntry<>( 253 SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS, 254 SubscriptionInfoInternal::getDeviceToDeviceStatusSharingContacts), 255 new AbstractMap.SimpleImmutableEntry<>( 256 SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED, 257 SubscriptionInfoInternal::getNrAdvancedCallingEnabled), 258 new AbstractMap.SimpleImmutableEntry<>( 259 SimInfo.COLUMN_PHONE_NUMBER_SOURCE_CARRIER, 260 SubscriptionInfoInternal::getNumberFromCarrier), 261 new AbstractMap.SimpleImmutableEntry<>( 262 SimInfo.COLUMN_PHONE_NUMBER_SOURCE_IMS, 263 SubscriptionInfoInternal::getNumberFromIms), 264 new AbstractMap.SimpleImmutableEntry<>( 265 SimInfo.COLUMN_PORT_INDEX, 266 SubscriptionInfoInternal::getPortIndex), 267 new AbstractMap.SimpleImmutableEntry<>( 268 SimInfo.COLUMN_USAGE_SETTING, 269 SubscriptionInfoInternal::getUsageSetting), 270 new AbstractMap.SimpleImmutableEntry<>( 271 SimInfo.COLUMN_TP_MESSAGE_REF, 272 SubscriptionInfoInternal::getLastUsedTPMessageReference), 273 new AbstractMap.SimpleImmutableEntry<>( 274 SimInfo.COLUMN_USER_HANDLE, 275 SubscriptionInfoInternal::getUserId), 276 new AbstractMap.SimpleImmutableEntry<>( 277 SimInfo.COLUMN_SATELLITE_ENABLED, 278 SubscriptionInfoInternal::getSatelliteEnabled), 279 new AbstractMap.SimpleImmutableEntry<>( 280 SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER, 281 SubscriptionInfoInternal::getSatelliteAttachEnabledForCarrier), 282 new AbstractMap.SimpleImmutableEntry<>( 283 SimInfo.COLUMN_IS_NTN, 284 SubscriptionInfoInternal::getOnlyNonTerrestrialNetwork), 285 new AbstractMap.SimpleImmutableEntry<>( 286 SimInfo.COLUMN_SERVICE_CAPABILITIES, 287 SubscriptionInfoInternal::getServiceCapabilities), 288 new AbstractMap.SimpleImmutableEntry<>( 289 SimInfo.COLUMN_TRANSFER_STATUS, 290 SubscriptionInfoInternal::getTransferStatus), 291 new AbstractMap.SimpleImmutableEntry<>( 292 SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS, 293 SubscriptionInfoInternal::getSatelliteEntitlementStatus), 294 new AbstractMap.SimpleImmutableEntry<>( 295 SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS, 296 SubscriptionInfoInternal::getSatelliteEntitlementPlmns) 297 ); 298 299 /** 300 * The mapping from columns in {@link android.provider.Telephony.SimInfo} table to 301 * {@link SubscriptionDatabaseManager} setting integer methods. 302 */ 303 private static final Map<String, TriConsumer<SubscriptionDatabaseManager, Integer, Integer>> 304 SUBSCRIPTION_SET_INTEGER_METHOD_MAP = Map.ofEntries( 305 new AbstractMap.SimpleImmutableEntry<>( 306 SimInfo.COLUMN_SIM_SLOT_INDEX, 307 SubscriptionDatabaseManager::setSimSlotIndex), 308 new AbstractMap.SimpleImmutableEntry<>( 309 SimInfo.COLUMN_NAME_SOURCE, 310 SubscriptionDatabaseManager::setDisplayNameSource), 311 new AbstractMap.SimpleImmutableEntry<>( 312 SimInfo.COLUMN_COLOR, 313 SubscriptionDatabaseManager::setIconTint), 314 new AbstractMap.SimpleImmutableEntry<>( 315 SimInfo.COLUMN_DATA_ROAMING, 316 SubscriptionDatabaseManager::setDataRoaming), 317 new AbstractMap.SimpleImmutableEntry<>( 318 SimInfo.COLUMN_IS_EMBEDDED, 319 SubscriptionDatabaseManager::setEmbedded), 320 new AbstractMap.SimpleImmutableEntry<>( 321 SimInfo.COLUMN_IS_REMOVABLE, 322 SubscriptionDatabaseManager::setRemovableEmbedded), 323 new AbstractMap.SimpleImmutableEntry<>( 324 SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT, 325 SubscriptionDatabaseManager::setCellBroadcastExtremeThreatAlertEnabled), 326 new AbstractMap.SimpleImmutableEntry<>( 327 SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT, 328 SubscriptionDatabaseManager::setCellBroadcastSevereThreatAlertEnabled), 329 new AbstractMap.SimpleImmutableEntry<>( 330 SimInfo.COLUMN_CB_AMBER_ALERT, 331 SubscriptionDatabaseManager::setCellBroadcastAmberAlertEnabled), 332 new AbstractMap.SimpleImmutableEntry<>( 333 SimInfo.COLUMN_CB_EMERGENCY_ALERT, 334 SubscriptionDatabaseManager::setCellBroadcastEmergencyAlertEnabled), 335 new AbstractMap.SimpleImmutableEntry<>( 336 SimInfo.COLUMN_CB_ALERT_SOUND_DURATION, 337 SubscriptionDatabaseManager::setCellBroadcastAlertSoundDuration), 338 new AbstractMap.SimpleImmutableEntry<>( 339 SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL, 340 SubscriptionDatabaseManager::setCellBroadcastAlertReminderInterval), 341 new AbstractMap.SimpleImmutableEntry<>( 342 SimInfo.COLUMN_CB_ALERT_VIBRATE, 343 SubscriptionDatabaseManager::setCellBroadcastAlertVibrationEnabled), 344 new AbstractMap.SimpleImmutableEntry<>( 345 SimInfo.COLUMN_CB_ALERT_SPEECH, 346 SubscriptionDatabaseManager::setCellBroadcastAlertSpeechEnabled), 347 new AbstractMap.SimpleImmutableEntry<>( 348 SimInfo.COLUMN_CB_ETWS_TEST_ALERT, 349 SubscriptionDatabaseManager::setCellBroadcastEtwsTestAlertEnabled), 350 new AbstractMap.SimpleImmutableEntry<>( 351 SimInfo.COLUMN_CB_CHANNEL_50_ALERT, 352 SubscriptionDatabaseManager::setCellBroadcastAreaInfoMessageEnabled), 353 new AbstractMap.SimpleImmutableEntry<>( 354 SimInfo.COLUMN_CB_CMAS_TEST_ALERT, 355 SubscriptionDatabaseManager::setCellBroadcastTestAlertEnabled), 356 new AbstractMap.SimpleImmutableEntry<>( 357 SimInfo.COLUMN_CB_OPT_OUT_DIALOG, 358 SubscriptionDatabaseManager::setCellBroadcastOptOutDialogEnabled), 359 new AbstractMap.SimpleImmutableEntry<>( 360 SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED, 361 SubscriptionDatabaseManager::setEnhanced4GModeEnabled), 362 new AbstractMap.SimpleImmutableEntry<>( 363 SimInfo.COLUMN_VT_IMS_ENABLED, 364 SubscriptionDatabaseManager::setVideoTelephonyEnabled), 365 new AbstractMap.SimpleImmutableEntry<>( 366 SimInfo.COLUMN_WFC_IMS_ENABLED, 367 SubscriptionDatabaseManager::setWifiCallingEnabled), 368 new AbstractMap.SimpleImmutableEntry<>( 369 SimInfo.COLUMN_WFC_IMS_MODE, 370 SubscriptionDatabaseManager::setWifiCallingMode), 371 new AbstractMap.SimpleImmutableEntry<>( 372 SimInfo.COLUMN_WFC_IMS_ROAMING_MODE, 373 SubscriptionDatabaseManager::setWifiCallingModeForRoaming), 374 new AbstractMap.SimpleImmutableEntry<>( 375 SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED, 376 SubscriptionDatabaseManager::setWifiCallingEnabledForRoaming), 377 new AbstractMap.SimpleImmutableEntry<>( 378 SimInfo.COLUMN_IS_OPPORTUNISTIC, 379 SubscriptionDatabaseManager::setOpportunistic), 380 new AbstractMap.SimpleImmutableEntry<>( 381 SimInfo.COLUMN_CARRIER_ID, 382 SubscriptionDatabaseManager::setCarrierId), 383 new AbstractMap.SimpleImmutableEntry<>( 384 SimInfo.COLUMN_PROFILE_CLASS, 385 SubscriptionDatabaseManager::setProfileClass), 386 new AbstractMap.SimpleImmutableEntry<>( 387 SimInfo.COLUMN_SUBSCRIPTION_TYPE, 388 SubscriptionDatabaseManager::setSubscriptionType), 389 new AbstractMap.SimpleImmutableEntry<>( 390 SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED, 391 SubscriptionDatabaseManager::setUiccApplicationsEnabled), 392 new AbstractMap.SimpleImmutableEntry<>( 393 SimInfo.COLUMN_IMS_RCS_UCE_ENABLED, 394 SubscriptionDatabaseManager::setRcsUceEnabled), 395 new AbstractMap.SimpleImmutableEntry<>( 396 SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED, 397 SubscriptionDatabaseManager::setCrossSimCallingEnabled), 398 new AbstractMap.SimpleImmutableEntry<>( 399 SimInfo.COLUMN_D2D_STATUS_SHARING, 400 SubscriptionDatabaseManager::setDeviceToDeviceStatusSharingPreference), 401 new AbstractMap.SimpleImmutableEntry<>( 402 SimInfo.COLUMN_VOIMS_OPT_IN_STATUS, 403 SubscriptionDatabaseManager::setVoImsOptInEnabled), 404 new AbstractMap.SimpleImmutableEntry<>( 405 SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED, 406 SubscriptionDatabaseManager::setNrAdvancedCallingEnabled), 407 new AbstractMap.SimpleImmutableEntry<>( 408 SimInfo.COLUMN_PORT_INDEX, 409 SubscriptionDatabaseManager::setPortIndex), 410 new AbstractMap.SimpleImmutableEntry<>( 411 SimInfo.COLUMN_USAGE_SETTING, 412 SubscriptionDatabaseManager::setUsageSetting), 413 new AbstractMap.SimpleImmutableEntry<>( 414 SimInfo.COLUMN_TP_MESSAGE_REF, 415 SubscriptionDatabaseManager::setLastUsedTPMessageReference), 416 new AbstractMap.SimpleImmutableEntry<>( 417 SimInfo.COLUMN_USER_HANDLE, 418 SubscriptionDatabaseManager::setUserId), 419 new AbstractMap.SimpleImmutableEntry<>( 420 SimInfo.COLUMN_SATELLITE_ENABLED, 421 SubscriptionDatabaseManager::setSatelliteEnabled), 422 new AbstractMap.SimpleImmutableEntry<>( 423 SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER, 424 SubscriptionDatabaseManager::setSatelliteAttachEnabledForCarrier), 425 new AbstractMap.SimpleImmutableEntry<>( 426 SimInfo.COLUMN_IS_NTN, 427 SubscriptionDatabaseManager::setNtn), 428 new AbstractMap.SimpleImmutableEntry<>( 429 SimInfo.COLUMN_SERVICE_CAPABILITIES, 430 SubscriptionDatabaseManager::setServiceCapabilities), 431 new AbstractMap.SimpleImmutableEntry<>( 432 SimInfo.COLUMN_TRANSFER_STATUS, 433 SubscriptionDatabaseManager::setTransferStatus), 434 new AbstractMap.SimpleImmutableEntry<>( 435 SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS, 436 SubscriptionDatabaseManager::setSatelliteEntitlementStatus) 437 ); 438 439 /** 440 * The mapping from columns in {@link android.provider.Telephony.SimInfo} table to 441 * {@link SubscriptionDatabaseManager} setting string methods. 442 */ 443 private static final Map<String, TriConsumer<SubscriptionDatabaseManager, Integer, String>> 444 SUBSCRIPTION_SET_STRING_METHOD_MAP = Map.ofEntries( 445 new AbstractMap.SimpleImmutableEntry<>( 446 SimInfo.COLUMN_ICC_ID, 447 SubscriptionDatabaseManager::setIccId), 448 new AbstractMap.SimpleImmutableEntry<>( 449 SimInfo.COLUMN_DISPLAY_NAME, 450 SubscriptionDatabaseManager::setDisplayName), 451 new AbstractMap.SimpleImmutableEntry<>( 452 SimInfo.COLUMN_CARRIER_NAME, 453 SubscriptionDatabaseManager::setCarrierName), 454 new AbstractMap.SimpleImmutableEntry<>( 455 SimInfo.COLUMN_NUMBER, 456 SubscriptionDatabaseManager::setNumber), 457 new AbstractMap.SimpleImmutableEntry<>( 458 SimInfo.COLUMN_MCC_STRING, 459 SubscriptionDatabaseManager::setMcc), 460 new AbstractMap.SimpleImmutableEntry<>( 461 SimInfo.COLUMN_MNC_STRING, 462 SubscriptionDatabaseManager::setMnc), 463 new AbstractMap.SimpleImmutableEntry<>( 464 SimInfo.COLUMN_EHPLMNS, 465 SubscriptionDatabaseManager::setEhplmns), 466 new AbstractMap.SimpleImmutableEntry<>( 467 SimInfo.COLUMN_HPLMNS, 468 SubscriptionDatabaseManager::setHplmns), 469 new AbstractMap.SimpleImmutableEntry<>( 470 SimInfo.COLUMN_CARD_ID, 471 SubscriptionDatabaseManager::setCardString), 472 new AbstractMap.SimpleImmutableEntry<>( 473 SimInfo.COLUMN_GROUP_UUID, 474 SubscriptionDatabaseManager::setGroupUuid), 475 new AbstractMap.SimpleImmutableEntry<>( 476 SimInfo.COLUMN_ISO_COUNTRY_CODE, 477 SubscriptionDatabaseManager::setCountryIso), 478 new AbstractMap.SimpleImmutableEntry<>( 479 SimInfo.COLUMN_GROUP_OWNER, 480 SubscriptionDatabaseManager::setGroupOwner), 481 new AbstractMap.SimpleImmutableEntry<>( 482 SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES, 483 SubscriptionDatabaseManager::setEnabledMobileDataPolicies), 484 new AbstractMap.SimpleImmutableEntry<>( 485 SimInfo.COLUMN_IMSI, 486 SubscriptionDatabaseManager::setImsi), 487 new AbstractMap.SimpleImmutableEntry<>( 488 SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS, 489 SubscriptionDatabaseManager::setAllowedNetworkTypesForReasons), 490 new AbstractMap.SimpleImmutableEntry<>( 491 SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS, 492 SubscriptionDatabaseManager::setDeviceToDeviceStatusSharingContacts), 493 new AbstractMap.SimpleImmutableEntry<>( 494 SimInfo.COLUMN_PHONE_NUMBER_SOURCE_CARRIER, 495 SubscriptionDatabaseManager::setNumberFromCarrier), 496 new AbstractMap.SimpleImmutableEntry<>( 497 SimInfo.COLUMN_PHONE_NUMBER_SOURCE_IMS, 498 SubscriptionDatabaseManager::setNumberFromIms), 499 new AbstractMap.SimpleImmutableEntry<>( 500 SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS, 501 SubscriptionDatabaseManager::setSatelliteEntitlementPlmns) 502 ); 503 504 /** 505 * The mapping from columns in {@link android.provider.Telephony.SimInfo} table to 506 * {@link SubscriptionDatabaseManager} setting byte array methods. 507 */ 508 private static final Map<String, TriConsumer<SubscriptionDatabaseManager, Integer, byte[]>> 509 SUBSCRIPTION_SET_BYTE_ARRAY_METHOD_MAP = Map.ofEntries( 510 new AbstractMap.SimpleImmutableEntry<>( 511 SimInfo.COLUMN_ACCESS_RULES, 512 SubscriptionDatabaseManager::setNativeAccessRules), 513 new AbstractMap.SimpleImmutableEntry<>( 514 SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS, 515 SubscriptionDatabaseManager::setCarrierConfigAccessRules), 516 new AbstractMap.SimpleImmutableEntry<>( 517 SimInfo.COLUMN_RCS_CONFIG, 518 SubscriptionDatabaseManager::setRcsConfig) 519 ); 520 521 /** 522 * The columns that should be in-sync between the subscriptions in the same group. Changing 523 * the value in those fields will automatically apply to the rest of the subscriptions in the 524 * group. 525 * 526 * @see SubscriptionManager#getSubscriptionsInGroup(ParcelUuid) 527 */ 528 private static final Set<String> GROUP_SHARING_COLUMNS = Set.of( 529 SimInfo.COLUMN_DISPLAY_NAME, 530 SimInfo.COLUMN_NAME_SOURCE, 531 SimInfo.COLUMN_COLOR, 532 SimInfo.COLUMN_DATA_ROAMING, 533 SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED, 534 SimInfo.COLUMN_VT_IMS_ENABLED, 535 SimInfo.COLUMN_WFC_IMS_ENABLED, 536 SimInfo.COLUMN_WFC_IMS_MODE, 537 SimInfo.COLUMN_WFC_IMS_ROAMING_MODE, 538 SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED, 539 SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES, 540 SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED, 541 SimInfo.COLUMN_IMS_RCS_UCE_ENABLED, 542 SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED, 543 SimInfo.COLUMN_RCS_CONFIG, 544 SimInfo.COLUMN_D2D_STATUS_SHARING, 545 SimInfo.COLUMN_VOIMS_OPT_IN_STATUS, 546 SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS, 547 SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED, 548 SimInfo.COLUMN_USER_HANDLE, 549 SimInfo.COLUMN_SATELLITE_ENABLED, 550 SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER 551 ); 552 553 /** 554 * The deprecated columns that do not have corresponding set methods in 555 * {@link SubscriptionDatabaseManager}. 556 */ 557 private static final Set<String> DEPRECATED_DATABASE_COLUMNS = Set.of( 558 SimInfo.COLUMN_DISPLAY_NUMBER_FORMAT, 559 SimInfo.COLUMN_MCC, 560 SimInfo.COLUMN_MNC, 561 SimInfo.COLUMN_SIM_PROVISIONING_STATUS, 562 SimInfo.COLUMN_IS_METERED, 563 SimInfo.COLUMN_DATA_ENABLED_OVERRIDE_RULES, 564 SimInfo.COLUMN_ALLOWED_NETWORK_TYPES 565 ); 566 567 /** The context */ 568 @NonNull 569 private final Context mContext; 570 571 /** The feature flags */ 572 @NonNull 573 private final FeatureFlags mFeatureFlags; 574 575 /** The callback used for passing events back to {@link SubscriptionManagerService}. */ 576 @NonNull 577 private final SubscriptionDatabaseManagerCallback mCallback; 578 579 /** UICC controller */ 580 private final UiccController mUiccController; 581 582 /** 583 * The read/write lock to protect the entire database access. Using a Re-entrant read lock as 584 * much more read requests are expected than the write requests. All the access to 585 * {@link #mAllSubscriptionInfoInternalCache} needs to be protected by this lock. 586 */ 587 @NonNull 588 private final ReadWriteLock mReadWriteLock = new ReentrantReadWriteLock(); 589 590 /** Indicating whether access the database asynchronously or not. */ 591 private final boolean mAsyncMode; 592 593 /** Local log for most important debug messages. */ 594 @NonNull 595 private final LocalLog mLocalLog = new LocalLog(128); 596 597 /** 598 * The entire subscription database, including subscriptions from inserted, previously inserted 599 * SIMs. This is the full memory cache of the subscription database. The key is the subscription 600 * id. Note all the access to this map needs to be protected by the re-entrant lock 601 * {@link #mReadWriteLock}. 602 * 603 * @see SimInfo 604 */ 605 @GuardedBy("mReadWriteLock") 606 @NonNull 607 private final Map<Integer, SubscriptionInfoInternal> mAllSubscriptionInfoInternalCache = 608 new HashMap<>(16); 609 610 /** Whether database has been initialized after boot up. */ 611 @GuardedBy("this") 612 private boolean mDatabaseInitialized = false; 613 614 /** 615 * This is the callback used for listening events from {@link SubscriptionDatabaseManager}. 616 */ 617 public abstract static class SubscriptionDatabaseManagerCallback { 618 /** The executor of the callback. */ 619 private final @NonNull Executor mExecutor; 620 621 /** 622 * Constructor 623 * 624 * @param executor The executor of the callback. 625 */ SubscriptionDatabaseManagerCallback(@onNull @allbackExecutor Executor executor)626 public SubscriptionDatabaseManagerCallback(@NonNull @CallbackExecutor Executor executor) { 627 mExecutor = executor; 628 } 629 630 /** 631 * @return The executor of the callback. 632 */ 633 @VisibleForTesting getExecutor()634 public @NonNull Executor getExecutor() { 635 return mExecutor; 636 } 637 638 /** 639 * Invoke the callback from executor. 640 * 641 * @param runnable The callback method to invoke. 642 */ invokeFromExecutor(@onNull Runnable runnable)643 public void invokeFromExecutor(@NonNull Runnable runnable) { 644 mExecutor.execute(runnable); 645 } 646 647 /** 648 * Called when database has been initialized. 649 */ onInitialized()650 public abstract void onInitialized(); 651 652 /** 653 * Called when subscription changed. 654 * 655 * @param subId The subscription id. 656 */ onSubscriptionChanged(int subId)657 public abstract void onSubscriptionChanged(int subId); 658 } 659 660 /** 661 * The constructor. 662 * 663 * @param context The context. 664 * @param looper Looper for the handler. 665 * @param featureFlags The feature flags. 666 * @param callback Subscription database callback. 667 */ SubscriptionDatabaseManager(@onNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags, @NonNull SubscriptionDatabaseManagerCallback callback)668 public SubscriptionDatabaseManager(@NonNull Context context, @NonNull Looper looper, 669 @NonNull FeatureFlags featureFlags, 670 @NonNull SubscriptionDatabaseManagerCallback callback) { 671 super(looper); 672 log("Created SubscriptionDatabaseManager."); 673 mContext = context; 674 mCallback = callback; 675 mUiccController = UiccController.getInstance(); 676 mAsyncMode = mContext.getResources().getBoolean( 677 com.android.internal.R.bool.config_subscription_database_async_update); 678 mFeatureFlags = featureFlags; 679 initializeDatabase(); 680 } 681 682 /** 683 * Helper method to get specific field from {@link SubscriptionInfoInternal} by the database 684 * column name. {@link SubscriptionInfoInternal} represent one single record in the 685 * {@link SimInfo} table. So every column has a corresponding get method in 686 * {@link SubscriptionInfoInternal} (except for unused or deprecated columns). 687 * 688 * @param subInfo The subscription info. 689 * @param columnName The database column name. 690 * 691 * @return The corresponding value from {@link SubscriptionInfoInternal}. 692 * 693 * @throws IllegalArgumentException if {@code columnName} is invalid. 694 * 695 * @see android.provider.Telephony.SimInfo for all the columns. 696 */ 697 @NonNull getSubscriptionInfoFieldByColumnName( @onNull SubscriptionInfoInternal subInfo, @NonNull String columnName)698 private static Object getSubscriptionInfoFieldByColumnName( 699 @NonNull SubscriptionInfoInternal subInfo, @NonNull String columnName) { 700 if (SUBSCRIPTION_GET_METHOD_MAP.containsKey(columnName)) { 701 return SUBSCRIPTION_GET_METHOD_MAP.get(columnName).apply(subInfo); 702 } 703 throw new IllegalArgumentException("Invalid column name " + columnName); 704 } 705 706 /** 707 * Get a specific field from the subscription database by {@code subId} and {@code columnName}. 708 * 709 * @param subId The subscription id. 710 * @param columnName The database column name. 711 * 712 * @return The value from subscription database. 713 * 714 * @throws IllegalArgumentException if {@code subId} or {@code columnName} is invalid. 715 * 716 * @see android.provider.Telephony.SimInfo for all the columns. 717 */ 718 @NonNull getSubscriptionProperty(int subId, @NonNull String columnName)719 public Object getSubscriptionProperty(int subId, @NonNull String columnName) { 720 SubscriptionInfoInternal subInfo = getSubscriptionInfoInternal(subId); 721 if (subInfo == null) { 722 throw new IllegalArgumentException("getSubscriptionProperty: Invalid subId " + subId 723 + ", columnName=" + columnName); 724 } 725 726 return getSubscriptionInfoFieldByColumnName(subInfo, columnName); 727 } 728 729 /** 730 * Set a field in the subscription database. Note not all fields are supported. 731 * 732 * @param subId Subscription Id of Subscription. 733 * @param columnName Column name in the database. Note not all fields are supported. 734 * @param value Value to store in the database. 735 * 736 * @throws IllegalArgumentException if {@code subId} or {@code columnName} is invalid, or 737 * {@code value} cannot be converted to the corresponding database column format. 738 * @throws NumberFormatException if a string value cannot be converted to integer. 739 * @throws ClassCastException if {@code value} cannot be casted to the required type. 740 * 741 * @see android.provider.Telephony.SimInfo for all the columns. 742 */ setSubscriptionProperty(int subId, @NonNull String columnName, @NonNull Object value)743 public void setSubscriptionProperty(int subId, @NonNull String columnName, 744 @NonNull Object value) { 745 if (SUBSCRIPTION_SET_INTEGER_METHOD_MAP.containsKey(columnName)) { 746 // For integer type columns, accepting both integer and string that can be converted to 747 // integer. 748 int intValue; 749 if (value instanceof String) { 750 intValue = Integer.parseInt((String) value); 751 } else if (value instanceof Integer) { 752 intValue = (int) value; 753 } else { 754 throw new ClassCastException("columnName=" + columnName + ", cannot cast " 755 + value.getClass() + " to integer."); 756 } 757 SUBSCRIPTION_SET_INTEGER_METHOD_MAP.get(columnName).accept(this, subId, intValue); 758 } else if (SUBSCRIPTION_SET_STRING_METHOD_MAP.containsKey(columnName)) { 759 // For string type columns. Will throw exception if value is not string type. 760 SUBSCRIPTION_SET_STRING_METHOD_MAP.get(columnName).accept(this, subId, (String) value); 761 } else if (SUBSCRIPTION_SET_BYTE_ARRAY_METHOD_MAP.containsKey(columnName)) { 762 // For byte array type columns, accepting both byte[] and string that can be converted 763 // to byte[] using base 64 encoding/decoding. 764 byte[] byteArrayValue; 765 if (value instanceof String) { 766 byteArrayValue = Base64.decode((String) value, Base64.DEFAULT); 767 } else if (value instanceof byte[]) { 768 byteArrayValue = (byte[]) value; 769 } else { 770 throw new ClassCastException("columnName=" + columnName + ", cannot cast " 771 + value.getClass() + " to byte[]."); 772 } 773 SUBSCRIPTION_SET_BYTE_ARRAY_METHOD_MAP.get(columnName).accept( 774 this, subId, byteArrayValue); 775 } else { 776 throw new IllegalArgumentException("Does not support set " + columnName + "."); 777 } 778 } 779 780 /** 781 * Comparing the old/new {@link SubscriptionInfoInternal} and create content values for database 782 * update. If any field in the new subscription info is different from the old one, then each 783 * delta will be added into the {@link ContentValues}. 784 * 785 * @param oldSubInfo The old {@link SubscriptionInfoInternal}. 786 * @param newSubInfo The new {@link SubscriptionInfoInternal}. 787 * 788 * @return The delta content values for database update. 789 */ 790 @NonNull createDeltaContentValues(@ullable SubscriptionInfoInternal oldSubInfo, @NonNull SubscriptionInfoInternal newSubInfo)791 private ContentValues createDeltaContentValues(@Nullable SubscriptionInfoInternal oldSubInfo, 792 @NonNull SubscriptionInfoInternal newSubInfo) { 793 ContentValues deltaContentValues = new ContentValues(); 794 795 for (String columnName : Telephony.SimInfo.getAllColumns()) { 796 if (DEPRECATED_DATABASE_COLUMNS.contains(columnName)) continue; 797 // subId is generated by the database. Cannot be updated. 798 if (columnName.equals(SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID)) continue; 799 Object newValue = getSubscriptionInfoFieldByColumnName(newSubInfo, columnName); 800 if (newValue != null) { 801 Object oldValue = null; 802 if (oldSubInfo != null) { 803 oldValue = getSubscriptionInfoFieldByColumnName(oldSubInfo, columnName); 804 } 805 // Some columns need special handling. We need to convert them into a format that 806 // is accepted by the database. 807 if (!Objects.equals(oldValue, newValue)) { 808 deltaContentValues.putObject(columnName, newValue); 809 } 810 } 811 } 812 return deltaContentValues; 813 } 814 815 /** 816 * Synchronously insert a new record into the database. This operation is synchronous because 817 * we need to convert the inserted row index into the subscription id. 818 * 819 * @param contentValues The fields of the subscription to be inserted into the database. 820 * 821 * @return The row index of the new record. {@link #INVALID_ROW_INDEX} if insertion failed. 822 */ insertNewRecordIntoDatabaseSync(@onNull ContentValues contentValues)823 private int insertNewRecordIntoDatabaseSync(@NonNull ContentValues contentValues) { 824 Objects.requireNonNull(contentValues); 825 Uri uri = mContext.getContentResolver().insert(SimInfo.CONTENT_URI, contentValues); 826 if (uri != null && uri.getLastPathSegment() != null) { 827 int subId = Integer.parseInt(uri.getLastPathSegment()); 828 if (SubscriptionManager.isValidSubscriptionId(subId)) { 829 logv("insertNewRecordIntoDatabaseSync: contentValues=" + contentValues); 830 logl("insertNewRecordIntoDatabaseSync: Successfully added subscription. subId=" 831 + uri.getLastPathSegment()); 832 return subId; 833 } 834 } 835 836 logel("insertNewRecordIntoDatabaseSync: Failed to insert subscription into database. " 837 + "contentValues=" + contentValues); 838 return INVALID_ROW_INDEX; 839 } 840 841 /** 842 * Insert a new subscription info. The subscription info must have subscription id 843 * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}. Note this is a slow method, so be 844 * cautious to call this method. 845 * 846 * @param subInfo The subscription info to update. 847 * 848 * @return The new subscription id. {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} (-1) if 849 * insertion fails. 850 */ insertSubscriptionInfo(@onNull SubscriptionInfoInternal subInfo)851 public int insertSubscriptionInfo(@NonNull SubscriptionInfoInternal subInfo) { 852 Objects.requireNonNull(subInfo); 853 // A new subscription to be inserted must have invalid subscription id. 854 if (SubscriptionManager.isValidSubscriptionId(subInfo.getSubscriptionId())) { 855 throw new RuntimeException("insertSubscriptionInfo: Not a new subscription to " 856 + "insert. subInfo=" + subInfo); 857 } 858 859 synchronized (this) { 860 if (!mDatabaseInitialized) { 861 throw new IllegalStateException( 862 "Database has not been initialized. Can't insert new " 863 + "record at this point."); 864 } 865 } 866 867 int subId; 868 // Grab the write lock so no other threads can read or write the cache. 869 mReadWriteLock.writeLock().lock(); 870 try { 871 // Synchronously insert into the database. Note this should be the only synchronous 872 // write operation performed by the subscription database manager. The reason is that 873 // we need to get the sub id for cache update. 874 subId = insertNewRecordIntoDatabaseSync(createDeltaContentValues(null, subInfo)); 875 if (subId > 0) { 876 mAllSubscriptionInfoInternalCache.put(subId, new SubscriptionInfoInternal 877 .Builder(subInfo) 878 .setId(subId).build()); 879 } else { 880 logel("insertSubscriptionInfo: Failed to insert a new subscription. subInfo=" 881 + subInfo); 882 } 883 } finally { 884 mReadWriteLock.writeLock().unlock(); 885 } 886 887 mCallback.invokeFromExecutor(() -> mCallback.onSubscriptionChanged(subId)); 888 return subId; 889 } 890 891 /** 892 * Remove a subscription record from the database. 893 * 894 * @param subId The subscription id of the subscription to be deleted. 895 * 896 * @throws IllegalArgumentException If {@code subId} is invalid. 897 */ removeSubscriptionInfo(int subId)898 public void removeSubscriptionInfo(int subId) { 899 if (!mAllSubscriptionInfoInternalCache.containsKey(subId)) { 900 throw new IllegalArgumentException("subId " + subId + " is invalid."); 901 } 902 903 mReadWriteLock.writeLock().lock(); 904 try { 905 if (mContext.getContentResolver().delete(SimInfo.CONTENT_URI, 906 SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=?", 907 new String[]{Integer.toString(subId)}) > 0) { 908 mAllSubscriptionInfoInternalCache.remove(subId); 909 } else { 910 logel("Failed to remove subscription with subId=" + subId); 911 } 912 } finally { 913 mReadWriteLock.writeLock().unlock(); 914 } 915 916 mCallback.invokeFromExecutor(() -> mCallback.onSubscriptionChanged(subId)); 917 } 918 919 /** 920 * Update a subscription in the database (synchronously or asynchronously). 921 * 922 * @param subId The subscription id of the subscription to be updated. 923 * @param contentValues The fields to be update. 924 * 925 * @return The number of rows updated. Note if the database is configured as asynchronously 926 * update, then this will be always 1. 927 */ updateDatabase(int subId, @NonNull ContentValues contentValues)928 private int updateDatabase(int subId, @NonNull ContentValues contentValues) { 929 logv("updateDatabase: prepare to update sub " + subId); 930 931 synchronized (this) { 932 if (!mDatabaseInitialized) { 933 logel("updateDatabase: Database has not been initialized. Can't update database at " 934 + "this point. contentValues=" + contentValues); 935 return 0; 936 } 937 } 938 939 if (mAsyncMode) { 940 // Perform the update in the handler thread asynchronously. 941 post(() -> { 942 mContext.getContentResolver().update(Uri.withAppendedPath( 943 SimInfo.CONTENT_URI, String.valueOf(subId)), contentValues, null, null); 944 logv("updateDatabase: async updated subscription in the database." 945 + " subId=" + subId + ", contentValues= " + contentValues.getValues()); 946 }); 947 return 1; 948 } else { 949 logv("updateDatabase: sync updated subscription in the database." 950 + " subId=" + subId + ", contentValues= " + contentValues.getValues()); 951 952 return mContext.getContentResolver().update(Uri.withAppendedPath( 953 SimInfo.CONTENT_URI, String.valueOf(subId)), contentValues, null, null); 954 } 955 } 956 957 /** 958 * Update a certain field of subscription in the database. Also update the subscription cache 959 * {@link #mAllSubscriptionInfoInternalCache}. 960 * 961 * @param subId The subscription id. 962 * @param columnName The database column name from the database table {@link SimInfo}. 963 * @param newValue The new value to update the subscription info cache 964 * {@link #mAllSubscriptionInfoInternalCache}. 965 * @param builderSetMethod The {@link SubscriptionInfo.Builder} method to set a specific field 966 * when constructing the new {@link SubscriptionInfo}. This should be one of the 967 * SubscriptionInfoInternal.Builder.setXxxx method. 968 * @param <T> The type of newValue for subscription cache update. 969 * 970 * @throws IllegalArgumentException if the subscription does not exist. 971 */ writeDatabaseAndCacheHelper(int subId, @NonNull String columnName, @Nullable T newValue, BiFunction<SubscriptionInfoInternal.Builder, T, SubscriptionInfoInternal.Builder> builderSetMethod)972 private <T> void writeDatabaseAndCacheHelper(int subId, @NonNull String columnName, 973 @Nullable T newValue, 974 BiFunction<SubscriptionInfoInternal.Builder, T, SubscriptionInfoInternal.Builder> 975 builderSetMethod) { 976 ContentValues contentValues = new ContentValues(); 977 978 // Grab the write lock so no other threads can read or write the cache. 979 mReadWriteLock.writeLock().lock(); 980 try { 981 final SubscriptionInfoInternal oldSubInfo = 982 mAllSubscriptionInfoInternalCache.get(subId); 983 if (oldSubInfo == null) { 984 logel("Subscription doesn't exist. subId=" + subId + ", columnName=" + columnName); 985 throw new IllegalArgumentException("Subscription doesn't exist. subId=" + subId 986 + ", columnName=" + columnName); 987 } 988 989 // Check if writing this field should automatically write to the rest of subscriptions 990 // in the same group. 991 final boolean syncToGroup = GROUP_SHARING_COLUMNS.contains(columnName); 992 993 mAllSubscriptionInfoInternalCache.forEach((id, subInfo) -> { 994 if (id == subId || (syncToGroup && !oldSubInfo.getGroupUuid().isEmpty() 995 && oldSubInfo.getGroupUuid().equals(subInfo.getGroupUuid()))) { 996 // Check if the new value is different from the old value in the cache. 997 if (!Objects.equals(getSubscriptionInfoFieldByColumnName(subInfo, columnName), 998 newValue)) { 999 logv("writeDatabaseAndCacheHelper: subId=" + subId + ",columnName=" 1000 + columnName + ", newValue=" + newValue); 1001 // If the value is different, then we need to update the cache. Since all 1002 // fields in SubscriptionInfo are final, we need to create a new 1003 // SubscriptionInfo. 1004 SubscriptionInfoInternal.Builder builder = new SubscriptionInfoInternal 1005 .Builder(subInfo); 1006 1007 // Apply the new value to the builder. This line is equivalent to 1008 // builder.setXxxxxx(newValue); 1009 builder = builderSetMethod.apply(builder, newValue); 1010 1011 // Prepare the content value for update. 1012 contentValues.putObject(columnName, newValue); 1013 if (updateDatabase(id, contentValues) > 0) { 1014 // Update the subscription database cache. 1015 mAllSubscriptionInfoInternalCache.put(id, builder.build()); 1016 mCallback.invokeFromExecutor(() 1017 -> mCallback.onSubscriptionChanged(subId)); 1018 } 1019 } 1020 } 1021 }); 1022 } finally { 1023 mReadWriteLock.writeLock().unlock(); 1024 } 1025 } 1026 1027 /** 1028 * Update the database with the {@link SubscriptionInfoInternal}, and also update the cache. 1029 * 1030 * @param newSubInfo The new {@link SubscriptionInfoInternal}. 1031 * 1032 * @throws IllegalArgumentException if the subscription does not exist. 1033 */ updateSubscription(@onNull SubscriptionInfoInternal newSubInfo)1034 public void updateSubscription(@NonNull SubscriptionInfoInternal newSubInfo) { 1035 Objects.requireNonNull(newSubInfo); 1036 1037 // Grab the write lock so no other threads can read or write the cache. 1038 mReadWriteLock.writeLock().lock(); 1039 try { 1040 int subId = newSubInfo.getSubscriptionId(); 1041 SubscriptionInfoInternal oldSubInfo = mAllSubscriptionInfoInternalCache.get( 1042 newSubInfo.getSubscriptionId()); 1043 if (oldSubInfo == null) { 1044 throw new IllegalArgumentException("updateSubscription: subscription does not " 1045 + "exist. subId=" + subId); 1046 } 1047 if (oldSubInfo.equalsDbItemsOnly(newSubInfo)) return; 1048 1049 if (updateDatabase(subId, createDeltaContentValues(oldSubInfo, newSubInfo)) > 0) { 1050 mAllSubscriptionInfoInternalCache.put(subId, newSubInfo); 1051 mCallback.invokeFromExecutor(() -> mCallback.onSubscriptionChanged(subId)); 1052 } 1053 } finally { 1054 mReadWriteLock.writeLock().unlock(); 1055 } 1056 } 1057 1058 /** 1059 * Set the ICCID of the SIM that is associated with the subscription. 1060 * 1061 * @param subId Subscription id. 1062 * @param iccId The ICCID of the SIM that is associated with this subscription. 1063 * 1064 * @throws IllegalArgumentException if the subscription does not exist. 1065 */ setIccId(int subId, @NonNull String iccId)1066 public void setIccId(int subId, @NonNull String iccId) { 1067 Objects.requireNonNull(iccId); 1068 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_ICC_ID, iccId, 1069 SubscriptionInfoInternal.Builder::setIccId); 1070 } 1071 1072 /** 1073 * Set the SIM index of the slot that currently contains the subscription. Set to 1074 * {@link SubscriptionManager#INVALID_SIM_SLOT_INDEX} if the subscription is inactive. 1075 * 1076 * @param subId Subscription id. 1077 * @param simSlotIndex The SIM slot index. 1078 * 1079 * @throws IllegalArgumentException if the subscription does not exist. 1080 */ setSimSlotIndex(int subId, int simSlotIndex)1081 public void setSimSlotIndex(int subId, int simSlotIndex) { 1082 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_SIM_SLOT_INDEX, simSlotIndex, 1083 SubscriptionInfoInternal.Builder::setSimSlotIndex); 1084 } 1085 1086 /** 1087 * Set the name displayed to the user that identifies this subscription. This name is used 1088 * in Settings page and can be renamed by the user. 1089 * 1090 * @param subId Subscription id. 1091 * @param displayName The display name. 1092 * 1093 * @throws IllegalArgumentException if the subscription does not exist. 1094 */ setDisplayName(int subId, @NonNull String displayName)1095 public void setDisplayName(int subId, @NonNull String displayName) { 1096 Objects.requireNonNull(displayName); 1097 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_DISPLAY_NAME, displayName, 1098 SubscriptionInfoInternal.Builder::setDisplayName); 1099 } 1100 1101 /** 1102 * Set the name displayed to the user that identifies subscription provider name. This name 1103 * is the SPN displayed in status bar and many other places. Can't be renamed by the user. 1104 * 1105 * @param subId Subscription id. 1106 * @param carrierName The carrier name. 1107 * 1108 * @throws IllegalArgumentException if the subscription does not exist. 1109 */ setCarrierName(int subId, @NonNull String carrierName)1110 public void setCarrierName(int subId, @NonNull String carrierName) { 1111 Objects.requireNonNull(carrierName); 1112 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CARRIER_NAME, carrierName, 1113 SubscriptionInfoInternal.Builder::setCarrierName); 1114 } 1115 1116 /** 1117 * Set the source of the display name. 1118 * 1119 * @param subId Subscription id. 1120 * @param displayNameSource The source of the display name. 1121 * 1122 * @throws IllegalArgumentException if the subscription does not exist. 1123 * 1124 * @see SubscriptionInfo#getDisplayName() 1125 */ setDisplayNameSource(int subId, @SimDisplayNameSource int displayNameSource)1126 public void setDisplayNameSource(int subId, @SimDisplayNameSource int displayNameSource) { 1127 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_NAME_SOURCE, displayNameSource, 1128 SubscriptionInfoInternal.Builder::setDisplayNameSource); 1129 } 1130 1131 /** 1132 * Set the color to be used for tinting the icon when displaying to the user. 1133 * 1134 * @param subId Subscription id. 1135 * @param iconTint The color to be used for tinting the icon when displaying to the user. 1136 * 1137 * @throws IllegalArgumentException if the subscription does not exist. 1138 */ setIconTint(int subId, @ColorInt int iconTint)1139 public void setIconTint(int subId, @ColorInt int iconTint) { 1140 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_COLOR, iconTint, 1141 SubscriptionInfoInternal.Builder::setIconTint); 1142 } 1143 1144 /** 1145 * Set the number presented to the user identify this subscription. 1146 * 1147 * @param subId Subscription id. 1148 * @param number the number presented to the user identify this subscription. 1149 * 1150 * @throws IllegalArgumentException if the subscription does not exist. 1151 */ setNumber(int subId, @NonNull String number)1152 public void setNumber(int subId, @NonNull String number) { 1153 Objects.requireNonNull(number); 1154 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_NUMBER, number, 1155 SubscriptionInfoInternal.Builder::setNumber); 1156 } 1157 1158 /** 1159 * Set whether user enables data roaming for this subscription or not. 1160 * 1161 * @param subId Subscription id. 1162 * @param dataRoaming Data roaming mode. Either 1163 * {@link SubscriptionManager#DATA_ROAMING_ENABLE} or 1164 * {@link SubscriptionManager#DATA_ROAMING_DISABLE} 1165 * 1166 * @throws IllegalArgumentException if the subscription does not exist. 1167 */ setDataRoaming(int subId, @DataRoamingMode int dataRoaming)1168 public void setDataRoaming(int subId, @DataRoamingMode int dataRoaming) { 1169 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_DATA_ROAMING, dataRoaming, 1170 SubscriptionInfoInternal.Builder::setDataRoaming); 1171 } 1172 1173 /** 1174 * Set the mobile country code. 1175 * 1176 * @param subId Subscription id. 1177 * @param mcc The mobile country code. 1178 * 1179 * @throws IllegalArgumentException if the subscription does not exist. 1180 */ setMcc(int subId, @NonNull String mcc)1181 public void setMcc(int subId, @NonNull String mcc) { 1182 Objects.requireNonNull(mcc); 1183 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_MCC_STRING, mcc, 1184 SubscriptionInfoInternal.Builder::setMcc); 1185 } 1186 1187 /** 1188 * Set the mobile network code. 1189 * 1190 * @param subId Subscription id. 1191 * @param mnc Mobile network code. 1192 * 1193 * @throws IllegalArgumentException if the subscription does not exist. 1194 */ setMnc(int subId, @NonNull String mnc)1195 public void setMnc(int subId, @NonNull String mnc) { 1196 Objects.requireNonNull(mnc); 1197 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_MNC_STRING, mnc, 1198 SubscriptionInfoInternal.Builder::setMnc); 1199 } 1200 1201 /** 1202 * Set EHPLMNs associated with the subscription. 1203 * 1204 * @param subId Subscription id. 1205 * @param ehplmns EHPLMNs associated with the subscription. 1206 * 1207 * @throws IllegalArgumentException if the subscription does not exist. 1208 */ setEhplmns(int subId, @NonNull String[] ehplmns)1209 public void setEhplmns(int subId, @NonNull String[] ehplmns) { 1210 Objects.requireNonNull(ehplmns); 1211 setEhplmns(subId, Arrays.stream(ehplmns) 1212 .filter(Predicate.not(TextUtils::isEmpty)) 1213 .collect(Collectors.joining(","))); 1214 } 1215 1216 /** 1217 * Set EHPLMNs associated with the subscription. 1218 * 1219 * @param subId Subscription id. 1220 * @param ehplmns EHPLMNs associated with the subscription. 1221 * 1222 * @throws IllegalArgumentException if the subscription does not exist. 1223 */ setEhplmns(int subId, @NonNull String ehplmns)1224 public void setEhplmns(int subId, @NonNull String ehplmns) { 1225 Objects.requireNonNull(ehplmns); 1226 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_EHPLMNS, ehplmns, 1227 SubscriptionInfoInternal.Builder::setEhplmns); 1228 } 1229 1230 /** 1231 * Set HPLMNs associated with the subscription. 1232 * 1233 * @param subId Subscription id. 1234 * @param hplmns HPLMNs associated with the subscription. 1235 * 1236 * @throws IllegalArgumentException if the subscription does not exist. 1237 */ setHplmns(int subId, @NonNull String[] hplmns)1238 public void setHplmns(int subId, @NonNull String[] hplmns) { 1239 Objects.requireNonNull(hplmns); 1240 setHplmns(subId, Arrays.stream(hplmns) 1241 .filter(Predicate.not(TextUtils::isEmpty)) 1242 .collect(Collectors.joining(","))); 1243 } 1244 1245 /** 1246 * Set HPLMNs associated with the subscription. 1247 * 1248 * @param subId Subscription id. 1249 * @param hplmns HPLMNs associated with the subscription. 1250 * 1251 * @throws IllegalArgumentException if the subscription does not exist. 1252 */ setHplmns(int subId, @NonNull String hplmns)1253 public void setHplmns(int subId, @NonNull String hplmns) { 1254 Objects.requireNonNull(hplmns); 1255 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_HPLMNS, hplmns, 1256 SubscriptionInfoInternal.Builder::setHplmns); 1257 } 1258 1259 /** 1260 * Set whether the subscription is from eSIM or not. 1261 * 1262 * @param subId Subscription id. 1263 * @param isEmbedded if the subscription is from eSIM. 1264 * 1265 * @throws IllegalArgumentException if the subscription does not exist. 1266 */ setEmbedded(int subId, int isEmbedded)1267 public void setEmbedded(int subId, int isEmbedded) { 1268 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_IS_EMBEDDED, isEmbedded, 1269 SubscriptionInfoInternal.Builder::setEmbedded); 1270 } 1271 1272 /** 1273 * Set whether the subscription is from eSIM or not. 1274 * 1275 * @param subId Subscription id. 1276 * @param isEmbedded {@code true} if the subscription is from eSIM. 1277 * 1278 * @throws IllegalArgumentException if the subscription does not exist. 1279 */ setEmbedded(int subId, boolean isEmbedded)1280 public void setEmbedded(int subId, boolean isEmbedded) { 1281 setEmbedded(subId, isEmbedded ? 1 : 0); 1282 } 1283 1284 /** 1285 * Set the card string of the SIM card. This is usually the ICCID or EID. 1286 * 1287 * @param subId Subscription id. 1288 * @param cardString The card string of the SIM card. 1289 * 1290 * @throws IllegalArgumentException if the subscription does not exist. 1291 * 1292 * @see SubscriptionInfo#getCardString() 1293 */ setCardString(int subId, @NonNull String cardString)1294 public void setCardString(int subId, @NonNull String cardString) { 1295 Objects.requireNonNull(cardString); 1296 // Also update the public card id. 1297 setCardId(subId, mUiccController.convertToPublicCardId(cardString)); 1298 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CARD_ID, cardString, 1299 SubscriptionInfoInternal.Builder::setCardString); 1300 } 1301 1302 /** 1303 * Set the card id. This is the non-PII card id converted from 1304 * {@link SubscriptionInfoInternal#getCardString()}. This field only exists in 1305 * {@link SubscriptionInfo}, but not the database. 1306 * 1307 * @param subId Subscription id. 1308 * @param cardId The card id. 1309 * 1310 * @throws IllegalArgumentException if the subscription does not exist. 1311 */ setCardId(int subId, int cardId)1312 public void setCardId(int subId, int cardId) { 1313 // card id does not have a corresponding SimInfo column. So we only update the cache. 1314 1315 // Grab the write lock so no other threads can read or write the cache. 1316 mReadWriteLock.writeLock().lock(); 1317 try { 1318 SubscriptionInfoInternal subInfoCache = mAllSubscriptionInfoInternalCache.get(subId); 1319 if (subInfoCache == null) { 1320 throw new IllegalArgumentException("setCardId: Subscription doesn't exist. subId=" 1321 + subId); 1322 } 1323 mAllSubscriptionInfoInternalCache.put(subId, 1324 new SubscriptionInfoInternal.Builder(subInfoCache) 1325 .setCardId(cardId).build()); 1326 } finally { 1327 mReadWriteLock.writeLock().unlock(); 1328 } 1329 } 1330 1331 /** 1332 * Set the native access rules for this subscription, if it is embedded and defines any. 1333 * This does not include access rules for non-embedded subscriptions. 1334 * 1335 * @param subId Subscription id. 1336 * @param nativeAccessRules The native access rules for this subscription. 1337 * 1338 * @throws IllegalArgumentException if the subscription does not exist. 1339 */ setNativeAccessRules(int subId, @NonNull byte[] nativeAccessRules)1340 public void setNativeAccessRules(int subId, @NonNull byte[] nativeAccessRules) { 1341 Objects.requireNonNull(nativeAccessRules); 1342 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_ACCESS_RULES, nativeAccessRules, 1343 SubscriptionInfoInternal.Builder::setNativeAccessRules); 1344 } 1345 1346 /** 1347 * Set the carrier certificates for this subscription that are saved in carrier configs. 1348 * This does not include access rules from the Uicc, whether embedded or non-embedded. 1349 * 1350 * @param subId Subscription id. 1351 * @param carrierConfigAccessRules The carrier certificates for this subscription. 1352 * 1353 * @throws IllegalArgumentException if the subscription does not exist. 1354 */ setCarrierConfigAccessRules(int subId, @NonNull byte[] carrierConfigAccessRules)1355 public void setCarrierConfigAccessRules(int subId, @NonNull byte[] carrierConfigAccessRules) { 1356 Objects.requireNonNull(carrierConfigAccessRules); 1357 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS, 1358 carrierConfigAccessRules, 1359 SubscriptionInfoInternal.Builder::setCarrierConfigAccessRules); 1360 } 1361 1362 /** 1363 * Set the carrier certificates for this subscription that are saved in carrier configs. 1364 * This does not include access rules from the Uicc, whether embedded or non-embedded. 1365 * 1366 * @param subId Subscription id. 1367 * @param carrierConfigAccessRules The carrier certificates for this subscription. 1368 * 1369 * @throws IllegalArgumentException if the subscription does not exist. 1370 */ setCarrierConfigAccessRules(int subId, @NonNull UiccAccessRule[] carrierConfigAccessRules)1371 public void setCarrierConfigAccessRules(int subId, 1372 @NonNull UiccAccessRule[] carrierConfigAccessRules) { 1373 Objects.requireNonNull(carrierConfigAccessRules); 1374 byte[] carrierConfigAccessRulesBytes = UiccAccessRule.encodeRules(carrierConfigAccessRules); 1375 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS, 1376 carrierConfigAccessRulesBytes, 1377 SubscriptionInfoInternal.Builder::setCarrierConfigAccessRules); 1378 } 1379 1380 /** 1381 * Set whether an embedded subscription is on a removable card. Such subscriptions are 1382 * marked inaccessible as soon as the current card is removed. Otherwise, they will remain 1383 * accessible unless explicitly deleted. Only meaningful for embedded subscription. 1384 * 1385 * @param subId Subscription id. 1386 * @param isRemovableEmbedded if the subscription is from the removable embedded SIM. 1387 * 1388 * @throws IllegalArgumentException if the subscription does not exist. 1389 */ setRemovableEmbedded(int subId, int isRemovableEmbedded)1390 public void setRemovableEmbedded(int subId, int isRemovableEmbedded) { 1391 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_IS_REMOVABLE, isRemovableEmbedded, 1392 SubscriptionInfoInternal.Builder::setRemovableEmbedded); 1393 } 1394 1395 /** 1396 * Set whether cell broadcast extreme threat alert is enabled by the user or not. 1397 * 1398 * @param subId Subscription id. 1399 * @param isExtremeThreatAlertEnabled whether cell broadcast extreme threat alert is enabled by 1400 * the user or not. 1401 * 1402 * @throws IllegalArgumentException if the subscription does not exist. 1403 */ setCellBroadcastExtremeThreatAlertEnabled(int subId, int isExtremeThreatAlertEnabled)1404 public void setCellBroadcastExtremeThreatAlertEnabled(int subId, 1405 int isExtremeThreatAlertEnabled) { 1406 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT, 1407 isExtremeThreatAlertEnabled, 1408 SubscriptionInfoInternal.Builder::setCellBroadcastExtremeThreatAlertEnabled); 1409 } 1410 1411 /** 1412 * Set whether cell broadcast severe threat alert is enabled by the user or not. 1413 * 1414 * @param subId Subscription id. 1415 * @param isSevereThreatAlertEnabled whether cell broadcast severe threat alert is enabled by 1416 * the user or not. 1417 * 1418 * @throws IllegalArgumentException if the subscription does not exist. 1419 */ setCellBroadcastSevereThreatAlertEnabled(int subId, int isSevereThreatAlertEnabled)1420 public void setCellBroadcastSevereThreatAlertEnabled(int subId, 1421 int isSevereThreatAlertEnabled) { 1422 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT, 1423 isSevereThreatAlertEnabled, 1424 SubscriptionInfoInternal.Builder::setCellBroadcastSevereThreatAlertEnabled); 1425 } 1426 1427 /** 1428 * Set whether cell broadcast amber alert is enabled by the user or not. 1429 * 1430 * @param subId Subscription id. 1431 * @param isAmberAlertEnabled whether cell broadcast amber alert is enabled by 1432 * the user or not. 1433 * 1434 * @throws IllegalArgumentException if the subscription does not exist. 1435 */ setCellBroadcastAmberAlertEnabled(int subId, int isAmberAlertEnabled)1436 public void setCellBroadcastAmberAlertEnabled(int subId, int isAmberAlertEnabled) { 1437 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_AMBER_ALERT, isAmberAlertEnabled, 1438 SubscriptionInfoInternal.Builder::setCellBroadcastAmberAlertEnabled); 1439 } 1440 1441 /** 1442 * Set whether cell broadcast emergency alert is enabled by the user or not. 1443 * 1444 * @param subId Subscription id. 1445 * @param isEmergencyAlertEnabled whether cell broadcast emergency alert is enabled by 1446 * the user or not. 1447 * 1448 * @throws IllegalArgumentException if the subscription does not exist. 1449 */ setCellBroadcastEmergencyAlertEnabled(int subId, int isEmergencyAlertEnabled)1450 public void setCellBroadcastEmergencyAlertEnabled(int subId, 1451 int isEmergencyAlertEnabled) { 1452 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_EMERGENCY_ALERT, 1453 isEmergencyAlertEnabled, 1454 SubscriptionInfoInternal.Builder::setCellBroadcastEmergencyAlertEnabled); 1455 } 1456 1457 /** 1458 * Set cell broadcast alert sound duration. 1459 * 1460 * @param subId Subscription id. 1461 * @param alertSoundDuration Alert sound duration in seconds. 1462 * 1463 * @throws IllegalArgumentException if the subscription does not exist. 1464 */ setCellBroadcastAlertSoundDuration(int subId, int alertSoundDuration)1465 public void setCellBroadcastAlertSoundDuration(int subId, int alertSoundDuration) { 1466 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_ALERT_SOUND_DURATION, 1467 alertSoundDuration, 1468 SubscriptionInfoInternal.Builder::setCellBroadcastAlertSoundDuration); 1469 } 1470 1471 /** 1472 * Set cell broadcast alert reminder interval. 1473 * 1474 * @param subId Subscription id. 1475 * @param reminderInterval Alert reminder interval in milliseconds. 1476 * 1477 * @throws IllegalArgumentException if the subscription does not exist. 1478 */ setCellBroadcastAlertReminderInterval(int subId, int reminderInterval)1479 public void setCellBroadcastAlertReminderInterval(int subId, int reminderInterval) { 1480 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL, 1481 reminderInterval, 1482 SubscriptionInfoInternal.Builder::setCellBroadcastAlertReminderInterval); 1483 } 1484 1485 /** 1486 * Set whether cell broadcast alert vibration is enabled by the user or not. 1487 * 1488 * @param subId Subscription id. 1489 * @param isAlertVibrationEnabled whether cell broadcast alert vibration is enabled by the user 1490 * or not. 1491 * 1492 * @throws IllegalArgumentException if the subscription does not exist. 1493 */ setCellBroadcastAlertVibrationEnabled(int subId, int isAlertVibrationEnabled)1494 public void setCellBroadcastAlertVibrationEnabled(int subId, int isAlertVibrationEnabled) { 1495 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_ALERT_VIBRATE, isAlertVibrationEnabled, 1496 SubscriptionInfoInternal.Builder::setCellBroadcastAlertVibrationEnabled); 1497 } 1498 1499 /** 1500 * Set whether cell broadcast alert speech is enabled by the user or not. 1501 * 1502 * @param subId Subscription id. 1503 * @param isAlertSpeechEnabled whether cell broadcast alert speech is enabled by the user or 1504 * not. 1505 * 1506 * @throws IllegalArgumentException if the subscription does not exist. 1507 */ setCellBroadcastAlertSpeechEnabled(int subId, int isAlertSpeechEnabled)1508 public void setCellBroadcastAlertSpeechEnabled(int subId, int isAlertSpeechEnabled) { 1509 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_ALERT_SPEECH, isAlertSpeechEnabled, 1510 SubscriptionInfoInternal.Builder::setCellBroadcastAlertSpeechEnabled); 1511 } 1512 1513 /** 1514 * Set whether ETWS test alert is enabled by the user or not. 1515 * 1516 * @param subId Subscription id. 1517 * @param isEtwsTestAlertEnabled whether cell broadcast ETWS test alert is enabled by the user 1518 * or not. 1519 * 1520 * @throws IllegalArgumentException if the subscription does not exist. 1521 */ setCellBroadcastEtwsTestAlertEnabled(int subId, int isEtwsTestAlertEnabled)1522 public void setCellBroadcastEtwsTestAlertEnabled(int subId, int isEtwsTestAlertEnabled) { 1523 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_ETWS_TEST_ALERT, 1524 isEtwsTestAlertEnabled, 1525 SubscriptionInfoInternal.Builder::setCellBroadcastEtwsTestAlertEnabled); 1526 } 1527 1528 /** 1529 * Set whether area info message is enabled by the user or not. 1530 * 1531 * @param subId Subscription id. 1532 * @param isAreaInfoMessageEnabled whether cell broadcast area info message is enabled by the 1533 * user or not. 1534 * 1535 * @throws IllegalArgumentException if the subscription does not exist. 1536 */ setCellBroadcastAreaInfoMessageEnabled(int subId, int isAreaInfoMessageEnabled)1537 public void setCellBroadcastAreaInfoMessageEnabled(int subId, int isAreaInfoMessageEnabled) { 1538 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_CHANNEL_50_ALERT, 1539 isAreaInfoMessageEnabled, 1540 SubscriptionInfoInternal.Builder::setCellBroadcastAreaInfoMessageEnabled); 1541 } 1542 1543 /** 1544 * Set whether cell broadcast test alert is enabled by the user or not. 1545 * 1546 * @param subId Subscription id. 1547 * @param isTestAlertEnabled whether cell broadcast test alert is enabled by the user or not. 1548 * 1549 * @throws IllegalArgumentException if the subscription does not exist. 1550 */ setCellBroadcastTestAlertEnabled(int subId, int isTestAlertEnabled)1551 public void setCellBroadcastTestAlertEnabled(int subId, int isTestAlertEnabled) { 1552 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_CMAS_TEST_ALERT, isTestAlertEnabled, 1553 SubscriptionInfoInternal.Builder::setCellBroadcastTestAlertEnabled); 1554 } 1555 1556 /** 1557 * Set whether cell broadcast opt-out dialog should be shown or not. 1558 * 1559 * @param subId Subscription id. 1560 * @param isOptOutDialogEnabled whether cell broadcast opt-out dialog should be shown or not. 1561 * 1562 * @throws IllegalArgumentException if the subscription does not exist. 1563 */ setCellBroadcastOptOutDialogEnabled(int subId, int isOptOutDialogEnabled)1564 public void setCellBroadcastOptOutDialogEnabled(int subId, int isOptOutDialogEnabled) { 1565 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CB_OPT_OUT_DIALOG, isOptOutDialogEnabled, 1566 SubscriptionInfoInternal.Builder::setCellBroadcastOptOutDialogEnabled); 1567 } 1568 1569 /** 1570 * Set whether enhanced 4G mode is enabled by the user or not. 1571 * 1572 * @param subId Subscription id. 1573 * @param isEnhanced4GModeEnabled whether enhanced 4G mode is enabled by the user or not. 1574 * 1575 * @throws IllegalArgumentException if the subscription does not exist. 1576 */ setEnhanced4GModeEnabled(int subId, int isEnhanced4GModeEnabled)1577 public void setEnhanced4GModeEnabled(int subId, int isEnhanced4GModeEnabled) { 1578 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED, 1579 isEnhanced4GModeEnabled, 1580 SubscriptionInfoInternal.Builder::setEnhanced4GModeEnabled); 1581 } 1582 1583 /** 1584 * Set whether video telephony is enabled by the user or not. 1585 * 1586 * @param subId Subscription id. 1587 * @param isVideoTelephonyEnabled whether video telephony is enabled by the user or not. 1588 * 1589 * @throws IllegalArgumentException if the subscription does not exist. 1590 */ setVideoTelephonyEnabled(int subId, int isVideoTelephonyEnabled)1591 public void setVideoTelephonyEnabled(int subId, int isVideoTelephonyEnabled) { 1592 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_VT_IMS_ENABLED, isVideoTelephonyEnabled, 1593 SubscriptionInfoInternal.Builder::setVideoTelephonyEnabled); 1594 } 1595 1596 /** 1597 * Set whether Wi-Fi calling is enabled by the user or not when the device is not roaming. 1598 * 1599 * @param subId Subscription id. 1600 * @param isWifiCallingEnabled whether Wi-Fi calling is enabled by the user or not when the 1601 * device is not roaming. 1602 * 1603 * @throws IllegalArgumentException if the subscription does not exist. 1604 */ setWifiCallingEnabled(int subId, int isWifiCallingEnabled)1605 public void setWifiCallingEnabled(int subId, int isWifiCallingEnabled) { 1606 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_WFC_IMS_ENABLED, isWifiCallingEnabled, 1607 SubscriptionInfoInternal.Builder::setWifiCallingEnabled); 1608 } 1609 1610 /** 1611 * Set Wi-Fi calling mode when the device is not roaming. 1612 * 1613 * @param subId Subscription id. 1614 * @param wifiCallingMode Wi-Fi calling mode when the device is not roaming. 1615 * 1616 * @throws IllegalArgumentException if the subscription does not exist. 1617 */ setWifiCallingMode(int subId, @ImsMmTelManager.WiFiCallingMode int wifiCallingMode)1618 public void setWifiCallingMode(int subId, 1619 @ImsMmTelManager.WiFiCallingMode int wifiCallingMode) { 1620 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_WFC_IMS_MODE, wifiCallingMode, 1621 SubscriptionInfoInternal.Builder::setWifiCallingMode); 1622 } 1623 1624 /** 1625 * Set Wi-Fi calling mode when the device is roaming. 1626 * 1627 * @param subId Subscription id. 1628 * @param wifiCallingModeForRoaming Wi-Fi calling mode when the device is roaming. 1629 * 1630 * @throws IllegalArgumentException if the subscription does not exist. 1631 */ setWifiCallingModeForRoaming(int subId, @ImsMmTelManager.WiFiCallingMode int wifiCallingModeForRoaming)1632 public void setWifiCallingModeForRoaming(int subId, 1633 @ImsMmTelManager.WiFiCallingMode int wifiCallingModeForRoaming) { 1634 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_WFC_IMS_ROAMING_MODE, 1635 wifiCallingModeForRoaming, 1636 SubscriptionInfoInternal.Builder::setWifiCallingModeForRoaming); 1637 } 1638 1639 /** 1640 * Set whether Wi-Fi calling is enabled by the user or not when the device is roaming. 1641 * 1642 * @param subId Subscription id. 1643 * @param isWifiCallingEnabledForRoaming whether Wi-Fi calling is enabled by the user or not 1644 * when the device is roaming. 1645 * 1646 * @throws IllegalArgumentException if the subscription does not exist. 1647 */ setWifiCallingEnabledForRoaming(int subId, int isWifiCallingEnabledForRoaming)1648 public void setWifiCallingEnabledForRoaming(int subId, int isWifiCallingEnabledForRoaming) { 1649 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED, 1650 isWifiCallingEnabledForRoaming, 1651 SubscriptionInfoInternal.Builder::setWifiCallingEnabledForRoaming); 1652 } 1653 1654 /** 1655 * Set whether the subscription is opportunistic or not. 1656 * 1657 * @param subId Subscription id. 1658 * @param isOpportunistic if the subscription is opportunistic. 1659 * 1660 * @throws IllegalArgumentException if the subscription does not exist. 1661 */ setOpportunistic(int subId, boolean isOpportunistic)1662 public void setOpportunistic(int subId, boolean isOpportunistic) { 1663 setOpportunistic(subId, isOpportunistic ? 1 : 0); 1664 } 1665 1666 /** 1667 * Set whether the subscription is opportunistic or not. 1668 * 1669 * @param subId Subscription id. 1670 * @param isOpportunistic if the subscription is opportunistic. 1671 * 1672 * @throws IllegalArgumentException if the subscription does not exist. 1673 */ setOpportunistic(int subId, int isOpportunistic)1674 public void setOpportunistic(int subId, int isOpportunistic) { 1675 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_IS_OPPORTUNISTIC, isOpportunistic, 1676 SubscriptionInfoInternal.Builder::setOpportunistic); 1677 } 1678 1679 /** 1680 * Set the group UUID of the subscription group. 1681 * 1682 * @param subId Subscription id. 1683 * @param groupUuid The group UUID. 1684 * 1685 * @throws IllegalArgumentException if the subscription does not exist. 1686 * 1687 * @see SubscriptionInfo#getGroupUuid() 1688 */ setGroupUuid(int subId, @NonNull String groupUuid)1689 public void setGroupUuid(int subId, @NonNull String groupUuid) { 1690 Objects.requireNonNull(groupUuid); 1691 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_GROUP_UUID, groupUuid, 1692 SubscriptionInfoInternal.Builder::setGroupUuid); 1693 } 1694 1695 /** 1696 * Set the ISO Country code for the subscription's provider. 1697 * 1698 * @param subId Subscription id. 1699 * @param countryIso The ISO country code for the subscription's provider. 1700 * 1701 * @throws IllegalArgumentException if the subscription does not exist. 1702 */ setCountryIso(int subId, @NonNull String countryIso)1703 public void setCountryIso(int subId, @NonNull String countryIso) { 1704 Objects.requireNonNull(countryIso); 1705 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_ISO_COUNTRY_CODE, countryIso, 1706 SubscriptionInfoInternal.Builder::setCountryIso); 1707 } 1708 1709 /** 1710 * Set the subscription carrier id. 1711 * 1712 * @param subId Subscription id. 1713 * @param carrierId The carrier id. 1714 * 1715 * @throws IllegalArgumentException if the subscription does not exist. 1716 * 1717 * @see TelephonyManager#getSimCarrierId() 1718 */ setCarrierId(int subId, int carrierId)1719 public void setCarrierId(int subId, int carrierId) { 1720 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CARRIER_ID, carrierId, 1721 SubscriptionInfoInternal.Builder::setCarrierId); 1722 } 1723 1724 /** 1725 * Set the profile class populated from the profile metadata if present. 1726 * 1727 * @param subId Subscription id. 1728 * @param profileClass the profile class populated from the profile metadata if present. 1729 * 1730 * @throws IllegalArgumentException if the subscription does not exist. 1731 * 1732 * @see SubscriptionInfo#getProfileClass() 1733 */ setProfileClass(int subId, @ProfileClass int profileClass)1734 public void setProfileClass(int subId, @ProfileClass int profileClass) { 1735 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_PROFILE_CLASS, profileClass, 1736 SubscriptionInfoInternal.Builder::setProfileClass); 1737 } 1738 1739 /** 1740 * Set the subscription type. 1741 * 1742 * @param subId Subscription id. 1743 * @param type Subscription type. 1744 * 1745 * @throws IllegalArgumentException if the subscription does not exist. 1746 */ setSubscriptionType(int subId, @SubscriptionType int type)1747 public void setSubscriptionType(int subId, @SubscriptionType int type) { 1748 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_SUBSCRIPTION_TYPE, type, 1749 SubscriptionInfoInternal.Builder::setType); 1750 } 1751 1752 /** 1753 * Set the owner package of group the subscription belongs to. 1754 * 1755 * @param subId Subscription id. 1756 * @param groupOwner Owner package of group the subscription belongs to. 1757 * 1758 * @throws IllegalArgumentException if the subscription does not exist. 1759 */ setGroupOwner(int subId, @NonNull String groupOwner)1760 public void setGroupOwner(int subId, @NonNull String groupOwner) { 1761 Objects.requireNonNull(groupOwner); 1762 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_GROUP_OWNER, groupOwner, 1763 SubscriptionInfoInternal.Builder::setGroupOwner); 1764 } 1765 1766 /** 1767 * Set the enabled mobile data policies. 1768 * 1769 * @param subId Subscription id. 1770 * @param enabledMobileDataPolicies The enabled mobile data policies. 1771 * 1772 * @throws IllegalArgumentException if the subscription does not exist. 1773 */ setEnabledMobileDataPolicies(int subId, @NonNull String enabledMobileDataPolicies)1774 public void setEnabledMobileDataPolicies(int subId, @NonNull String enabledMobileDataPolicies) { 1775 Objects.requireNonNull(enabledMobileDataPolicies); 1776 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES, 1777 enabledMobileDataPolicies, 1778 SubscriptionInfoInternal.Builder::setEnabledMobileDataPolicies); 1779 } 1780 1781 /** 1782 * Set the IMSI (International Mobile Subscriber Identity) of the subscription. 1783 * 1784 * @param subId Subscription id. 1785 * @param imsi The IMSI. 1786 * 1787 * @throws IllegalArgumentException if the subscription does not exist. 1788 */ setImsi(int subId, @NonNull String imsi)1789 public void setImsi(int subId, @NonNull String imsi) { 1790 Objects.requireNonNull(imsi); 1791 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_IMSI, imsi, 1792 SubscriptionInfoInternal.Builder::setImsi); 1793 } 1794 1795 /** 1796 * Set whether Uicc applications are configured to enable or not. 1797 * 1798 * @param subId Subscription id. 1799 * @param areUiccApplicationsEnabled if Uicc applications are configured to enable. 1800 * 1801 * @throws IllegalArgumentException if the subscription does not exist. 1802 */ setUiccApplicationsEnabled(int subId, boolean areUiccApplicationsEnabled)1803 public void setUiccApplicationsEnabled(int subId, boolean areUiccApplicationsEnabled) { 1804 setUiccApplicationsEnabled(subId, areUiccApplicationsEnabled ? 1 : 0); 1805 } 1806 1807 /** 1808 * Set whether Uicc applications are configured to enable or not. 1809 * 1810 * @param subId Subscription id. 1811 * @param areUiccApplicationsEnabled if Uicc applications are configured to enable. 1812 * 1813 * @throws IllegalArgumentException if the subscription does not exist. 1814 */ setUiccApplicationsEnabled(int subId, int areUiccApplicationsEnabled)1815 public void setUiccApplicationsEnabled(int subId, int areUiccApplicationsEnabled) { 1816 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED, 1817 areUiccApplicationsEnabled, 1818 SubscriptionInfoInternal.Builder::setUiccApplicationsEnabled); 1819 } 1820 1821 /** 1822 * Set whether the user has enabled IMS RCS User Capability Exchange (UCE) for this 1823 * subscription. 1824 * 1825 * @param subId Subscription id. 1826 * @param isRcsUceEnabled If the user enabled RCS UCE for this subscription. 1827 * 1828 * @throws IllegalArgumentException if the subscription does not exist. 1829 */ setRcsUceEnabled(int subId, int isRcsUceEnabled)1830 public void setRcsUceEnabled(int subId, int isRcsUceEnabled) { 1831 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_IMS_RCS_UCE_ENABLED, isRcsUceEnabled, 1832 SubscriptionInfoInternal.Builder::setRcsUceEnabled); 1833 } 1834 1835 /** 1836 * Set whether the user has enabled cross SIM calling for this subscription. 1837 * 1838 * @param subId Subscription id. 1839 * @param isCrossSimCallingEnabled If the user enabled cross SIM calling for this 1840 * subscription. 1841 * 1842 * @throws IllegalArgumentException if the subscription does not exist. 1843 */ setCrossSimCallingEnabled(int subId, int isCrossSimCallingEnabled)1844 public void setCrossSimCallingEnabled(int subId, int isCrossSimCallingEnabled) { 1845 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED, 1846 isCrossSimCallingEnabled, 1847 SubscriptionInfoInternal.Builder::setCrossSimCallingEnabled); 1848 } 1849 1850 /** 1851 * Set the RCS config for this subscription. 1852 * 1853 * @param subId Subscription id. 1854 * @param rcsConfig The RCS config for this subscription. 1855 * 1856 * @throws IllegalArgumentException if the subscription does not exist. 1857 */ setRcsConfig(int subId, @NonNull byte[] rcsConfig)1858 public void setRcsConfig(int subId, @NonNull byte[] rcsConfig) { 1859 Objects.requireNonNull(rcsConfig); 1860 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_RCS_CONFIG, rcsConfig, 1861 SubscriptionInfoInternal.Builder::setRcsConfig); 1862 } 1863 1864 /** 1865 * Set the allowed network types for reasons. 1866 * 1867 * @param subId Subscription id. 1868 * @param allowedNetworkTypesForReasons The allowed network types for reasons in string 1869 * format. The format is "[reason]=[network types bitmask], [reason]=[network types bitmask], 1870 * ...". For example, "user=1239287394, thermal=298791239, carrier=3456812312". 1871 * 1872 * @throws IllegalArgumentException if the subscription does not exist. 1873 */ setAllowedNetworkTypesForReasons(int subId, @NonNull String allowedNetworkTypesForReasons)1874 public void setAllowedNetworkTypesForReasons(int subId, 1875 @NonNull String allowedNetworkTypesForReasons) { 1876 Objects.requireNonNull(allowedNetworkTypesForReasons); 1877 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS, 1878 allowedNetworkTypesForReasons, 1879 SubscriptionInfoInternal.Builder::setAllowedNetworkTypesForReasons); 1880 } 1881 1882 /** 1883 * Set device to device sharing status. 1884 * 1885 * @param subId Subscription id. 1886 * @param deviceToDeviceStatusSharingPreference Device to device sharing status. 1887 * 1888 * @throws IllegalArgumentException if the subscription does not exist. 1889 */ setDeviceToDeviceStatusSharingPreference(int subId, @DeviceToDeviceStatusSharingPreference int deviceToDeviceStatusSharingPreference)1890 public void setDeviceToDeviceStatusSharingPreference(int subId, 1891 @DeviceToDeviceStatusSharingPreference int deviceToDeviceStatusSharingPreference) { 1892 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_D2D_STATUS_SHARING, 1893 deviceToDeviceStatusSharingPreference, 1894 SubscriptionInfoInternal.Builder::setDeviceToDeviceStatusSharingPreference); 1895 } 1896 1897 /** 1898 * Set whether the user has opted-in voice over IMS. 1899 * 1900 * @param subId Subscription id. 1901 * @param isVoImsOptInEnabled Whether the user has opted-in voice over IMS. 1902 * 1903 * @throws IllegalArgumentException if the subscription does not exist. 1904 */ setVoImsOptInEnabled(int subId, int isVoImsOptInEnabled)1905 public void setVoImsOptInEnabled(int subId, int isVoImsOptInEnabled) { 1906 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_VOIMS_OPT_IN_STATUS, isVoImsOptInEnabled, 1907 SubscriptionInfoInternal.Builder::setVoImsOptInEnabled); 1908 } 1909 1910 /** 1911 * Set contacts information that allow device to device sharing. 1912 * 1913 * @param subId Subscription id. 1914 * @param deviceToDeviceStatusSharingContacts contacts information that allow device to 1915 * device sharing. 1916 * 1917 * @throws IllegalArgumentException if the subscription does not exist. 1918 */ setDeviceToDeviceStatusSharingContacts(int subId, @NonNull String deviceToDeviceStatusSharingContacts)1919 public void setDeviceToDeviceStatusSharingContacts(int subId, 1920 @NonNull String deviceToDeviceStatusSharingContacts) { 1921 Objects.requireNonNull(deviceToDeviceStatusSharingContacts); 1922 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS, 1923 deviceToDeviceStatusSharingContacts, 1924 SubscriptionInfoInternal.Builder::setDeviceToDeviceStatusSharingContacts); 1925 } 1926 1927 /** 1928 * Set whether the user has enabled NR advanced calling. 1929 * 1930 * @param subId Subscription id. 1931 * @param isNrAdvancedCallingEnabled Whether the user has enabled NR advanced calling. 1932 * 1933 * @throws IllegalArgumentException if the subscription does not exist. 1934 */ setNrAdvancedCallingEnabled(int subId, int isNrAdvancedCallingEnabled)1935 public void setNrAdvancedCallingEnabled(int subId, int isNrAdvancedCallingEnabled) { 1936 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED, 1937 isNrAdvancedCallingEnabled, 1938 SubscriptionInfoInternal.Builder::setNrAdvancedCallingEnabled); 1939 } 1940 1941 /** 1942 * Set the phone number retrieved from carrier. 1943 * 1944 * @param subId Subscription id. 1945 * @param numberFromCarrier The phone number retrieved from carrier. 1946 * 1947 * @throws IllegalArgumentException if the subscription does not exist. 1948 */ setNumberFromCarrier(int subId, @NonNull String numberFromCarrier)1949 public void setNumberFromCarrier(int subId, @NonNull String numberFromCarrier) { 1950 Objects.requireNonNull(numberFromCarrier); 1951 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_PHONE_NUMBER_SOURCE_CARRIER, 1952 numberFromCarrier, SubscriptionInfoInternal.Builder::setNumberFromCarrier); 1953 } 1954 1955 /** 1956 * Set the phone number retrieved from IMS. 1957 * 1958 * @param subId Subscription id. 1959 * @param numberFromIms The phone number retrieved from IMS. 1960 * 1961 * @throws IllegalArgumentException if the subscription does not exist. 1962 */ setNumberFromIms(int subId, @NonNull String numberFromIms)1963 public void setNumberFromIms(int subId, @NonNull String numberFromIms) { 1964 Objects.requireNonNull(numberFromIms); 1965 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_PHONE_NUMBER_SOURCE_IMS, 1966 numberFromIms, SubscriptionInfoInternal.Builder::setNumberFromIms); 1967 } 1968 1969 /** 1970 * Set the port index of the Uicc card. 1971 * 1972 * @param subId Subscription id. 1973 * @param portIndex The port index of the Uicc card. 1974 * 1975 * @throws IllegalArgumentException if the subscription does not exist. 1976 */ setPortIndex(int subId, int portIndex)1977 public void setPortIndex(int subId, int portIndex) { 1978 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_PORT_INDEX, portIndex, 1979 SubscriptionInfoInternal.Builder::setPortIndex); 1980 } 1981 1982 /** 1983 * Set subscription's preferred usage setting. 1984 * 1985 * @param subId Subscription id. 1986 * @param usageSetting Subscription's preferred usage setting. 1987 * 1988 * @throws IllegalArgumentException if the subscription does not exist. 1989 */ setUsageSetting(int subId, @UsageSetting int usageSetting)1990 public void setUsageSetting(int subId, @UsageSetting int usageSetting) { 1991 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_USAGE_SETTING, usageSetting, 1992 SubscriptionInfoInternal.Builder::setUsageSetting); 1993 } 1994 1995 /** 1996 * Set last used TP message reference. 1997 * 1998 * @param subId Subscription id. 1999 * @param lastUsedTPMessageReference Last used TP message reference. 2000 * 2001 * @throws IllegalArgumentException if the subscription does not exist. 2002 */ setLastUsedTPMessageReference(int subId, int lastUsedTPMessageReference)2003 public void setLastUsedTPMessageReference(int subId, int lastUsedTPMessageReference) { 2004 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_TP_MESSAGE_REF, 2005 lastUsedTPMessageReference, 2006 SubscriptionInfoInternal.Builder::setLastUsedTPMessageReference); 2007 } 2008 2009 /** 2010 * Set the user id associated with this subscription. 2011 * 2012 * @param subId Subscription id. 2013 * @param userId The user id associated with this subscription. 2014 * 2015 * @throws IllegalArgumentException if the subscription does not exist. 2016 */ setUserId(int subId, @UserIdInt int userId)2017 public void setUserId(int subId, @UserIdInt int userId) { 2018 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_USER_HANDLE, userId, 2019 SubscriptionInfoInternal.Builder::setUserId); 2020 } 2021 2022 /** 2023 * Set whether satellite is enabled or not. 2024 * 2025 * @param subId Subscription id. 2026 * @param isSatelliteEnabled if satellite is enabled or not. 2027 * 2028 * @throws IllegalArgumentException if the subscription does not exist. 2029 */ setSatelliteEnabled(int subId, int isSatelliteEnabled)2030 public void setSatelliteEnabled(int subId, int isSatelliteEnabled) { 2031 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_SATELLITE_ENABLED, 2032 isSatelliteEnabled, 2033 SubscriptionInfoInternal.Builder::setSatelliteEnabled); 2034 } 2035 2036 /** 2037 * Set whether satellite attach for carrier is enabled or disabled by user. 2038 * 2039 * @param subId Subscription id. 2040 * @param isSatelliteAttachEnabledForCarrier Whether satellite attach for carrier is enabled or 2041 * disabled. 2042 * 2043 * @throws IllegalArgumentException if the subscription does not exist. 2044 */ setSatelliteAttachEnabledForCarrier(int subId, int isSatelliteAttachEnabledForCarrier)2045 public void setSatelliteAttachEnabledForCarrier(int subId, 2046 int isSatelliteAttachEnabledForCarrier) { 2047 writeDatabaseAndCacheHelper(subId, 2048 SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER, 2049 isSatelliteAttachEnabledForCarrier, 2050 SubscriptionInfoInternal.Builder::setSatelliteAttachEnabledForCarrier); 2051 } 2052 2053 /** 2054 * Set whether the subscription is exclusively used for non-terrestrial networks or not. 2055 * 2056 * @param subId Subscription ID. 2057 * @param isNtn {@code 1} if it is a non-terrestrial network subscription. 2058 * {@code 0} otherwise. 2059 * 2060 * @throws IllegalArgumentException if the subscription does not exist. 2061 */ setNtn(int subId, int isNtn)2062 public void setNtn(int subId, int isNtn) { 2063 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 2064 return; 2065 } 2066 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_IS_NTN, isNtn, 2067 SubscriptionInfoInternal.Builder::setOnlyNonTerrestrialNetwork); 2068 } 2069 2070 /** 2071 * Set whether group of the subscription is disabled. This is only useful if it's a grouped 2072 * opportunistic subscription. In this case, if all primary (non-opportunistic) 2073 * subscriptions in the group are deactivated (unplugged pSIM or deactivated eSIM profile), 2074 * we should disable this opportunistic subscription. 2075 * 2076 * @param subId Subscription id. 2077 * @param isGroupDisabled if group of the subscription is disabled. 2078 * 2079 * @throws IllegalArgumentException if the subscription does not exist. 2080 */ setGroupDisabled(int subId, boolean isGroupDisabled)2081 public void setGroupDisabled(int subId, boolean isGroupDisabled) { 2082 // group disabled does not have a corresponding SimInfo column. So we only update the cache. 2083 boolean isChanged = false; 2084 // Grab the write lock so no other threads can read or write the cache. 2085 mReadWriteLock.writeLock().lock(); 2086 try { 2087 SubscriptionInfoInternal subInfoCache = mAllSubscriptionInfoInternalCache.get(subId); 2088 if (subInfoCache == null) { 2089 throw new IllegalArgumentException("setGroupDisabled: Subscription doesn't exist. " 2090 + "subId=" + subId); 2091 } 2092 isChanged = subInfoCache.isGroupDisabled() != isGroupDisabled; 2093 mAllSubscriptionInfoInternalCache.put(subId, 2094 new SubscriptionInfoInternal.Builder(subInfoCache) 2095 .setGroupDisabled(isGroupDisabled).build()); 2096 } finally { 2097 mReadWriteLock.writeLock().unlock(); 2098 } 2099 2100 if (isChanged) { 2101 log("setGroupDisabled value changed, firing the callback"); 2102 mCallback.invokeFromExecutor(() -> mCallback.onSubscriptionChanged(subId)); 2103 } 2104 } 2105 2106 /** 2107 * Set service capabilities the subscription support. 2108 * @param subId Subscription id. 2109 * @param capabilities Service capabilities bitmasks 2110 */ setServiceCapabilities(int subId, int capabilities)2111 public void setServiceCapabilities(int subId, int capabilities) { 2112 if (!mFeatureFlags.dataOnlyCellularService()) { 2113 return; 2114 } 2115 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_SERVICE_CAPABILITIES, 2116 capabilities, SubscriptionInfoInternal.Builder::setServiceCapabilities); 2117 } 2118 2119 /** 2120 * Set whether satellite entitlement status is enabled by entitlement query result. 2121 * 2122 * @param subId Subscription id. 2123 * @param isSatelliteEntitlementStatus Whether satellite entitlement status is enabled or 2124 * disabled. 2125 * @throws IllegalArgumentException if the subscription does not exist. 2126 */ setSatelliteEntitlementStatus(int subId, int isSatelliteEntitlementStatus)2127 public void setSatelliteEntitlementStatus(int subId, 2128 int isSatelliteEntitlementStatus) { 2129 writeDatabaseAndCacheHelper(subId, 2130 SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS, 2131 isSatelliteEntitlementStatus, 2132 SubscriptionInfoInternal.Builder::setSatelliteEntitlementStatus); 2133 } 2134 2135 /** 2136 * Set satellite entitlement plmns by entitlement query result. 2137 * 2138 * @param subId Subscription id. 2139 * @param satelliteEntitlementPlmns Satellite entitlement plmns 2140 * @throws IllegalArgumentException if the subscription does not exist. 2141 */ setSatelliteEntitlementPlmns(int subId, @NonNull String satelliteEntitlementPlmns)2142 public void setSatelliteEntitlementPlmns(int subId, 2143 @NonNull String satelliteEntitlementPlmns) { 2144 writeDatabaseAndCacheHelper(subId, 2145 SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS, 2146 satelliteEntitlementPlmns, 2147 SubscriptionInfoInternal.Builder::setSatelliteEntitlementPlmns); 2148 } 2149 2150 /** 2151 * Set satellite entitlement plmn list by entitlement query result. 2152 * 2153 * @param subId Subscription id. 2154 * @param satelliteEntitlementPlmnList Satellite entitlement plmn list 2155 * @throws IllegalArgumentException if the subscription does not exist. 2156 */ setSatelliteEntitlementPlmnList(int subId, @NonNull List<String> satelliteEntitlementPlmnList)2157 public void setSatelliteEntitlementPlmnList(int subId, 2158 @NonNull List<String> satelliteEntitlementPlmnList) { 2159 String satelliteEntitlementPlmns = satelliteEntitlementPlmnList.stream().collect( 2160 Collectors.joining(",")); 2161 setSatelliteEntitlementPlmns(subId, satelliteEntitlementPlmns); 2162 } 2163 2164 /** 2165 * Reload the database from content provider to the cache. This must be a synchronous operation 2166 * to prevent cache/database out-of-sync. Callers should be cautious to call this method because 2167 * it might take longer time to complete. 2168 */ reloadDatabaseSync()2169 public void reloadDatabaseSync() { 2170 logl("reloadDatabaseSync"); 2171 // Synchronously load the database into the cache. 2172 loadDatabaseInternal(); 2173 } 2174 2175 /** 2176 * Load the database from content provider to the cache. 2177 */ loadDatabaseInternal()2178 private void loadDatabaseInternal() { 2179 logl("loadDatabaseInternal"); 2180 try (Cursor cursor = mContext.getContentResolver().query( 2181 SimInfo.CONTENT_URI, null, null, null, null)) { 2182 mReadWriteLock.writeLock().lock(); 2183 try { 2184 Map<Integer, SubscriptionInfoInternal> newAllSubscriptionInfoInternalCache = 2185 new HashMap<>(); 2186 boolean changed = false; 2187 while (cursor != null && cursor.moveToNext()) { 2188 SubscriptionInfoInternal subInfo = createSubscriptionInfoFromCursor(cursor); 2189 newAllSubscriptionInfoInternalCache.put(subInfo.getSubscriptionId(), subInfo); 2190 if (!Objects.equals(mAllSubscriptionInfoInternalCache 2191 .get(subInfo.getSubscriptionId()), subInfo)) { 2192 mCallback.invokeFromExecutor(() -> mCallback.onSubscriptionChanged( 2193 subInfo.getSubscriptionId())); 2194 changed = true; 2195 } 2196 } 2197 2198 if (changed) { 2199 mAllSubscriptionInfoInternalCache.clear(); 2200 mAllSubscriptionInfoInternalCache.putAll(newAllSubscriptionInfoInternalCache); 2201 2202 logl("Loaded " + mAllSubscriptionInfoInternalCache.size() 2203 + " records from the subscription database."); 2204 mAllSubscriptionInfoInternalCache.forEach( 2205 (subId, subInfo) -> log(" " + subInfo.toString())); 2206 } 2207 } finally { 2208 mReadWriteLock.writeLock().unlock(); 2209 } 2210 } 2211 } 2212 2213 /** 2214 * Initialize the database cache. Load the entire database into the cache. 2215 */ initializeDatabase()2216 private void initializeDatabase() { 2217 if (mAsyncMode) { 2218 // Load the database asynchronously. 2219 post(() -> { 2220 synchronized (this) { 2221 loadDatabaseInternal(); 2222 mDatabaseInitialized = true; 2223 mCallback.invokeFromExecutor(mCallback::onInitialized); 2224 } 2225 }); 2226 } else { 2227 // Load the database synchronously. 2228 synchronized (this) { 2229 loadDatabaseInternal(); 2230 mDatabaseInitialized = true; 2231 mCallback.invokeFromExecutor(mCallback::onInitialized); 2232 } 2233 } 2234 } 2235 2236 /** 2237 * Build the {@link SubscriptionInfoInternal} from database. 2238 * 2239 * @param cursor The cursor of the database. 2240 * 2241 * @return The subscription info from a single database record. 2242 */ 2243 @NonNull createSubscriptionInfoFromCursor(@onNull Cursor cursor)2244 private SubscriptionInfoInternal createSubscriptionInfoFromCursor(@NonNull Cursor cursor) { 2245 SubscriptionInfoInternal.Builder builder = new SubscriptionInfoInternal.Builder(); 2246 int id = cursor.getInt(cursor.getColumnIndexOrThrow( 2247 SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID)); 2248 builder.setId(id) 2249 .setIccId(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2250 SimInfo.COLUMN_ICC_ID)))) 2251 .setSimSlotIndex(cursor.getInt(cursor.getColumnIndexOrThrow( 2252 SimInfo.COLUMN_SIM_SLOT_INDEX))) 2253 .setDisplayName(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2254 SimInfo.COLUMN_DISPLAY_NAME)))) 2255 .setCarrierName(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2256 SimInfo.COLUMN_CARRIER_NAME)))) 2257 .setDisplayNameSource(cursor.getInt(cursor.getColumnIndexOrThrow( 2258 SimInfo.COLUMN_NAME_SOURCE))) 2259 .setIconTint(cursor.getInt(cursor.getColumnIndexOrThrow( 2260 SimInfo.COLUMN_COLOR))) 2261 .setNumber(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2262 SimInfo.COLUMN_NUMBER)))) 2263 .setDataRoaming(cursor.getInt(cursor.getColumnIndexOrThrow( 2264 SimInfo.COLUMN_DATA_ROAMING))) 2265 .setMcc(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2266 SimInfo.COLUMN_MCC_STRING)))) 2267 .setMnc(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2268 SimInfo.COLUMN_MNC_STRING)))) 2269 .setEhplmns(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2270 SimInfo.COLUMN_EHPLMNS)))) 2271 .setHplmns(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2272 SimInfo.COLUMN_HPLMNS)))) 2273 .setEmbedded(cursor.getInt(cursor.getColumnIndexOrThrow( 2274 SimInfo.COLUMN_IS_EMBEDDED))); 2275 2276 String cardString = TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2277 SimInfo.COLUMN_CARD_ID))); 2278 builder.setCardString(cardString); 2279 // publicCardId is the publicly exposed int card ID 2280 int publicCardId = mUiccController.convertToPublicCardId(cardString); 2281 2282 byte[] rules = cursor.getBlob(cursor.getColumnIndexOrThrow(SimInfo.COLUMN_ACCESS_RULES)); 2283 if (rules != null) { 2284 builder.setNativeAccessRules(rules); 2285 } 2286 2287 rules = cursor.getBlob(cursor.getColumnIndexOrThrow( 2288 SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS)); 2289 if (rules != null) { 2290 builder.setCarrierConfigAccessRules(rules); 2291 } 2292 2293 byte[] config = cursor.getBlob(cursor.getColumnIndexOrThrow(SimInfo.COLUMN_RCS_CONFIG)); 2294 if (config != null) { 2295 builder.setRcsConfig(config); 2296 } 2297 2298 builder.setCardId(publicCardId) 2299 .setRemovableEmbedded(cursor.getInt(cursor.getColumnIndexOrThrow( 2300 SimInfo.COLUMN_IS_REMOVABLE))) 2301 .setCellBroadcastExtremeThreatAlertEnabled(cursor.getInt(cursor 2302 .getColumnIndexOrThrow(SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT))) 2303 .setCellBroadcastSevereThreatAlertEnabled(cursor.getInt(cursor 2304 .getColumnIndexOrThrow(SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT))) 2305 .setCellBroadcastAmberAlertEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2306 SimInfo.COLUMN_CB_AMBER_ALERT))) 2307 .setCellBroadcastEmergencyAlertEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2308 SimInfo.COLUMN_CB_EMERGENCY_ALERT))) 2309 .setCellBroadcastAlertSoundDuration(cursor.getInt(cursor.getColumnIndexOrThrow( 2310 SimInfo.COLUMN_CB_ALERT_SOUND_DURATION))) 2311 .setCellBroadcastAlertReminderInterval(cursor.getInt(cursor.getColumnIndexOrThrow( 2312 SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL))) 2313 .setCellBroadcastAlertVibrationEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2314 SimInfo.COLUMN_CB_ALERT_VIBRATE))) 2315 .setCellBroadcastAlertSpeechEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2316 SimInfo.COLUMN_CB_ALERT_SPEECH))) 2317 .setCellBroadcastEtwsTestAlertEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2318 SimInfo.COLUMN_CB_ETWS_TEST_ALERT))) 2319 .setCellBroadcastAreaInfoMessageEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2320 SimInfo.COLUMN_CB_CHANNEL_50_ALERT))) 2321 .setCellBroadcastTestAlertEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2322 SimInfo.COLUMN_CB_CMAS_TEST_ALERT))) 2323 .setCellBroadcastOptOutDialogEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2324 SimInfo.COLUMN_CB_OPT_OUT_DIALOG))) 2325 .setEnhanced4GModeEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2326 SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED))) 2327 .setVideoTelephonyEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2328 SimInfo.COLUMN_VT_IMS_ENABLED))) 2329 .setWifiCallingEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2330 SimInfo.COLUMN_WFC_IMS_ENABLED))) 2331 .setWifiCallingMode(cursor.getInt(cursor.getColumnIndexOrThrow( 2332 SimInfo.COLUMN_WFC_IMS_MODE))) 2333 .setWifiCallingModeForRoaming(cursor.getInt(cursor.getColumnIndexOrThrow( 2334 SimInfo.COLUMN_WFC_IMS_ROAMING_MODE))) 2335 .setWifiCallingEnabledForRoaming(cursor.getInt(cursor.getColumnIndexOrThrow( 2336 SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED))) 2337 .setOpportunistic(cursor.getInt(cursor.getColumnIndexOrThrow( 2338 SimInfo.COLUMN_IS_OPPORTUNISTIC))) 2339 .setGroupUuid(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2340 SimInfo.COLUMN_GROUP_UUID)))) 2341 .setCountryIso(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2342 SimInfo.COLUMN_ISO_COUNTRY_CODE)))) 2343 .setCarrierId(cursor.getInt(cursor.getColumnIndexOrThrow( 2344 SimInfo.COLUMN_CARRIER_ID))) 2345 .setProfileClass(cursor.getInt(cursor.getColumnIndexOrThrow( 2346 SimInfo.COLUMN_PROFILE_CLASS))) 2347 .setType(cursor.getInt(cursor.getColumnIndexOrThrow( 2348 SimInfo.COLUMN_SUBSCRIPTION_TYPE))) 2349 .setGroupOwner(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2350 SimInfo.COLUMN_GROUP_OWNER)))) 2351 .setEnabledMobileDataPolicies(TextUtils.emptyIfNull( 2352 cursor.getString(cursor.getColumnIndexOrThrow( 2353 SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES)))) 2354 .setImsi(TextUtils.emptyIfNull(cursor.getString(cursor.getColumnIndexOrThrow( 2355 SimInfo.COLUMN_IMSI)))) 2356 .setUiccApplicationsEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2357 SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED))) 2358 .setRcsUceEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2359 SimInfo.COLUMN_IMS_RCS_UCE_ENABLED))) 2360 .setCrossSimCallingEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2361 SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED))) 2362 .setAllowedNetworkTypesForReasons(TextUtils.emptyIfNull( 2363 cursor.getString(cursor.getColumnIndexOrThrow( 2364 SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS)))) 2365 .setDeviceToDeviceStatusSharingPreference(cursor.getInt( 2366 cursor.getColumnIndexOrThrow( 2367 SimInfo.COLUMN_D2D_STATUS_SHARING))) 2368 .setVoImsOptInEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2369 SimInfo.COLUMN_VOIMS_OPT_IN_STATUS))) 2370 .setDeviceToDeviceStatusSharingContacts(TextUtils.emptyIfNull(cursor.getString( 2371 cursor.getColumnIndexOrThrow( 2372 SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS)))) 2373 .setNrAdvancedCallingEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2374 SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED))) 2375 .setNumberFromCarrier(TextUtils.emptyIfNull(cursor.getString( 2376 cursor.getColumnIndexOrThrow( 2377 SimInfo.COLUMN_PHONE_NUMBER_SOURCE_CARRIER)))) 2378 .setNumberFromIms(TextUtils.emptyIfNull(cursor.getString( 2379 cursor.getColumnIndexOrThrow( 2380 SimInfo.COLUMN_PHONE_NUMBER_SOURCE_IMS)))) 2381 .setPortIndex(cursor.getInt(cursor.getColumnIndexOrThrow( 2382 SimInfo.COLUMN_PORT_INDEX))) 2383 .setUsageSetting(cursor.getInt(cursor.getColumnIndexOrThrow( 2384 SimInfo.COLUMN_USAGE_SETTING))) 2385 .setLastUsedTPMessageReference(cursor.getInt(cursor.getColumnIndexOrThrow( 2386 SimInfo.COLUMN_TP_MESSAGE_REF))) 2387 .setUserId(cursor.getInt(cursor.getColumnIndexOrThrow( 2388 SimInfo.COLUMN_USER_HANDLE))) 2389 .setSatelliteEnabled(cursor.getInt(cursor.getColumnIndexOrThrow( 2390 SimInfo.COLUMN_SATELLITE_ENABLED))) 2391 .setSatelliteAttachEnabledForCarrier(cursor.getInt( 2392 cursor.getColumnIndexOrThrow( 2393 SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER))) 2394 .setServiceCapabilities(cursor.getInt( 2395 cursor.getColumnIndexOrThrow( 2396 SimInfo.COLUMN_SERVICE_CAPABILITIES))) 2397 .setSatelliteEntitlementStatus(cursor.getInt( 2398 cursor.getColumnIndexOrThrow( 2399 SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS))) 2400 .setSatelliteEntitlementPlmns(cursor.getString( 2401 cursor.getColumnIndexOrThrow( 2402 SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS))); 2403 if (mFeatureFlags.oemEnabledSatelliteFlag()) { 2404 builder.setOnlyNonTerrestrialNetwork(cursor.getInt(cursor.getColumnIndexOrThrow( 2405 SimInfo.COLUMN_IS_NTN))); 2406 } 2407 if (mFeatureFlags.supportPsimToEsimConversion()) { 2408 builder.setTransferStatus(cursor.getInt(cursor.getColumnIndexOrThrow( 2409 SimInfo.COLUMN_TRANSFER_STATUS))); 2410 } 2411 return builder.build(); 2412 } 2413 2414 /** 2415 * Sync the group sharing fields from reference subscription to the rest of the subscriptions in 2416 * the same group. For example, if user enables wifi calling, the same setting should be applied 2417 * to all subscriptions in the same group. 2418 * 2419 * @param subId The subscription id of reference subscription. 2420 * 2421 * @throws IllegalArgumentException if the subscription does not exist. 2422 */ syncToGroup(int subId)2423 public void syncToGroup(int subId) { 2424 if (!mAllSubscriptionInfoInternalCache.containsKey(subId)) { 2425 throw new IllegalArgumentException("Invalid subId " + subId); 2426 } 2427 2428 for (String column : GROUP_SHARING_COLUMNS) { 2429 // Get the value from the reference subscription, and set to itself again. 2430 // writeDatabaseAndCacheHelper() will automatically sync to the rest of the group. 2431 setSubscriptionProperty(subId, column, getSubscriptionProperty(subId, column)); 2432 } 2433 } 2434 2435 /** 2436 * Get the subscription info by subscription id. 2437 * 2438 * @param subId The subscription id. 2439 * 2440 * @return The subscription info. {@code null} if not found. 2441 */ 2442 @Nullable getSubscriptionInfoInternal(int subId)2443 public SubscriptionInfoInternal getSubscriptionInfoInternal(int subId) { 2444 mReadWriteLock.readLock().lock(); 2445 try { 2446 return mAllSubscriptionInfoInternalCache.get(subId); 2447 } finally { 2448 mReadWriteLock.readLock().unlock(); 2449 } 2450 } 2451 2452 /** 2453 * @return All subscription infos in the database. 2454 */ 2455 @NonNull getAllSubscriptions()2456 public List<SubscriptionInfoInternal> getAllSubscriptions() { 2457 mReadWriteLock.readLock().lock(); 2458 try { 2459 return new ArrayList<>(mAllSubscriptionInfoInternalCache.values()); 2460 } finally { 2461 mReadWriteLock.readLock().unlock(); 2462 } 2463 } 2464 2465 /** 2466 * Get subscription info by ICCID. 2467 * 2468 * @param iccId The ICCID of the SIM card. 2469 * @return The subscription info if found. {@code null} if not found. 2470 */ 2471 @Nullable getSubscriptionInfoInternalByIccId(@onNull String iccId)2472 public SubscriptionInfoInternal getSubscriptionInfoInternalByIccId(@NonNull String iccId) { 2473 mReadWriteLock.readLock().lock(); 2474 try { 2475 return mAllSubscriptionInfoInternalCache.values().stream() 2476 .filter(subInfo -> subInfo.getIccId().equals(iccId)) 2477 .findFirst() 2478 .orElse(null); 2479 } finally { 2480 mReadWriteLock.readLock().unlock(); 2481 } 2482 } 2483 2484 /** 2485 * Set the transfer status of the subscriptionInfo that corresponds to subId. 2486 * 2487 * @param subId Subscription ID. 2488 * @param status The transfer status to change. 2489 * 2490 * @throws IllegalArgumentException if the subscription does not exist. 2491 */ setTransferStatus(int subId, int status)2492 public void setTransferStatus(int subId, int status) { 2493 if (!mFeatureFlags.supportPsimToEsimConversion()) { 2494 log("SubscriptionDatabaseManager:supportPsimToEsimConversion is false"); 2495 return; 2496 } 2497 2498 writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_TRANSFER_STATUS, 2499 status, 2500 SubscriptionInfoInternal.Builder::setTransferStatus); 2501 } 2502 2503 /** 2504 * Log debug messages. 2505 * 2506 * @param s debug messages 2507 */ log(@onNull String s)2508 private void log(@NonNull String s) { 2509 Rlog.d(LOG_TAG, s); 2510 } 2511 2512 /** 2513 * Log error messages. 2514 * 2515 * @param s error messages 2516 */ loge(@onNull String s)2517 private void loge(@NonNull String s) { 2518 Rlog.e(LOG_TAG, s); 2519 } 2520 2521 /** 2522 * Log verbose messages. 2523 * 2524 * @param s debug messages. 2525 */ logv(@onNull String s)2526 private void logv(@NonNull String s) { 2527 if (VDBG) Rlog.v(LOG_TAG, s); 2528 } 2529 2530 /** 2531 * Log error messages and also log into the local log. 2532 * 2533 * @param s debug messages 2534 */ logel(@onNull String s)2535 private void logel(@NonNull String s) { 2536 loge(s); 2537 mLocalLog.log(s); 2538 } 2539 2540 /** 2541 * Log debug messages and also log into the local log. 2542 * 2543 * @param s debug messages 2544 */ logl(@onNull String s)2545 private void logl(@NonNull String s) { 2546 log(s); 2547 mLocalLog.log(s); 2548 } 2549 2550 /** 2551 * Dump the state of {@link SubscriptionDatabaseManager}. 2552 * 2553 * @param fd File descriptor 2554 * @param printWriter Print writer 2555 * @param args Arguments 2556 */ dump(@onNull FileDescriptor fd, @NonNull PrintWriter printWriter, @NonNull String[] args)2557 public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter printWriter, 2558 @NonNull String[] args) { 2559 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 2560 pw.println(SubscriptionDatabaseManager.class.getSimpleName() + ":"); 2561 pw.increaseIndent(); 2562 pw.println("All subscriptions:"); 2563 pw.increaseIndent(); 2564 mReadWriteLock.readLock().lock(); 2565 try { 2566 mAllSubscriptionInfoInternalCache.forEach((subId, subInfo) -> pw.println(subInfo)); 2567 } finally { 2568 mReadWriteLock.readLock().unlock(); 2569 } 2570 pw.decreaseIndent(); 2571 pw.println(); 2572 pw.println("mAsyncMode=" + mAsyncMode); 2573 synchronized (this) { 2574 pw.println("mDatabaseInitialized=" + mDatabaseInitialized); 2575 } 2576 pw.println("mReadWriteLock=" + mReadWriteLock); 2577 pw.println(); 2578 pw.println("Local log:"); 2579 pw.increaseIndent(); 2580 mLocalLog.dump(fd, printWriter, args); 2581 pw.decreaseIndent(); 2582 pw.decreaseIndent(); 2583 } 2584 } 2585