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