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