• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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