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