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