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