1 /* 2 * Copyright (C) 2014 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.services.telephony; 18 19 import android.app.PropertyInvalidatedCache; 20 import android.content.BroadcastReceiver; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.content.pm.PackageManager; 26 import android.content.res.Resources; 27 import android.database.ContentObserver; 28 import android.graphics.Bitmap; 29 import android.graphics.Canvas; 30 import android.graphics.PorterDuff; 31 import android.graphics.drawable.Drawable; 32 import android.graphics.drawable.Icon; 33 import android.net.Uri; 34 import android.os.Bundle; 35 import android.os.Handler; 36 import android.os.HandlerExecutor; 37 import android.os.HandlerThread; 38 import android.os.Looper; 39 import android.os.PersistableBundle; 40 import android.os.UserHandle; 41 import android.provider.Settings; 42 import android.provider.Telephony; 43 import android.telecom.PhoneAccount; 44 import android.telecom.PhoneAccountHandle; 45 import android.telecom.TelecomManager; 46 import android.telephony.CarrierConfigManager; 47 import android.telephony.ServiceState; 48 import android.telephony.SubscriptionInfo; 49 import android.telephony.SubscriptionManager; 50 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 51 import android.telephony.TelephonyCallback; 52 import android.telephony.TelephonyManager; 53 import android.telephony.ims.ImsException; 54 import android.telephony.ims.ImsMmTelManager; 55 import android.telephony.ims.ImsRcsManager; 56 import android.telephony.ims.ImsReasonInfo; 57 import android.telephony.ims.RegistrationManager; 58 import android.telephony.ims.feature.MmTelFeature; 59 import android.telephony.ims.stub.ImsRegistrationImplBase; 60 import android.text.TextUtils; 61 62 import com.android.ims.ImsManager; 63 import com.android.internal.telephony.ExponentialBackoff; 64 import com.android.internal.telephony.Phone; 65 import com.android.internal.telephony.PhoneFactory; 66 import com.android.internal.telephony.SubscriptionController; 67 import com.android.phone.PhoneGlobals; 68 import com.android.phone.PhoneUtils; 69 import com.android.phone.R; 70 import com.android.telephony.Rlog; 71 72 import java.util.Arrays; 73 import java.util.LinkedList; 74 import java.util.List; 75 import java.util.Optional; 76 import java.util.function.Predicate; 77 78 /** 79 * Owns all data we have registered with Telecom including handling dynamic addition and 80 * removal of SIMs and SIP accounts. 81 */ 82 public class TelecomAccountRegistry { 83 private static final boolean DBG = false; /* STOP SHIP if true */ 84 private static final String LOG_TAG = "TelecomAccountRegistry"; 85 86 // This icon is the one that is used when the Slot ID that we have for a particular SIM 87 // is not supported, i.e. SubscriptionManager.INVALID_SLOT_ID or the 5th SIM in a phone. 88 private final static int DEFAULT_SIM_ICON = R.drawable.ic_multi_sim; 89 private final static String GROUP_PREFIX = "group_"; 90 91 private static final int REGISTER_START_DELAY_MS = 1 * 1000; // 1 second 92 private static final int REGISTER_MAXIMUM_DELAY_MS = 60 * 1000; // 1 minute 93 94 /** 95 * Indicates the {@link SubscriptionManager.OnSubscriptionsChangedListener} has not yet been 96 * registered. 97 */ 98 private static final int LISTENER_STATE_UNREGISTERED = 0; 99 100 /** 101 * Indicates the first {@link SubscriptionManager.OnSubscriptionsChangedListener} registration 102 * attempt failed and we are performing backoff registration. 103 */ 104 private static final int LISTENER_STATE_PERFORMING_BACKOFF = 2; 105 106 /** 107 * Indicates the {@link SubscriptionManager.OnSubscriptionsChangedListener} has been registered. 108 */ 109 private static final int LISTENER_STATE_REGISTERED = 3; 110 111 /** 112 * Copy-pasted from android.telecom.PhoneAccount -- hidden constant which is unfortunately being 113 * used by some 1P apps, so we're keeping it here until we can remove it. 114 */ 115 private static final String EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK = 116 "android.telecom.extra.SUPPORTS_VIDEO_CALLING_FALLBACK"; 117 118 private Handler mHandler; 119 120 final class AccountEntry implements PstnPhoneCapabilitiesNotifier.Listener { 121 private final Phone mPhone; 122 private PhoneAccount mAccount; 123 private final PstnIncomingCallNotifier mIncomingCallNotifier; 124 private final PstnPhoneCapabilitiesNotifier mPhoneCapabilitiesNotifier; 125 private boolean mIsEmergency; 126 private boolean mIsRttCapable; 127 private boolean mIsCallComposerCapable; 128 private boolean mIsAdhocConfCapable; 129 private boolean mIsEmergencyPreferred; 130 private MmTelFeature.MmTelCapabilities mMmTelCapabilities; 131 private ImsMmTelManager.CapabilityCallback mMmtelCapabilityCallback; 132 private RegistrationManager.RegistrationCallback mImsRegistrationCallback; 133 private ImsMmTelManager mMmTelManager; 134 private final boolean mIsTestAccount; 135 private boolean mIsVideoCapable; 136 private boolean mIsVideoPresenceSupported; 137 private boolean mIsVideoPauseSupported; 138 private boolean mIsMergeCallSupported; 139 private boolean mIsMergeImsCallSupported; 140 private boolean mIsVideoConferencingSupported; 141 private boolean mIsMergeOfWifiCallsAllowedWhenVoWifiOff; 142 private boolean mIsManageImsConferenceCallSupported; 143 private boolean mIsUsingSimCallManager; 144 private boolean mIsShowPreciseFailedCause; 145 AccountEntry(Phone phone, boolean isEmergency, boolean isTest)146 AccountEntry(Phone phone, boolean isEmergency, boolean isTest) { 147 mPhone = phone; 148 mIsEmergency = isEmergency; 149 mIsTestAccount = isTest; 150 mIsAdhocConfCapable = mPhone.isImsRegistered(); 151 mAccount = registerPstnPhoneAccount(isEmergency, isTest); 152 Log.i(this, "Registered phoneAccount: %s with handle: %s", 153 mAccount, mAccount.getAccountHandle()); 154 mIncomingCallNotifier = new PstnIncomingCallNotifier((Phone) mPhone); 155 mPhoneCapabilitiesNotifier = new PstnPhoneCapabilitiesNotifier((Phone) mPhone, 156 this); 157 158 if (mIsTestAccount || isEmergency) { 159 // For test and emergency entries, there is no sub ID that can be assigned, so do 160 // not register for capabilities callbacks. 161 return; 162 } 163 164 try { 165 if (mPhone.getContext().getPackageManager().hasSystemFeature( 166 PackageManager.FEATURE_TELEPHONY_IMS)) { 167 mMmTelManager = ImsMmTelManager.createForSubscriptionId(getSubId()); 168 } 169 } catch (IllegalArgumentException e) { 170 Log.i(this, "Not registering MmTel capabilities listener because the subid '" 171 + getSubId() + "' is invalid: " + e.getMessage()); 172 return; 173 } 174 175 mMmtelCapabilityCallback = new ImsMmTelManager.CapabilityCallback() { 176 @Override 177 public void onCapabilitiesStatusChanged( 178 MmTelFeature.MmTelCapabilities capabilities) { 179 mMmTelCapabilities = capabilities; 180 updateRttCapability(); 181 updateCallComposerCapability(capabilities); 182 } 183 }; 184 registerMmTelCapabilityCallback(); 185 186 mImsRegistrationCallback = new RegistrationManager.RegistrationCallback() { 187 @Override 188 public void onRegistered(int imsRadioTech) { 189 updateAdhocConfCapability(true); 190 } 191 192 @Override 193 public void onRegistering(int imsRadioTech) { 194 updateAdhocConfCapability(false); 195 } 196 197 @Override 198 public void onUnregistered(ImsReasonInfo imsReasonInfo) { 199 updateAdhocConfCapability(false); 200 } 201 }; 202 registerImsRegistrationCallback(); 203 } 204 teardown()205 void teardown() { 206 mIncomingCallNotifier.teardown(); 207 mPhoneCapabilitiesNotifier.teardown(); 208 if (mMmTelManager != null) { 209 if (mMmtelCapabilityCallback != null) { 210 mMmTelManager.unregisterMmTelCapabilityCallback(mMmtelCapabilityCallback); 211 } 212 213 if (mImsRegistrationCallback != null) { 214 mMmTelManager.unregisterImsRegistrationCallback(mImsRegistrationCallback); 215 } 216 } 217 } 218 registerMmTelCapabilityCallback()219 private void registerMmTelCapabilityCallback() { 220 if (mMmTelManager == null || mMmtelCapabilityCallback == null) { 221 // The subscription id associated with this account is invalid or not associated 222 // with a subscription. Do not register in this case. 223 return; 224 } 225 226 try { 227 mMmTelManager.registerMmTelCapabilityCallback(mContext.getMainExecutor(), 228 mMmtelCapabilityCallback); 229 } catch (ImsException e) { 230 Log.w(this, "registerMmTelCapabilityCallback: registration failed, no ImsService" 231 + " available. Exception: " + e.getMessage()); 232 return; 233 } catch (IllegalArgumentException e) { 234 Log.w(this, "registerMmTelCapabilityCallback: registration failed, invalid" 235 + " subscription, Exception" + e.getMessage()); 236 return; 237 } 238 } 239 registerImsRegistrationCallback()240 private void registerImsRegistrationCallback() { 241 if (mMmTelManager == null || mImsRegistrationCallback == null) { 242 return; 243 } 244 245 try { 246 mMmTelManager.registerImsRegistrationCallback(mContext.getMainExecutor(), 247 mImsRegistrationCallback); 248 } catch (ImsException e) { 249 Log.w(this, "registerImsRegistrationCallback: registration failed, no ImsService" 250 + " available. Exception: " + e.getMessage()); 251 return; 252 } catch (IllegalArgumentException e) { 253 Log.w(this, "registerImsRegistrationCallback: registration failed, invalid" 254 + " subscription, Exception" + e.getMessage()); 255 return; 256 } 257 } 258 259 /** 260 * Trigger re-registration of this account. 261 */ reRegisterPstnPhoneAccount()262 public void reRegisterPstnPhoneAccount() { 263 PhoneAccount newAccount = buildPstnPhoneAccount(mIsEmergency, mIsTestAccount); 264 if (!newAccount.equals(mAccount)) { 265 Log.i(this, "reRegisterPstnPhoneAccount: subId: " + getSubId() 266 + " - re-register due to account change."); 267 mTelecomManager.registerPhoneAccount(newAccount); 268 mAccount = newAccount; 269 } else { 270 Log.i(this, "reRegisterPstnPhoneAccount: subId: " + getSubId() + " - no change"); 271 } 272 } 273 registerPstnPhoneAccount(boolean isEmergency, boolean isTestAccount)274 private PhoneAccount registerPstnPhoneAccount(boolean isEmergency, boolean isTestAccount) { 275 PhoneAccount account = buildPstnPhoneAccount(mIsEmergency, mIsTestAccount); 276 // Register with Telecom and put into the account entry. 277 mTelecomManager.registerPhoneAccount(account); 278 return account; 279 } 280 281 /** 282 * Registers the specified account with Telecom as a PhoneAccountHandle. 283 */ buildPstnPhoneAccount(boolean isEmergency, boolean isTestAccount)284 private PhoneAccount buildPstnPhoneAccount(boolean isEmergency, boolean isTestAccount) { 285 String testPrefix = isTestAccount ? "Test " : ""; 286 287 // Build the Phone account handle. 288 PhoneAccountHandle phoneAccountHandle = 289 PhoneUtils.makePstnPhoneAccountHandleWithPrefix( 290 mPhone, testPrefix, isEmergency); 291 292 // Populate the phone account data. 293 int subId = mPhone.getSubId(); 294 String subscriberId = mPhone.getSubscriberId(); 295 int color = PhoneAccount.NO_HIGHLIGHT_COLOR; 296 int slotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX; 297 String line1Number = mTelephonyManager.getLine1Number(subId); 298 if (line1Number == null) { 299 line1Number = ""; 300 } 301 String subNumber = mPhone.getLine1Number(); 302 if (subNumber == null) { 303 subNumber = ""; 304 } 305 306 String label; 307 String description; 308 Icon icon = null; 309 310 // We can only get the real slotId from the SubInfoRecord, we can't calculate the 311 // slotId from the subId or the phoneId in all instances. 312 SubscriptionInfo record = 313 mSubscriptionManager.getActiveSubscriptionInfo(subId); 314 TelephonyManager tm = mTelephonyManager.createForSubscriptionId(subId); 315 316 if (isEmergency) { 317 label = mContext.getResources().getString(R.string.sim_label_emergency_calls); 318 description = 319 mContext.getResources().getString(R.string.sim_description_emergency_calls); 320 } else if (mTelephonyManager.getPhoneCount() == 1) { 321 // For single-SIM devices, we show the label and description as whatever the name of 322 // the network is. 323 description = label = tm.getNetworkOperatorName(); 324 } else { 325 CharSequence subDisplayName = null; 326 327 if (record != null) { 328 subDisplayName = record.getDisplayName(); 329 slotId = record.getSimSlotIndex(); 330 color = record.getIconTint(); 331 icon = Icon.createWithBitmap(record.createIconBitmap(mContext)); 332 } 333 334 String slotIdString; 335 if (SubscriptionManager.isValidSlotIndex(slotId)) { 336 slotIdString = Integer.toString(slotId); 337 } else { 338 slotIdString = mContext.getResources().getString(R.string.unknown); 339 } 340 341 if (TextUtils.isEmpty(subDisplayName)) { 342 // Either the sub record is not there or it has an empty display name. 343 Log.w(this, "Could not get a display name for subid: %d", subId); 344 subDisplayName = mContext.getResources().getString( 345 R.string.sim_description_default, slotIdString); 346 } 347 348 // The label is user-visible so let's use the display name that the user may 349 // have set in Settings->Sim cards. 350 label = testPrefix + subDisplayName; 351 description = testPrefix + mContext.getResources().getString( 352 R.string.sim_description_default, slotIdString); 353 } 354 355 // By default all SIM phone accounts can place emergency calls. 356 int capabilities = PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION | 357 PhoneAccount.CAPABILITY_CALL_PROVIDER | 358 PhoneAccount.CAPABILITY_MULTI_USER; 359 360 if (mContext.getResources().getBoolean(R.bool.config_pstnCanPlaceEmergencyCalls)) { 361 capabilities |= PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS; 362 } 363 364 mIsEmergencyPreferred = isEmergencyPreferredAccount(subId, mActiveDataSubscriptionId); 365 if (mIsEmergencyPreferred) { 366 capabilities |= PhoneAccount.CAPABILITY_EMERGENCY_PREFERRED; 367 } 368 369 if (isRttCurrentlySupported()) { 370 capabilities |= PhoneAccount.CAPABILITY_RTT; 371 mIsRttCapable = true; 372 } else { 373 mIsRttCapable = false; 374 } 375 376 if (mIsCallComposerCapable) { 377 capabilities |= PhoneAccount.CAPABILITY_CALL_COMPOSER; 378 } 379 380 mIsVideoCapable = mPhone.isVideoEnabled(); 381 boolean isVideoEnabledByPlatform = ImsManager.getInstance(mPhone.getContext(), 382 mPhone.getPhoneId()).isVtEnabledByPlatform(); 383 384 if (!mIsPrimaryUser) { 385 Log.i(this, "Disabling video calling for secondary user."); 386 mIsVideoCapable = false; 387 isVideoEnabledByPlatform = false; 388 } 389 390 if (mIsVideoCapable) { 391 capabilities |= PhoneAccount.CAPABILITY_VIDEO_CALLING; 392 } 393 394 if (isVideoEnabledByPlatform) { 395 capabilities |= PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING; 396 } 397 398 mIsVideoPresenceSupported = isCarrierVideoPresenceSupported(); 399 if (mIsVideoCapable && mIsVideoPresenceSupported) { 400 capabilities |= PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE; 401 } 402 403 if (mIsVideoCapable && isCarrierEmergencyVideoCallsAllowed()) { 404 capabilities |= PhoneAccount.CAPABILITY_EMERGENCY_VIDEO_CALLING; 405 } 406 407 mIsVideoPauseSupported = isCarrierVideoPauseSupported(); 408 Bundle extras = new Bundle(); 409 if (isCarrierInstantLetteringSupported()) { 410 capabilities |= PhoneAccount.CAPABILITY_CALL_SUBJECT; 411 extras.putAll(getPhoneAccountExtras()); 412 } 413 414 if (mIsAdhocConfCapable && isCarrierAdhocConferenceCallSupported()) { 415 capabilities |= PhoneAccount.CAPABILITY_ADHOC_CONFERENCE_CALLING; 416 } else { 417 capabilities &= ~PhoneAccount.CAPABILITY_ADHOC_CONFERENCE_CALLING; 418 } 419 420 final boolean isHandoverFromSupported = mContext.getResources().getBoolean( 421 R.bool.config_support_handover_from); 422 if (isHandoverFromSupported && !isEmergency) { 423 // Only set the extra is handover is supported and this isn't the emergency-only 424 // acct. 425 extras.putBoolean(PhoneAccount.EXTRA_SUPPORTS_HANDOVER_FROM, 426 isHandoverFromSupported); 427 } 428 429 final boolean isTelephonyAudioDeviceSupported = mContext.getResources().getBoolean( 430 R.bool.config_support_telephony_audio_device); 431 if (isTelephonyAudioDeviceSupported && !isEmergency 432 && isCarrierUseCallRecordingTone()) { 433 extras.putBoolean(PhoneAccount.EXTRA_PLAY_CALL_RECORDING_TONE, true); 434 } 435 436 extras.putBoolean(EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK, 437 mContext.getResources() 438 .getBoolean(R.bool.config_support_video_calling_fallback)); 439 440 if (slotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) { 441 extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, slotId); 442 } 443 444 mIsMergeCallSupported = isCarrierMergeCallSupported(); 445 mIsMergeImsCallSupported = isCarrierMergeImsCallSupported(); 446 mIsVideoConferencingSupported = isCarrierVideoConferencingSupported(); 447 mIsMergeOfWifiCallsAllowedWhenVoWifiOff = 448 isCarrierMergeOfWifiCallsAllowedWhenVoWifiOff(); 449 mIsManageImsConferenceCallSupported = isCarrierManageImsConferenceCallSupported(); 450 mIsUsingSimCallManager = isCarrierUsingSimCallManager(); 451 mIsShowPreciseFailedCause = isCarrierShowPreciseFailedCause(); 452 453 if (isEmergency && mContext.getResources().getBoolean( 454 R.bool.config_emergency_account_emergency_calls_only)) { 455 capabilities |= PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY; 456 } 457 458 if (icon == null) { 459 // TODO: Switch to using Icon.createWithResource() once that supports tinting. 460 Resources res = mContext.getResources(); 461 Drawable drawable = res.getDrawable(DEFAULT_SIM_ICON, null); 462 drawable.setTint(res.getColor(R.color.default_sim_icon_tint_color, null)); 463 drawable.setTintMode(PorterDuff.Mode.SRC_ATOP); 464 465 int width = drawable.getIntrinsicWidth(); 466 int height = drawable.getIntrinsicHeight(); 467 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 468 Canvas canvas = new Canvas(bitmap); 469 drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 470 drawable.draw(canvas); 471 472 icon = Icon.createWithBitmap(bitmap); 473 } 474 475 // Check to see if the newly registered account should replace the old account. 476 String groupId = ""; 477 String[] mergedImsis = mTelephonyManager.getMergedSubscriberIds(); 478 boolean isMergedSim = false; 479 if (mergedImsis != null && subscriberId != null && !isEmergency) { 480 for (String imsi : mergedImsis) { 481 if (imsi.equals(subscriberId)) { 482 isMergedSim = true; 483 break; 484 } 485 } 486 } 487 if(isMergedSim) { 488 groupId = GROUP_PREFIX + line1Number; 489 Log.i(this, "Adding Merged Account with group: " + Rlog.pii(LOG_TAG, groupId)); 490 } 491 492 PhoneAccount account = PhoneAccount.builder(phoneAccountHandle, label) 493 .setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, line1Number, null)) 494 .setSubscriptionAddress( 495 Uri.fromParts(PhoneAccount.SCHEME_TEL, subNumber, null)) 496 .setCapabilities(capabilities) 497 .setIcon(icon) 498 .setHighlightColor(color) 499 .setShortDescription(description) 500 .setSupportedUriSchemes(Arrays.asList( 501 PhoneAccount.SCHEME_TEL, PhoneAccount.SCHEME_VOICEMAIL)) 502 .setExtras(extras) 503 .setGroupId(groupId) 504 .build(); 505 506 return account; 507 } 508 getPhoneAccountHandle()509 public PhoneAccountHandle getPhoneAccountHandle() { 510 return mAccount != null ? mAccount.getAccountHandle() : null; 511 } 512 getSubId()513 public int getSubId() { 514 return mPhone.getSubId(); 515 } 516 517 /** 518 * In some cases, we need to try sending the emergency call over this PhoneAccount due to 519 * restrictions and limitations in MSIM configured devices. This includes the following: 520 * 1) The device does not support GNSS SUPL requests on the non-DDS subscription due to 521 * modem limitations. If the device does not support SUPL on non-DDS, we need to try the 522 * emergency call on the DDS subscription first to allow for SUPL to be completed. 523 * 524 * @return true if Telecom should prefer this PhoneAccount, false if there is no preference 525 * needed. 526 */ isEmergencyPreferredAccount(int subId, int activeDataSubId)527 private boolean isEmergencyPreferredAccount(int subId, int activeDataSubId) { 528 Log.d(this, "isEmergencyPreferredAccount: subId=" + subId + ", activeData=" 529 + activeDataSubId); 530 final boolean gnssSuplRequiresDefaultData = mContext.getResources().getBoolean( 531 R.bool.config_gnss_supl_requires_default_data_for_emergency); 532 if (!gnssSuplRequiresDefaultData) { 533 Log.d(this, "isEmergencyPreferredAccount: Device does not require preference."); 534 // No preference is necessary. 535 return false; 536 } 537 538 SubscriptionController controller = SubscriptionController.getInstance(); 539 if (controller == null) { 540 Log.d(this, "isEmergencyPreferredAccount: SubscriptionController not available."); 541 return false; 542 } 543 // Only set an emergency preference on devices with multiple active subscriptions 544 // (include opportunistic subscriptions) in this check. 545 // API says never null, but this can return null in testing. 546 int[] activeSubIds = controller.getActiveSubIdList(false); 547 if (activeSubIds == null || activeSubIds.length <= 1) { 548 Log.d(this, "isEmergencyPreferredAccount: one or less active subscriptions."); 549 return false; 550 } 551 // Check to see if this PhoneAccount is associated with the default Data subscription. 552 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 553 Log.d(this, "isEmergencyPreferredAccount: provided subId " + subId + "is not " 554 + "valid."); 555 return false; 556 } 557 int userDefaultData = controller.getDefaultDataSubId(); 558 boolean isActiveDataValid = SubscriptionManager.isValidSubscriptionId(activeDataSubId); 559 boolean isActiveDataOpportunistic = isActiveDataValid 560 && controller.isOpportunistic(activeDataSubId); 561 // compare the activeDataSubId to the subId specified only if it is valid and not an 562 // opportunistic subscription (only supports data). If not, use the current default 563 // defined by the user. 564 Log.d(this, "isEmergencyPreferredAccount: userDefaultData=" + userDefaultData 565 + ", isActiveDataOppurtunistic=" + isActiveDataOpportunistic); 566 return subId == ((isActiveDataValid && !isActiveDataOpportunistic) ? activeDataSubId : 567 userDefaultData); 568 } 569 570 /** 571 * Determines from carrier configuration whether pausing of IMS video calls is supported. 572 * 573 * @return {@code true} if pausing IMS video calls is supported. 574 */ isCarrierVideoPauseSupported()575 private boolean isCarrierVideoPauseSupported() { 576 // Check if IMS video pause is supported. 577 PersistableBundle b = 578 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 579 return b != null && 580 b.getBoolean(CarrierConfigManager.KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL); 581 } 582 583 /** 584 * Determines from carrier configuration and user setting whether RCS presence indication 585 * for video calls is supported. 586 * 587 * @return {@code true} if RCS presence indication for video calls is supported. 588 */ isCarrierVideoPresenceSupported()589 private boolean isCarrierVideoPresenceSupported() { 590 PersistableBundle b = 591 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 592 if (b == null) return false; 593 594 // If using the new RcsUceAdapter API, this should be true if 595 // KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL is set. If using the old 596 // KEY_USE_RCS_PRESENCE_BOOL key, we have to also check the user setting. 597 return b.getBoolean( 598 CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL) 599 || (b.getBoolean(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL) 600 && isUserContactDiscoverySettingEnabled()); 601 } 602 603 /** 604 * @return true if the user has enabled contact discovery for the subscription associated 605 * with this account entry, false otherwise. 606 */ isUserContactDiscoverySettingEnabled()607 private boolean isUserContactDiscoverySettingEnabled() { 608 try { 609 ImsRcsManager manager = mImsManager.getImsRcsManager(mPhone.getSubId()); 610 return manager.getUceAdapter().isUceSettingEnabled(); 611 } catch (Exception e) { 612 Log.w(LOG_TAG, "isUserContactDiscoverySettingEnabled caught exception: " + e); 613 return false; 614 } 615 } 616 617 /** 618 * Determines from carrier config whether instant lettering is supported. 619 * 620 * @return {@code true} if instant lettering is supported, {@code false} otherwise. 621 */ isCarrierInstantLetteringSupported()622 private boolean isCarrierInstantLetteringSupported() { 623 PersistableBundle b = 624 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 625 return b != null && 626 b.getBoolean(CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL); 627 } 628 629 /** 630 * Determines from carrier config whether adhoc conference calling is supported. 631 * 632 * @return {@code true} if adhoc conference calling is supported, {@code false} otherwise. 633 */ isCarrierAdhocConferenceCallSupported()634 private boolean isCarrierAdhocConferenceCallSupported() { 635 PersistableBundle b = 636 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 637 return b != null && 638 b.getBoolean(CarrierConfigManager.KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL); 639 } 640 641 642 /** 643 * Determines from carrier config whether merging calls is supported. 644 * 645 * @return {@code true} if merging calls is supported, {@code false} otherwise. 646 */ isCarrierMergeCallSupported()647 private boolean isCarrierMergeCallSupported() { 648 PersistableBundle b = 649 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 650 return b != null && 651 b.getBoolean(CarrierConfigManager.KEY_SUPPORT_CONFERENCE_CALL_BOOL); 652 } 653 654 /** 655 * Determines from carrier config whether merging IMS calls is supported. 656 * 657 * @return {@code true} if merging IMS calls is supported, {@code false} otherwise. 658 */ isCarrierMergeImsCallSupported()659 private boolean isCarrierMergeImsCallSupported() { 660 PersistableBundle b = 661 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 662 return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_IMS_CONFERENCE_CALL_BOOL); 663 } 664 665 /** 666 * Determines from carrier config whether emergency video calls are supported. 667 * 668 * @return {@code true} if emergency video calls are allowed, {@code false} otherwise. 669 */ isCarrierEmergencyVideoCallsAllowed()670 private boolean isCarrierEmergencyVideoCallsAllowed() { 671 PersistableBundle b = 672 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 673 return b != null && 674 b.getBoolean(CarrierConfigManager.KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL); 675 } 676 677 /** 678 * Determines from carrier config whether video conferencing is supported. 679 * 680 * @return {@code true} if video conferencing is supported, {@code false} otherwise. 681 */ isCarrierVideoConferencingSupported()682 private boolean isCarrierVideoConferencingSupported() { 683 PersistableBundle b = 684 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 685 return b != null && 686 b.getBoolean(CarrierConfigManager.KEY_SUPPORT_VIDEO_CONFERENCE_CALL_BOOL); 687 } 688 689 /** 690 * Determines from carrier config whether merging of wifi calls is allowed when VoWIFI is 691 * turned off. 692 * 693 * @return {@code true} merging of wifi calls when VoWIFI is disabled should be prevented, 694 * {@code false} otherwise. 695 */ isCarrierMergeOfWifiCallsAllowedWhenVoWifiOff()696 private boolean isCarrierMergeOfWifiCallsAllowedWhenVoWifiOff() { 697 PersistableBundle b = 698 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 699 return b != null && b.getBoolean( 700 CarrierConfigManager.KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL); 701 } 702 703 /** 704 * Determines from carrier config whether managing IMS conference calls is supported. 705 * 706 * @return {@code true} if managing IMS conference calls is supported, 707 * {@code false} otherwise. 708 */ isCarrierManageImsConferenceCallSupported()709 private boolean isCarrierManageImsConferenceCallSupported() { 710 PersistableBundle b = 711 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 712 return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_MANAGE_IMS_CONFERENCE_CALL_BOOL); 713 } 714 715 /** 716 * Determines from carrier config whether the carrier uses a sim call manager. 717 * 718 * @return {@code true} if the carrier uses a sim call manager, 719 * {@code false} otherwise. 720 */ isCarrierUsingSimCallManager()721 private boolean isCarrierUsingSimCallManager() { 722 PersistableBundle b = 723 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 724 return !TextUtils.isEmpty( 725 b.getString(CarrierConfigManager.KEY_DEFAULT_SIM_CALL_MANAGER_STRING)); 726 } 727 728 /** 729 * Determines from carrier config whether showing percise call diconnect cause to user 730 * is supported. 731 * 732 * @return {@code true} if showing percise call diconnect cause to user is supported, 733 * {@code false} otherwise. 734 */ isCarrierShowPreciseFailedCause()735 private boolean isCarrierShowPreciseFailedCause() { 736 PersistableBundle b = 737 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 738 return b.getBoolean(CarrierConfigManager.KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL); 739 } 740 741 /** 742 * Determines from carrier config whether the carrier requires the use of a call recording 743 * tone. 744 * 745 * @return {@code true} if a call recording tone should be used, {@code false} otherwise. 746 */ isCarrierUseCallRecordingTone()747 private boolean isCarrierUseCallRecordingTone() { 748 PersistableBundle b = 749 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 750 return b.getBoolean(CarrierConfigManager.KEY_PLAY_CALL_RECORDING_TONE_BOOL); 751 } 752 753 /** 754 * Determines from carrier config whether to always allow RTT while roaming. 755 */ isCarrierAllowRttWhenRoaming()756 private boolean isCarrierAllowRttWhenRoaming() { 757 PersistableBundle b = 758 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 759 return b.getBoolean(CarrierConfigManager.KEY_RTT_SUPPORTED_WHILE_ROAMING_BOOL); 760 } 761 762 /** 763 * Where a device supports instant lettering and call subjects, retrieves the necessary 764 * PhoneAccount extras for those features. 765 * 766 * @return The {@link PhoneAccount} extras associated with the current subscription. 767 */ getPhoneAccountExtras()768 private Bundle getPhoneAccountExtras() { 769 PersistableBundle b = 770 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); 771 772 int instantLetteringMaxLength = b.getInt( 773 CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_LENGTH_LIMIT_INT); 774 String instantLetteringEncoding = b.getString( 775 CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_ENCODING_STRING); 776 Bundle phoneAccountExtras = new Bundle(); 777 phoneAccountExtras.putInt(PhoneAccount.EXTRA_CALL_SUBJECT_MAX_LENGTH, 778 instantLetteringMaxLength); 779 phoneAccountExtras.putString(PhoneAccount.EXTRA_CALL_SUBJECT_CHARACTER_ENCODING, 780 instantLetteringEncoding); 781 return phoneAccountExtras; 782 } 783 784 /** 785 * Receives callback from {@link PstnPhoneCapabilitiesNotifier} when the video capabilities 786 * have changed. 787 * 788 * @param isVideoCapable {@code true} if video is capable. 789 */ 790 @Override onVideoCapabilitiesChanged(boolean isVideoCapable)791 public void onVideoCapabilitiesChanged(boolean isVideoCapable) { 792 mIsVideoCapable = isVideoCapable; 793 synchronized (mAccountsLock) { 794 if (!mAccounts.contains(this)) { 795 // Account has already been torn down, don't try to register it again. 796 // This handles the case where teardown has already happened, and we got a video 797 // update that lost the race for the mAccountsLock. In such a scenario by the 798 // time we get here, the original phone account could have been torn down. 799 return; 800 } 801 mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount); 802 } 803 } 804 updateAdhocConfCapability(boolean isAdhocConfCapable)805 public void updateAdhocConfCapability(boolean isAdhocConfCapable) { 806 synchronized (mAccountsLock) { 807 if (!mAccounts.contains(this)) { 808 // Account has already been torn down, don't try to register it again. 809 // This handles the case where teardown has already happened, and we got a Ims 810 // registartion update that lost the race for the mAccountsLock. In such a 811 // scenario by the time we get here, the original phone account could have been 812 // torn down. 813 return; 814 } 815 816 if (isAdhocConfCapable != mIsAdhocConfCapable) { 817 Log.i(this, "updateAdhocConfCapability - changed, new value: " 818 + isAdhocConfCapable); 819 mIsAdhocConfCapable = isAdhocConfCapable; 820 mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount); 821 } 822 } 823 } 824 updateVideoPresenceCapability()825 public void updateVideoPresenceCapability() { 826 synchronized (mAccountsLock) { 827 if (!mAccounts.contains(this)) { 828 // Account has already been torn down, don't try to register it again. 829 // This handles the case where teardown has already happened, and we got a Ims 830 // registration update that lost the race for the mAccountsLock. In such a 831 // scenario by the time we get here, the original phone account could have been 832 // torn down. 833 return; 834 } 835 836 boolean isVideoPresenceSupported = isCarrierVideoPresenceSupported(); 837 if (mIsVideoPresenceSupported != isVideoPresenceSupported) { 838 Log.i(this, "updateVideoPresenceCapability for subId=" + mPhone.getSubId() 839 + ", new value= " + isVideoPresenceSupported); 840 mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount); 841 } 842 } 843 } 844 updateRttCapability()845 public void updateRttCapability() { 846 synchronized (mAccountsLock) { 847 if (!mAccounts.contains(this)) { 848 // Account has already been torn down, don't try to register it again. 849 // This handles the case where teardown has already happened, and we got a Ims 850 // registartion update that lost the race for the mAccountsLock. In such a 851 // scenario by the time we get here, the original phone account could have been 852 // torn down. 853 return; 854 } 855 856 boolean isRttEnabled = isRttCurrentlySupported(); 857 if (isRttEnabled != mIsRttCapable) { 858 Log.i(this, "updateRttCapability - changed, new value: " + isRttEnabled); 859 mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount); 860 } 861 } 862 } 863 updateCallComposerCapability(MmTelFeature.MmTelCapabilities capabilities)864 public void updateCallComposerCapability(MmTelFeature.MmTelCapabilities capabilities) { 865 synchronized (mAccountsLock) { 866 if (!mAccounts.contains(this)) { 867 // Account has already been torn down, don't try to register it again. 868 // This handles the case where teardown has already happened, and we got a Ims 869 // registartion update that lost the race for the mAccountsLock. In such a 870 // scenario by the time we get here, the original phone account could have been 871 // torn down. 872 return; 873 } 874 875 boolean isCallComposerCapable = capabilities.isCapable( 876 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_CALL_COMPOSER); 877 if (isCallComposerCapable != mIsCallComposerCapable) { 878 mIsCallComposerCapable = isCallComposerCapable; 879 Log.i(this, "updateCallComposerCapability - changed, new value: " 880 + isCallComposerCapable); 881 mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount); 882 } 883 } 884 } 885 updateDefaultDataSubId(int activeDataSubId)886 public void updateDefaultDataSubId(int activeDataSubId) { 887 synchronized (mAccountsLock) { 888 if (!mAccounts.contains(this)) { 889 // Account has already been torn down, don't try to register it again. 890 // This handles the case where teardown has already happened, and we got a Ims 891 // registartion update that lost the race for the mAccountsLock. In such a 892 // scenario by the time we get here, the original phone account could have been 893 // torn down. 894 return; 895 } 896 897 boolean isEmergencyPreferred = isEmergencyPreferredAccount(mPhone.getSubId(), 898 activeDataSubId); 899 if (isEmergencyPreferred != mIsEmergencyPreferred) { 900 Log.i(this, 901 "updateDefaultDataSubId - changed, new value: " + isEmergencyPreferred); 902 mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount); 903 } 904 } 905 } 906 907 /** 908 * Determines whether RTT is supported given the current state of the 909 * device. 910 */ isRttCurrentlySupported()911 private boolean isRttCurrentlySupported() { 912 // First check the emergency case -- if it's supported and turned on, 913 // we want to present RTT as available on the emergency-only phone account 914 if (mIsEmergency) { 915 // First check whether the device supports it 916 boolean devicesSupportsRtt = 917 mContext.getResources().getBoolean(R.bool.config_support_rtt); 918 boolean deviceSupportsEmergencyRtt = mContext.getResources().getBoolean( 919 R.bool.config_support_simless_emergency_rtt); 920 if (!(deviceSupportsEmergencyRtt && devicesSupportsRtt)) { 921 Log.i(this, "isRttCurrentlySupported -- emergency acct and no device support"); 922 return false; 923 } 924 // Next check whether we're in or near a country that supports it 925 String country = 926 mPhone.getServiceStateTracker().getLocaleTracker() 927 .getLastKnownCountryIso().toLowerCase(); 928 929 String[] supportedCountries = mContext.getResources().getStringArray( 930 R.array.config_simless_emergency_rtt_supported_countries); 931 if (supportedCountries == null || Arrays.stream(supportedCountries).noneMatch( 932 Predicate.isEqual(country))) { 933 Log.i(this, "isRttCurrentlySupported -- emergency acct and" 934 + " not supported in this country: " + country); 935 return false; 936 } 937 938 return true; 939 } 940 941 boolean hasVoiceAvailability = isImsVoiceAvailable(); 942 943 boolean isRttSupported = PhoneGlobals.getInstance().phoneMgr 944 .isRttEnabled(mPhone.getSubId()); 945 946 boolean isRoaming = mTelephonyManager.isNetworkRoaming(mPhone.getSubId()); 947 boolean isOnWfc = mPhone.getImsRegistrationTech() 948 == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN; 949 boolean alwaysAllowWhileRoaming = isCarrierAllowRttWhenRoaming(); 950 951 boolean shouldDisableBecauseRoamingOffWfc = 952 (isRoaming && !isOnWfc) && !alwaysAllowWhileRoaming; 953 954 Log.i(this, "isRttCurrentlySupported -- regular acct," 955 + " hasVoiceAvailability: " + hasVoiceAvailability + "\n" 956 + " isRttSupported: " + isRttSupported + "\n" 957 + " alwaysAllowWhileRoaming: " + alwaysAllowWhileRoaming + "\n" 958 + " isRoaming: " + isRoaming + "\n" 959 + " isOnWfc: " + isOnWfc + "\n"); 960 961 return hasVoiceAvailability && isRttSupported && !shouldDisableBecauseRoamingOffWfc; 962 } 963 964 /** 965 * Indicates whether this account supports pausing video calls. 966 * @return {@code true} if the account supports pausing video calls, {@code false} 967 * otherwise. 968 */ isVideoPauseSupported()969 public boolean isVideoPauseSupported() { 970 return mIsVideoCapable && mIsVideoPauseSupported; 971 } 972 973 /** 974 * Indicates whether this account supports merging calls (i.e. conferencing). 975 * @return {@code true} if the account supports merging calls, {@code false} otherwise. 976 */ isMergeCallSupported()977 public boolean isMergeCallSupported() { 978 return mIsMergeCallSupported; 979 } 980 981 /** 982 * Indicates whether this account supports merging IMS calls (i.e. conferencing). 983 * @return {@code true} if the account supports merging IMS calls, {@code false} otherwise. 984 */ isMergeImsCallSupported()985 public boolean isMergeImsCallSupported() { 986 return mIsMergeImsCallSupported; 987 } 988 989 /** 990 * Indicates whether this account supports video conferencing. 991 * @return {@code true} if the account supports video conferencing, {@code false} otherwise. 992 */ isVideoConferencingSupported()993 public boolean isVideoConferencingSupported() { 994 return mIsVideoConferencingSupported; 995 } 996 997 /** 998 * Indicate whether this account allow merging of wifi calls when VoWIFI is off. 999 * @return {@code true} if allowed, {@code false} otherwise. 1000 */ isMergeOfWifiCallsAllowedWhenVoWifiOff()1001 public boolean isMergeOfWifiCallsAllowedWhenVoWifiOff() { 1002 return mIsMergeOfWifiCallsAllowedWhenVoWifiOff; 1003 } 1004 1005 /** 1006 * Indicates whether this account supports managing IMS conference calls 1007 * @return {@code true} if the account supports managing IMS conference calls, 1008 * {@code false} otherwise. 1009 */ isManageImsConferenceCallSupported()1010 public boolean isManageImsConferenceCallSupported() { 1011 return mIsManageImsConferenceCallSupported; 1012 } 1013 1014 /** 1015 * Indicates whether this account uses a sim call manger. 1016 * @return {@code true} if the account uses a sim call manager, 1017 * {@code false} otherwise. 1018 */ isUsingSimCallManager()1019 public boolean isUsingSimCallManager() { 1020 return mIsUsingSimCallManager; 1021 } 1022 1023 /** 1024 * Indicates whether this account supports showing the precise call disconnect cause 1025 * to user (i.e. conferencing). 1026 * @return {@code true} if the account supports showing the precise call disconnect cause, 1027 * {@code false} otherwise. 1028 */ isShowPreciseFailedCause()1029 public boolean isShowPreciseFailedCause() { 1030 return mIsShowPreciseFailedCause; 1031 } 1032 isImsVoiceAvailable()1033 private boolean isImsVoiceAvailable() { 1034 if (mMmTelCapabilities != null) { 1035 return mMmTelCapabilities.isCapable( 1036 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE); 1037 } 1038 1039 if (mMmTelManager == null) { 1040 // The Subscription is invalid, so IMS is unavailable. 1041 return false; 1042 } 1043 1044 // In the rare case that mMmTelCapabilities hasn't been set, try fetching it 1045 // directly and register callback. 1046 registerMmTelCapabilityCallback(); 1047 return mMmTelManager.isAvailable(ImsRegistrationImplBase.REGISTRATION_TECH_LTE, 1048 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE) 1049 || mMmTelManager.isAvailable(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, 1050 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE) 1051 || mMmTelManager.isAvailable( 1052 ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM, 1053 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE); 1054 } 1055 } 1056 1057 private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener = 1058 new OnSubscriptionsChangedListener() { 1059 @Override 1060 public void onSubscriptionsChanged() { 1061 if (mSubscriptionListenerState != LISTENER_STATE_REGISTERED) { 1062 mRegisterSubscriptionListenerBackoff.stop(); 1063 mHandlerThread.quitSafely(); 1064 } 1065 mSubscriptionListenerState = LISTENER_STATE_REGISTERED; 1066 1067 // Any time the SubscriptionInfo changes rerun the setup 1068 Log.i(this, "TelecomAccountRegistry: onSubscriptionsChanged - update accounts"); 1069 tearDownAccounts(); 1070 setupAccounts(); 1071 } 1072 1073 @Override 1074 public void onAddListenerFailed() { 1075 // Woe! Failed to add the listener! 1076 Log.w(this, "TelecomAccountRegistry: onAddListenerFailed - failed to register " 1077 + "OnSubscriptionsChangedListener"); 1078 1079 // Even though registering the listener failed, we will still try to setup the phone 1080 // accounts now; the phone instances should already be present and ready, so even if 1081 // telephony registry is poking along we can still try to setup the phone account. 1082 tearDownAccounts(); 1083 setupAccounts(); 1084 1085 if (mSubscriptionListenerState == LISTENER_STATE_UNREGISTERED) { 1086 // Initial registration attempt failed; start exponential backoff. 1087 mSubscriptionListenerState = LISTENER_STATE_PERFORMING_BACKOFF; 1088 mRegisterSubscriptionListenerBackoff.start(); 1089 } else { 1090 // We're already doing exponential backoff and a registration failed. 1091 mRegisterSubscriptionListenerBackoff.notifyFailed(); 1092 } 1093 } 1094 }; 1095 1096 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 1097 @Override 1098 public void onReceive(Context context, Intent intent) { 1099 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 1100 Log.i(this, "TelecomAccountRegistry: User changed, re-registering phone accounts."); 1101 1102 UserHandle currentUser = intent.getParcelableExtra(Intent.EXTRA_USER); 1103 mIsPrimaryUser = currentUser == null ? true : currentUser.isSystem(); 1104 1105 // Any time the user changes, re-register the accounts. 1106 tearDownAccounts(); 1107 setupAccounts(); 1108 } else if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals( 1109 intent.getAction())) { 1110 Log.i(this, "Carrier-config changed, checking for phone account updates."); 1111 int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, 1112 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 1113 handleCarrierConfigChange(subId); 1114 } 1115 } 1116 }; 1117 1118 private BroadcastReceiver mLocaleChangeReceiver = new BroadcastReceiver() { 1119 @Override 1120 public void onReceive(Context context, Intent intent) { 1121 Log.i(this, "Locale change; re-registering phone accounts."); 1122 tearDownAccounts(); 1123 setupAccounts(); 1124 } 1125 }; 1126 1127 private final TelephonyCallback mTelephonyCallback = new TelecomAccountTelephonyCallback(); 1128 1129 private class TelecomAccountTelephonyCallback extends TelephonyCallback implements 1130 TelephonyCallback.ActiveDataSubscriptionIdListener, 1131 TelephonyCallback.ServiceStateListener { 1132 @Override onServiceStateChanged(ServiceState serviceState)1133 public void onServiceStateChanged(ServiceState serviceState) { 1134 int newState = serviceState.getState(); 1135 if (newState == ServiceState.STATE_IN_SERVICE && mServiceState != newState) { 1136 tearDownAccounts(); 1137 setupAccounts(); 1138 } else { 1139 synchronized (mAccountsLock) { 1140 for (AccountEntry account : mAccounts) { 1141 account.updateRttCapability(); 1142 } 1143 } 1144 } 1145 mServiceState = newState; 1146 } 1147 1148 @Override onActiveDataSubscriptionIdChanged(int subId)1149 public void onActiveDataSubscriptionIdChanged(int subId) { 1150 mActiveDataSubscriptionId = subId; 1151 synchronized (mAccountsLock) { 1152 for (AccountEntry account : mAccounts) { 1153 account.updateDefaultDataSubId(mActiveDataSubscriptionId); 1154 } 1155 } 1156 } 1157 } 1158 1159 private static TelecomAccountRegistry sInstance; 1160 private final Context mContext; 1161 private final TelecomManager mTelecomManager; 1162 private final android.telephony.ims.ImsManager mImsManager; 1163 private final TelephonyManager mTelephonyManager; 1164 private final SubscriptionManager mSubscriptionManager; 1165 private List<AccountEntry> mAccounts = new LinkedList<AccountEntry>(); 1166 private final Object mAccountsLock = new Object(); 1167 private int mSubscriptionListenerState = LISTENER_STATE_UNREGISTERED; 1168 private int mServiceState = ServiceState.STATE_POWER_OFF; 1169 private int mActiveDataSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 1170 private boolean mIsPrimaryUser = true; 1171 private ExponentialBackoff mRegisterSubscriptionListenerBackoff; 1172 private final HandlerThread mHandlerThread = new HandlerThread("TelecomAccountRegistry"); 1173 1174 // TODO: Remove back-pointer from app singleton to Service, since this is not a preferred 1175 // pattern; redesign. This was added to fix a late release bug. 1176 private TelephonyConnectionService mTelephonyConnectionService; 1177 1178 // Used to register subscription changed listener when initial attempts fail. 1179 private Runnable mRegisterOnSubscriptionsChangedListenerRunnable = new Runnable() { 1180 @Override 1181 public void run() { 1182 if (mSubscriptionListenerState != LISTENER_STATE_REGISTERED) { 1183 Log.i(this, "TelecomAccountRegistry: performing delayed register."); 1184 SubscriptionManager.from(mContext).addOnSubscriptionsChangedListener( 1185 mOnSubscriptionsChangedListener); 1186 } 1187 } 1188 }; 1189 TelecomAccountRegistry(Context context)1190 TelecomAccountRegistry(Context context) { 1191 mContext = context; 1192 mTelecomManager = context.getSystemService(TelecomManager.class); 1193 mImsManager = context.getSystemService(android.telephony.ims.ImsManager.class); 1194 mTelephonyManager = TelephonyManager.from(context); 1195 mSubscriptionManager = SubscriptionManager.from(context); 1196 mHandlerThread.start(); 1197 mHandler = new Handler(Looper.getMainLooper()); 1198 mRegisterSubscriptionListenerBackoff = new ExponentialBackoff( 1199 REGISTER_START_DELAY_MS, 1200 REGISTER_MAXIMUM_DELAY_MS, 1201 2, /* multiplier */ 1202 mHandlerThread.getLooper(), 1203 mRegisterOnSubscriptionsChangedListenerRunnable); 1204 } 1205 1206 /** 1207 * Get the singleton instance. 1208 */ getInstance(Context context)1209 public static synchronized TelecomAccountRegistry getInstance(Context context) { 1210 if (sInstance == null && context != null) { 1211 sInstance = new TelecomAccountRegistry(context); 1212 } 1213 return sInstance; 1214 } 1215 setTelephonyConnectionService(TelephonyConnectionService telephonyConnectionService)1216 void setTelephonyConnectionService(TelephonyConnectionService telephonyConnectionService) { 1217 this.mTelephonyConnectionService = telephonyConnectionService; 1218 } 1219 getTelephonyConnectionService()1220 public TelephonyConnectionService getTelephonyConnectionService() { 1221 return mTelephonyConnectionService; 1222 } 1223 1224 /** 1225 * Determines if the {@link AccountEntry} associated with a {@link PhoneAccountHandle} supports 1226 * pausing video calls. 1227 * 1228 * @param handle The {@link PhoneAccountHandle}. 1229 * @return {@code True} if video pausing is supported. 1230 */ isVideoPauseSupported(PhoneAccountHandle handle)1231 boolean isVideoPauseSupported(PhoneAccountHandle handle) { 1232 synchronized (mAccountsLock) { 1233 for (AccountEntry entry : mAccounts) { 1234 if (entry.getPhoneAccountHandle().equals(handle)) { 1235 return entry.isVideoPauseSupported(); 1236 } 1237 } 1238 } 1239 return false; 1240 } 1241 1242 /** 1243 * Determines if the {@link AccountEntry} associated with a {@link PhoneAccountHandle} supports 1244 * merging calls. 1245 * 1246 * @param handle The {@link PhoneAccountHandle}. 1247 * @return {@code True} if merging calls is supported. 1248 */ isMergeCallSupported(PhoneAccountHandle handle)1249 public boolean isMergeCallSupported(PhoneAccountHandle handle) { 1250 synchronized (mAccountsLock) { 1251 for (AccountEntry entry : mAccounts) { 1252 if (entry.getPhoneAccountHandle().equals(handle)) { 1253 return entry.isMergeCallSupported(); 1254 } 1255 } 1256 } 1257 return false; 1258 } 1259 1260 /** 1261 * Determines if the {@link AccountEntry} associated with a {@link PhoneAccountHandle} supports 1262 * video conferencing. 1263 * 1264 * @param handle The {@link PhoneAccountHandle}. 1265 * @return {@code True} if video conferencing is supported. 1266 */ isVideoConferencingSupported(PhoneAccountHandle handle)1267 public boolean isVideoConferencingSupported(PhoneAccountHandle handle) { 1268 synchronized (mAccountsLock) { 1269 for (AccountEntry entry : mAccounts) { 1270 if (entry.getPhoneAccountHandle().equals(handle)) { 1271 return entry.isVideoConferencingSupported(); 1272 } 1273 } 1274 } 1275 return false; 1276 } 1277 1278 /** 1279 * Determines if the {@link AccountEntry} associated with a {@link PhoneAccountHandle} allows 1280 * merging of wifi calls when VoWIFI is disabled. 1281 * 1282 * @param handle The {@link PhoneAccountHandle}. 1283 * @return {@code True} if merging of wifi calls is allowed when VoWIFI is disabled. 1284 */ isMergeOfWifiCallsAllowedWhenVoWifiOff(final PhoneAccountHandle handle)1285 public boolean isMergeOfWifiCallsAllowedWhenVoWifiOff(final PhoneAccountHandle handle) { 1286 synchronized (mAccountsLock) { 1287 Optional<AccountEntry> result = mAccounts.stream().filter( 1288 entry -> entry.getPhoneAccountHandle().equals(handle)).findFirst(); 1289 1290 if (result.isPresent()) { 1291 return result.get().isMergeOfWifiCallsAllowedWhenVoWifiOff(); 1292 } else { 1293 return false; 1294 } 1295 } 1296 } 1297 1298 /** 1299 * Determines if the {@link AccountEntry} associated with a {@link PhoneAccountHandle} supports 1300 * merging IMS calls. 1301 * 1302 * @param handle The {@link PhoneAccountHandle}. 1303 * @return {@code True} if merging IMS calls is supported. 1304 */ isMergeImsCallSupported(PhoneAccountHandle handle)1305 public boolean isMergeImsCallSupported(PhoneAccountHandle handle) { 1306 synchronized (mAccountsLock) { 1307 for (AccountEntry entry : mAccounts) { 1308 if (entry.getPhoneAccountHandle().equals(handle)) { 1309 return entry.isMergeImsCallSupported(); 1310 } 1311 } 1312 } 1313 return false; 1314 } 1315 1316 /** 1317 * Determines if the {@link AccountEntry} associated with a {@link PhoneAccountHandle} supports 1318 * managing IMS conference calls. 1319 * 1320 * @param handle The {@link PhoneAccountHandle}. 1321 * @return {@code True} if managing IMS conference calls is supported. 1322 */ isManageImsConferenceCallSupported(PhoneAccountHandle handle)1323 boolean isManageImsConferenceCallSupported(PhoneAccountHandle handle) { 1324 synchronized (mAccountsLock) { 1325 for (AccountEntry entry : mAccounts) { 1326 if (entry.getPhoneAccountHandle().equals(handle)) { 1327 return entry.isManageImsConferenceCallSupported(); 1328 } 1329 } 1330 } 1331 return false; 1332 } 1333 1334 /** 1335 * showing precise call disconnect cause to the user. 1336 * 1337 * @param handle The {@link PhoneAccountHandle}. 1338 * @return {@code True} if showing precise call disconnect cause to the user is supported. 1339 */ isShowPreciseFailedCause(PhoneAccountHandle handle)1340 boolean isShowPreciseFailedCause(PhoneAccountHandle handle) { 1341 synchronized (mAccountsLock) { 1342 for (AccountEntry entry : mAccounts) { 1343 if (entry.getPhoneAccountHandle().equals(handle)) { 1344 return entry.isShowPreciseFailedCause(); 1345 } 1346 } 1347 } 1348 return false; 1349 } 1350 1351 /** 1352 * @return Reference to the {@code TelecomAccountRegistry}'s subscription manager. 1353 */ getSubscriptionManager()1354 SubscriptionManager getSubscriptionManager() { 1355 return mSubscriptionManager; 1356 } 1357 1358 /** 1359 * Returns the address (e.g. the phone number) associated with a subscription. 1360 * 1361 * @param handle The phone account handle to find the subscription address for. 1362 * @return The address. 1363 */ getAddress(PhoneAccountHandle handle)1364 public Uri getAddress(PhoneAccountHandle handle) { 1365 synchronized (mAccountsLock) { 1366 for (AccountEntry entry : mAccounts) { 1367 if (entry.getPhoneAccountHandle().equals(handle)) { 1368 return entry.mAccount.getAddress(); 1369 } 1370 } 1371 } 1372 return null; 1373 } 1374 refreshAdhocConference(boolean isEnableAdhocConf)1375 public void refreshAdhocConference(boolean isEnableAdhocConf) { 1376 synchronized (mAccountsLock) { 1377 Log.v(this, "refreshAdhocConference isEnable = " + isEnableAdhocConf); 1378 for (AccountEntry entry : mAccounts) { 1379 boolean hasAdhocConfCapability = entry.mAccount.hasCapabilities( 1380 PhoneAccount.CAPABILITY_ADHOC_CONFERENCE_CALLING); 1381 if (!isEnableAdhocConf && hasAdhocConfCapability) { 1382 entry.updateAdhocConfCapability(isEnableAdhocConf); 1383 } else if (isEnableAdhocConf && !hasAdhocConfCapability) { 1384 entry.updateAdhocConfCapability(entry.mPhone.isImsRegistered()); 1385 } 1386 } 1387 } 1388 } 1389 1390 /** 1391 * Returns whethere a the subscription associated with a {@link PhoneAccountHandle} is using a 1392 * sim call manager. 1393 * 1394 * @param handle The phone account handle to find the subscription address for. 1395 * @return {@code true} if a sim call manager is in use, {@code false} otherwise. 1396 */ isUsingSimCallManager(PhoneAccountHandle handle)1397 public boolean isUsingSimCallManager(PhoneAccountHandle handle) { 1398 synchronized (mAccountsLock) { 1399 for (AccountEntry entry : mAccounts) { 1400 if (entry.getPhoneAccountHandle().equals(handle)) { 1401 return entry.isUsingSimCallManager(); 1402 } 1403 } 1404 } 1405 return false; 1406 } 1407 1408 /** 1409 * Sets up all the phone accounts for SIMs on first boot. 1410 */ setupOnBoot()1411 public void setupOnBoot() { 1412 // TODO: When this object "finishes" we should unregister by invoking 1413 // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener); 1414 // This is not strictly necessary because it will be unregistered if the 1415 // notification fails but it is good form. 1416 1417 // Register for SubscriptionInfo list changes which is guaranteed 1418 // to invoke onSubscriptionsChanged the first time. 1419 Log.i(this, "TelecomAccountRegistry: setupOnBoot - register subscription listener"); 1420 SubscriptionManager.from(mContext).addOnSubscriptionsChangedListener( 1421 mOnSubscriptionsChangedListener); 1422 1423 // We also need to listen for changes to the service state (e.g. emergency -> in service) 1424 // because this could signal a removal or addition of a SIM in a single SIM phone. 1425 mTelephonyManager.registerTelephonyCallback(TelephonyManager.INCLUDE_LOCATION_DATA_NONE, 1426 new HandlerExecutor(mHandler), 1427 mTelephonyCallback); 1428 1429 // Listen for user switches. When the user switches, we need to ensure that if the current 1430 // use is not the primary user we disable video calling. 1431 IntentFilter filter = new IntentFilter(); 1432 filter.addAction(Intent.ACTION_USER_SWITCHED); 1433 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 1434 mContext.registerReceiver(mReceiver, filter); 1435 1436 //We also need to listen for locale changes 1437 //(e.g. system language changed -> SIM card name changed) 1438 IntentFilter localeChangeFilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED); 1439 localeChangeFilter.addAction(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED); 1440 mContext.registerReceiver(mLocaleChangeReceiver, localeChangeFilter); 1441 1442 registerContentObservers(); 1443 } 1444 registerContentObservers()1445 private void registerContentObservers() { 1446 // Listen to the RTT system setting so that we update it when the user flips it. 1447 ContentObserver rttUiSettingObserver = new ContentObserver(mHandler) { 1448 @Override 1449 public void onChange(boolean selfChange) { 1450 synchronized (mAccountsLock) { 1451 for (AccountEntry account : mAccounts) { 1452 account.updateRttCapability(); 1453 } 1454 } 1455 } 1456 }; 1457 1458 Uri rttSettingUri = Settings.Secure.getUriFor(Settings.Secure.RTT_CALLING_MODE); 1459 mContext.getContentResolver().registerContentObserver( 1460 rttSettingUri, false, rttUiSettingObserver); 1461 1462 // Listen to the changes to the user's Contacts Discovery Setting. 1463 ContentObserver contactDiscoveryObserver = new ContentObserver(mHandler) { 1464 @Override 1465 public void onChange(boolean selfChange) { 1466 synchronized (mAccountsLock) { 1467 for (AccountEntry account : mAccounts) { 1468 account.updateVideoPresenceCapability(); 1469 } 1470 } 1471 } 1472 }; 1473 Uri contactDiscUri = Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI, 1474 Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED); 1475 mContext.getContentResolver().registerContentObserver( 1476 contactDiscUri, true /*notifyForDescendants*/, contactDiscoveryObserver); 1477 } 1478 1479 /** 1480 * Determines if the list of {@link AccountEntry}(s) contains an {@link AccountEntry} with a 1481 * specified {@link PhoneAccountHandle}. 1482 * 1483 * @param handle The {@link PhoneAccountHandle}. 1484 * @return {@code True} if an entry exists. 1485 */ hasAccountEntryForPhoneAccount(PhoneAccountHandle handle)1486 boolean hasAccountEntryForPhoneAccount(PhoneAccountHandle handle) { 1487 synchronized (mAccountsLock) { 1488 for (AccountEntry entry : mAccounts) { 1489 if (entry.getPhoneAccountHandle().equals(handle)) { 1490 return true; 1491 } 1492 } 1493 } 1494 return false; 1495 } 1496 getPhoneAccountHandleForSubId(int subId)1497 PhoneAccountHandle getPhoneAccountHandleForSubId(int subId) { 1498 synchronized (mAccountsLock) { 1499 for (AccountEntry entry : mAccounts) { 1500 if (entry.getSubId() == subId) { 1501 return entry.getPhoneAccountHandle(); 1502 } 1503 } 1504 } 1505 return null; 1506 } 1507 1508 /** 1509 * Un-registers any {@link PhoneAccount}s which are no longer present in the list 1510 * {@code AccountEntry}(s). 1511 */ cleanupPhoneAccounts()1512 private void cleanupPhoneAccounts() { 1513 ComponentName telephonyComponentName = 1514 new ComponentName(mContext, TelephonyConnectionService.class); 1515 // This config indicates whether the emergency account was flagged as emergency calls only 1516 // in which case we need to consider all phone accounts, not just the call capable ones. 1517 final boolean emergencyCallsOnlyEmergencyAccount = mContext.getResources().getBoolean( 1518 R.bool.config_emergency_account_emergency_calls_only); 1519 List<PhoneAccountHandle> accountHandles = emergencyCallsOnlyEmergencyAccount 1520 ? mTelecomManager.getAllPhoneAccountHandles() 1521 : mTelecomManager.getCallCapablePhoneAccounts(); 1522 1523 for (PhoneAccountHandle handle : accountHandles) { 1524 if (telephonyComponentName.equals(handle.getComponentName()) && 1525 !hasAccountEntryForPhoneAccount(handle)) { 1526 Log.i(this, "Unregistering phone account %s.", handle); 1527 mTelecomManager.unregisterPhoneAccount(handle); 1528 } 1529 } 1530 } 1531 setupAccounts()1532 private void setupAccounts() { 1533 // Go through SIM-based phones and register ourselves -- registering an existing account 1534 // will cause the existing entry to be replaced. 1535 Phone[] phones = PhoneFactory.getPhones(); 1536 Log.i(this, "setupAccounts: Found %d phones. Attempting to register.", phones.length); 1537 1538 final boolean phoneAccountsEnabled = mContext.getResources().getBoolean( 1539 R.bool.config_pstn_phone_accounts_enabled); 1540 1541 synchronized (mAccountsLock) { 1542 try { 1543 if (phoneAccountsEnabled) { 1544 for (Phone phone : phones) { 1545 int subscriptionId = phone.getSubId(); 1546 Log.i(this, "setupAccounts: Phone with subscription id %d", subscriptionId); 1547 // setupAccounts can be called multiple times during service changes. 1548 // Don't add an account if the Icc has not been set yet. 1549 if (!SubscriptionManager.isValidSubscriptionId(subscriptionId) 1550 || phone.getFullIccSerialNumber() == null) { 1551 Log.d(this, "setupAccounts: skipping invalid subid %d", subscriptionId); 1552 continue; 1553 } 1554 // Don't add account if it's opportunistic subscription, which is considered 1555 // data only for now. 1556 SubscriptionInfo info = SubscriptionManager.from(mContext) 1557 .getActiveSubscriptionInfo(subscriptionId); 1558 if (info == null || info.isOpportunistic()) { 1559 Log.d(this, "setupAccounts: skipping unknown or opportunistic subid %d", 1560 subscriptionId); 1561 continue; 1562 } 1563 1564 mAccounts.add(new AccountEntry(phone, false /* emergency */, 1565 false /* isTest */)); 1566 } 1567 } 1568 } finally { 1569 // If we did not list ANY accounts, we need to provide a "default" SIM account 1570 // for emergency numbers since no actual SIM is needed for dialing emergency 1571 // numbers but a phone account is. 1572 if (mAccounts.isEmpty()) { 1573 Log.i(this, "setupAccounts: adding default"); 1574 mAccounts.add( 1575 new AccountEntry(PhoneFactory.getDefaultPhone(), true /* emergency */, 1576 false /* isTest */)); 1577 } 1578 } 1579 1580 // Add a fake account entry. 1581 if (DBG && phones.length > 0 && "TRUE".equals(System.getProperty("test_sim"))) { 1582 mAccounts.add(new AccountEntry(phones[0], false /* emergency */, 1583 true /* isTest */)); 1584 } 1585 } 1586 1587 // Clean up any PhoneAccounts that are no longer relevant 1588 cleanupPhoneAccounts(); 1589 } 1590 tearDownAccounts()1591 private void tearDownAccounts() { 1592 synchronized (mAccountsLock) { 1593 for (AccountEntry entry : mAccounts) { 1594 entry.teardown(); 1595 } 1596 mAccounts.clear(); 1597 } 1598 // Invalidate the TelephonyManager cache which maps phone account handles to sub ids since 1599 // all the phone account handles are being recreated at this point. 1600 PropertyInvalidatedCache.invalidateCache(TelephonyManager.CACHE_KEY_PHONE_ACCOUNT_TO_SUBID); 1601 } 1602 1603 /** 1604 * Handles changes to the carrier configuration which may impact a phone account. There are 1605 * some extras defined in the {@link PhoneAccount} which are based on carrier config options. 1606 * Only checking for carrier config changes when the subscription is configured runs the risk of 1607 * missing carrier config changes which happen later. 1608 * @param subId The subid the carrier config changed for, if applicable. Will be 1609 * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if not specified. 1610 */ handleCarrierConfigChange(int subId)1611 private void handleCarrierConfigChange(int subId) { 1612 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 1613 return; 1614 } 1615 synchronized (mAccountsLock) { 1616 for (AccountEntry entry : mAccounts) { 1617 if (entry.getSubId() == subId) { 1618 Log.d(this, "handleCarrierConfigChange: subId=%d, accountSubId=%d", subId, 1619 entry.getSubId()); 1620 entry.reRegisterPstnPhoneAccount(); 1621 } 1622 } 1623 } 1624 } 1625 } 1626