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