1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.services.telephony;
18 
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.res.Resources;
22 import android.graphics.Bitmap;
23 import android.graphics.Canvas;
24 import android.graphics.PorterDuff;
25 import android.graphics.drawable.Drawable;
26 import android.graphics.drawable.Icon;
27 import android.net.Uri;
28 import android.os.Bundle;
29 import android.os.PersistableBundle;
30 import android.os.ServiceManager;
31 import android.telecom.PhoneAccount;
32 import android.telecom.PhoneAccountHandle;
33 import android.telecom.TelecomManager;
34 import android.telephony.CarrierConfigManager;
35 import android.telephony.PhoneStateListener;
36 import android.telephony.ServiceState;
37 import android.telephony.SubscriptionInfo;
38 import android.telephony.SubscriptionManager;
39 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
40 import android.telephony.TelephonyManager;
41 import android.text.TextUtils;
42 
43 import com.android.internal.telephony.IPhoneSubInfo;
44 import com.android.internal.telephony.Phone;
45 import com.android.internal.telephony.PhoneFactory;
46 import com.android.phone.PhoneGlobals;
47 import com.android.phone.PhoneUtils;
48 import com.android.phone.R;
49 
50 import java.util.Arrays;
51 import java.util.LinkedList;
52 import java.util.List;
53 
54 /**
55  * Owns all data we have registered with Telecom including handling dynamic addition and
56  * removal of SIMs and SIP accounts.
57  */
58 final class TelecomAccountRegistry {
59     private static final boolean DBG = false; /* STOP SHIP if true */
60 
61     // This icon is the one that is used when the Slot ID that we have for a particular SIM
62     // is not supported, i.e. SubscriptionManager.INVALID_SLOT_ID or the 5th SIM in a phone.
63     private final static int DEFAULT_SIM_ICON =  R.drawable.ic_multi_sim;
64 
65     final class AccountEntry implements PstnPhoneCapabilitiesNotifier.Listener {
66         private final Phone mPhone;
67         private final PhoneAccount mAccount;
68         private final PstnIncomingCallNotifier mIncomingCallNotifier;
69         private final PstnPhoneCapabilitiesNotifier mPhoneCapabilitiesNotifier;
70         private boolean mIsVideoCapable;
71         private boolean mIsVideoPresenceSupported;
72         private boolean mIsVideoPauseSupported;
73         private boolean mIsMergeCallSupported;
74 
AccountEntry(Phone phone, boolean isEmergency, boolean isDummy)75         AccountEntry(Phone phone, boolean isEmergency, boolean isDummy) {
76             mPhone = phone;
77             mAccount = registerPstnPhoneAccount(isEmergency, isDummy);
78             Log.i(this, "Registered phoneAccount: %s with handle: %s",
79                     mAccount, mAccount.getAccountHandle());
80             mIncomingCallNotifier = new PstnIncomingCallNotifier((Phone) mPhone);
81             mPhoneCapabilitiesNotifier = new PstnPhoneCapabilitiesNotifier((Phone) mPhone,
82                     this);
83         }
84 
teardown()85         void teardown() {
86             mIncomingCallNotifier.teardown();
87             mPhoneCapabilitiesNotifier.teardown();
88         }
89 
90         /**
91          * Registers the specified account with Telecom as a PhoneAccountHandle.
92          */
registerPstnPhoneAccount(boolean isEmergency, boolean isDummyAccount)93         private PhoneAccount registerPstnPhoneAccount(boolean isEmergency, boolean isDummyAccount) {
94             String dummyPrefix = isDummyAccount ? "Dummy " : "";
95 
96             // Build the Phone account handle.
97             PhoneAccountHandle phoneAccountHandle =
98                     PhoneUtils.makePstnPhoneAccountHandleWithPrefix(
99                             mPhone, dummyPrefix, isEmergency);
100 
101             // Populate the phone account data.
102             int subId = mPhone.getSubId();
103             int color = PhoneAccount.NO_HIGHLIGHT_COLOR;
104             int slotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
105             String line1Number = mTelephonyManager.getLine1Number(subId);
106             if (line1Number == null) {
107                 line1Number = "";
108             }
109             String subNumber = mPhone.getLine1Number();
110             if (subNumber == null) {
111                 subNumber = "";
112             }
113 
114             String label;
115             String description;
116             Icon icon = null;
117 
118             // We can only get the real slotId from the SubInfoRecord, we can't calculate the
119             // slotId from the subId or the phoneId in all instances.
120             SubscriptionInfo record =
121                     mSubscriptionManager.getActiveSubscriptionInfo(subId);
122 
123             if (isEmergency) {
124                 label = mContext.getResources().getString(R.string.sim_label_emergency_calls);
125                 description =
126                         mContext.getResources().getString(R.string.sim_description_emergency_calls);
127             } else if (mTelephonyManager.getPhoneCount() == 1) {
128                 // For single-SIM devices, we show the label and description as whatever the name of
129                 // the network is.
130                 description = label = mTelephonyManager.getNetworkOperatorName();
131             } else {
132                 CharSequence subDisplayName = null;
133 
134                 if (record != null) {
135                     subDisplayName = record.getDisplayName();
136                     slotId = record.getSimSlotIndex();
137                     color = record.getIconTint();
138                     icon = Icon.createWithBitmap(record.createIconBitmap(mContext));
139                 }
140 
141                 String slotIdString;
142                 if (SubscriptionManager.isValidSlotId(slotId)) {
143                     slotIdString = Integer.toString(slotId);
144                 } else {
145                     slotIdString = mContext.getResources().getString(R.string.unknown);
146                 }
147 
148                 if (TextUtils.isEmpty(subDisplayName)) {
149                     // Either the sub record is not there or it has an empty display name.
150                     Log.w(this, "Could not get a display name for subid: %d", subId);
151                     subDisplayName = mContext.getResources().getString(
152                             R.string.sim_description_default, slotIdString);
153                 }
154 
155                 // The label is user-visible so let's use the display name that the user may
156                 // have set in Settings->Sim cards.
157                 label = dummyPrefix + subDisplayName;
158                 description = dummyPrefix + mContext.getResources().getString(
159                                 R.string.sim_description_default, slotIdString);
160             }
161 
162             // By default all SIM phone accounts can place emergency calls.
163             int capabilities = PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
164                     PhoneAccount.CAPABILITY_CALL_PROVIDER |
165                     PhoneAccount.CAPABILITY_MULTI_USER;
166 
167             if (mContext.getResources().getBoolean(R.bool.config_pstnCanPlaceEmergencyCalls)) {
168                 capabilities |= PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS;
169             }
170 
171             mIsVideoCapable = mPhone.isVideoEnabled();
172             if (mIsVideoCapable) {
173                 capabilities |= PhoneAccount.CAPABILITY_VIDEO_CALLING;
174             }
175 
176             mIsVideoPresenceSupported = isCarrierVideoPresenceSupported();
177             if (mIsVideoCapable && mIsVideoPresenceSupported) {
178                 capabilities |= PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE;
179             }
180 
181             if (mIsVideoCapable && isCarrierEmergencyVideoCallsAllowed()) {
182                 capabilities |= PhoneAccount.CAPABILITY_EMERGENCY_VIDEO_CALLING;
183             }
184 
185             mIsVideoPauseSupported = isCarrierVideoPauseSupported();
186             Bundle instantLetteringExtras = null;
187             if (isCarrierInstantLetteringSupported()) {
188                 capabilities |= PhoneAccount.CAPABILITY_CALL_SUBJECT;
189                 instantLetteringExtras = getPhoneAccountExtras();
190             }
191             mIsMergeCallSupported = isCarrierMergeCallSupported();
192 
193             if (isEmergency && mContext.getResources().getBoolean(
194                     R.bool.config_emergency_account_emergency_calls_only)) {
195                 capabilities |= PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY;
196             }
197 
198             if (icon == null) {
199                 // TODO: Switch to using Icon.createWithResource() once that supports tinting.
200                 Resources res = mContext.getResources();
201                 Drawable drawable = res.getDrawable(DEFAULT_SIM_ICON, null);
202                 drawable.setTint(res.getColor(R.color.default_sim_icon_tint_color, null));
203                 drawable.setTintMode(PorterDuff.Mode.SRC_ATOP);
204 
205                 int width = drawable.getIntrinsicWidth();
206                 int height = drawable.getIntrinsicHeight();
207                 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
208                 Canvas canvas = new Canvas(bitmap);
209                 drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
210                 drawable.draw(canvas);
211 
212                 icon = Icon.createWithBitmap(bitmap);
213             }
214 
215             PhoneAccount account = PhoneAccount.builder(phoneAccountHandle, label)
216                     .setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, line1Number, null))
217                     .setSubscriptionAddress(
218                             Uri.fromParts(PhoneAccount.SCHEME_TEL, subNumber, null))
219                     .setCapabilities(capabilities)
220                     .setIcon(icon)
221                     .setHighlightColor(color)
222                     .setShortDescription(description)
223                     .setSupportedUriSchemes(Arrays.asList(
224                             PhoneAccount.SCHEME_TEL, PhoneAccount.SCHEME_VOICEMAIL))
225                     .setExtras(instantLetteringExtras)
226                     .build();
227 
228             // Register with Telecom and put into the account entry.
229             mTelecomManager.registerPhoneAccount(account);
230 
231             return account;
232         }
233 
getPhoneAccountHandle()234         public PhoneAccountHandle getPhoneAccountHandle() {
235             return mAccount != null ? mAccount.getAccountHandle() : null;
236         }
237 
238         /**
239          * Determines from carrier configuration whether pausing of IMS video calls is supported.
240          *
241          * @return {@code true} if pausing IMS video calls is supported.
242          */
isCarrierVideoPauseSupported()243         private boolean isCarrierVideoPauseSupported() {
244             // Check if IMS video pause is supported.
245             PersistableBundle b =
246                     PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
247             return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL);
248         }
249 
250         /**
251          * Determines from carrier configuration whether RCS presence indication for video calls is
252          * supported.
253          *
254          * @return {@code true} if RCS presence indication for video calls is supported.
255          */
isCarrierVideoPresenceSupported()256         private boolean isCarrierVideoPresenceSupported() {
257             PersistableBundle b =
258                     PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
259             return b.getBoolean(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL);
260         }
261 
262         /**
263          * Determines from carrier config whether instant lettering is supported.
264          *
265          * @return {@code true} if instant lettering is supported, {@code false} otherwise.
266          */
isCarrierInstantLetteringSupported()267         private boolean isCarrierInstantLetteringSupported() {
268             PersistableBundle b =
269                     PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
270             return b.getBoolean(CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL);
271         }
272 
273         /**
274          * Determines from carrier config whether merging calls is supported.
275          *
276          * @return {@code true} if merging calls is supported, {@code false} otherwise.
277          */
isCarrierMergeCallSupported()278         private boolean isCarrierMergeCallSupported() {
279             PersistableBundle b =
280                     PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
281             return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_CONFERENCE_CALL_BOOL);
282         }
283 
284         /**
285          * Determines from carrier config whether emergency video calls are supported.
286          *
287          * @return {@code true} if emergency video calls are allowed, {@code false} otherwise.
288          */
isCarrierEmergencyVideoCallsAllowed()289         private boolean isCarrierEmergencyVideoCallsAllowed() {
290             PersistableBundle b =
291                     PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
292             return b.getBoolean(CarrierConfigManager.KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL);
293         }
294 
295         /**
296          * @return The {@linke PhoneAccount} extras associated with the current subscription.
297          */
getPhoneAccountExtras()298         private Bundle getPhoneAccountExtras() {
299             PersistableBundle b =
300                     PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
301 
302             int instantLetteringMaxLength = b.getInt(
303                     CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_LENGTH_LIMIT_INT);
304             String instantLetteringEncoding = b.getString(
305                     CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_ENCODING_STRING);
306 
307             Bundle phoneAccountExtras = new Bundle();
308             phoneAccountExtras.putInt(PhoneAccount.EXTRA_CALL_SUBJECT_MAX_LENGTH,
309                     instantLetteringMaxLength);
310             phoneAccountExtras.putString(PhoneAccount.EXTRA_CALL_SUBJECT_CHARACTER_ENCODING,
311                     instantLetteringEncoding);
312             return phoneAccountExtras;
313         }
314 
315         /**
316          * Receives callback from {@link PstnPhoneCapabilitiesNotifier} when the video capabilities
317          * have changed.
318          *
319          * @param isVideoCapable {@code true} if video is capable.
320          */
321         @Override
onVideoCapabilitiesChanged(boolean isVideoCapable)322         public void onVideoCapabilitiesChanged(boolean isVideoCapable) {
323             mIsVideoCapable = isVideoCapable;
324         }
325 
326         /**
327          * Indicates whether this account supports pausing video calls.
328          * @return {@code true} if the account supports pausing video calls, {@code false}
329          * otherwise.
330          */
isVideoPauseSupported()331         public boolean isVideoPauseSupported() {
332             return mIsVideoCapable && mIsVideoPauseSupported;
333         }
334 
335         /**
336          * Indicates whether this account supports merging calls (i.e. conferencing).
337          * @return {@code true} if the account supports merging calls, {@code false} otherwise.
338          */
isMergeCallSupported()339         public boolean isMergeCallSupported() {
340             return mIsMergeCallSupported;
341         }
342     }
343 
344     private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
345             new OnSubscriptionsChangedListener() {
346         @Override
347         public void onSubscriptionsChanged() {
348             // Any time the SubscriptionInfo changes...rerun the setup
349             tearDownAccounts();
350             setupAccounts();
351         }
352     };
353 
354     private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
355         @Override
356         public void onServiceStateChanged(ServiceState serviceState) {
357             int newState = serviceState.getState();
358             if (newState == ServiceState.STATE_IN_SERVICE && mServiceState != newState) {
359                 tearDownAccounts();
360                 setupAccounts();
361             }
362             mServiceState = newState;
363         }
364     };
365 
366     private static TelecomAccountRegistry sInstance;
367     private final Context mContext;
368     private final TelecomManager mTelecomManager;
369     private final TelephonyManager mTelephonyManager;
370     private final SubscriptionManager mSubscriptionManager;
371     private List<AccountEntry> mAccounts = new LinkedList<AccountEntry>();
372     private int mServiceState = ServiceState.STATE_POWER_OFF;
373 
374     // TODO: Remove back-pointer from app singleton to Service, since this is not a preferred
375     // pattern; redesign. This was added to fix a late release bug.
376     private TelephonyConnectionService mTelephonyConnectionService;
377 
TelecomAccountRegistry(Context context)378     TelecomAccountRegistry(Context context) {
379         mContext = context;
380         mTelecomManager = TelecomManager.from(context);
381         mTelephonyManager = TelephonyManager.from(context);
382         mSubscriptionManager = SubscriptionManager.from(context);
383     }
384 
getInstance(Context context)385     static synchronized final TelecomAccountRegistry getInstance(Context context) {
386         if (sInstance == null && context != null) {
387             sInstance = new TelecomAccountRegistry(context);
388         }
389         return sInstance;
390     }
391 
setTelephonyConnectionService(TelephonyConnectionService telephonyConnectionService)392     void setTelephonyConnectionService(TelephonyConnectionService telephonyConnectionService) {
393         this.mTelephonyConnectionService = telephonyConnectionService;
394     }
395 
getTelephonyConnectionService()396     TelephonyConnectionService getTelephonyConnectionService() {
397         return mTelephonyConnectionService;
398     }
399 
400     /**
401      * Determines if the {@link AccountEntry} associated with a {@link PhoneAccountHandle} supports
402      * pausing video calls.
403      *
404      * @param handle The {@link PhoneAccountHandle}.
405      * @return {@code True} if video pausing is supported.
406      */
isVideoPauseSupported(PhoneAccountHandle handle)407     boolean isVideoPauseSupported(PhoneAccountHandle handle) {
408         for (AccountEntry entry : mAccounts) {
409             if (entry.getPhoneAccountHandle().equals(handle)) {
410                 return entry.isVideoPauseSupported();
411             }
412         }
413         return false;
414     }
415 
416     /**
417      * Determines if the {@link AccountEntry} associated with a {@link PhoneAccountHandle} supports
418      * merging calls.
419      *
420      * @param handle The {@link PhoneAccountHandle}.
421      * @return {@code True} if merging calls is supported.
422      */
isMergeCallSupported(PhoneAccountHandle handle)423     boolean isMergeCallSupported(PhoneAccountHandle handle) {
424         for (AccountEntry entry : mAccounts) {
425             if (entry.getPhoneAccountHandle().equals(handle)) {
426                 return entry.isMergeCallSupported();
427             }
428         }
429         return false;
430     }
431 
432     /**
433      * @return Reference to the {@code TelecomAccountRegistry}'s subscription manager.
434      */
getSubscriptionManager()435     SubscriptionManager getSubscriptionManager() {
436         return mSubscriptionManager;
437     }
438 
439     /**
440      * Returns the address (e.g. the phone number) associated with a subscription.
441      *
442      * @param handle The phone account handle to find the subscription address for.
443      * @return The address.
444      */
getAddress(PhoneAccountHandle handle)445     Uri getAddress(PhoneAccountHandle handle) {
446         for (AccountEntry entry : mAccounts) {
447             if (entry.getPhoneAccountHandle().equals(handle)) {
448                 return entry.mAccount.getAddress();
449             }
450         }
451         return null;
452     }
453 
454     /**
455      * Sets up all the phone accounts for SIMs on first boot.
456      */
setupOnBoot()457     void setupOnBoot() {
458         // TODO: When this object "finishes" we should unregister by invoking
459         // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
460         // This is not strictly necessary because it will be unregistered if the
461         // notification fails but it is good form.
462 
463         // Register for SubscriptionInfo list changes which is guaranteed
464         // to invoke onSubscriptionsChanged the first time.
465         SubscriptionManager.from(mContext).addOnSubscriptionsChangedListener(
466                 mOnSubscriptionsChangedListener);
467 
468         // We also need to listen for changes to the service state (e.g. emergency -> in service)
469         // because this could signal a removal or addition of a SIM in a single SIM phone.
470         mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
471     }
472 
473     /**
474      * Determines if the list of {@link AccountEntry}(s) contains an {@link AccountEntry} with a
475      * specified {@link PhoneAccountHandle}.
476      *
477      * @param handle The {@link PhoneAccountHandle}.
478      * @return {@code True} if an entry exists.
479      */
hasAccountEntryForPhoneAccount(PhoneAccountHandle handle)480     boolean hasAccountEntryForPhoneAccount(PhoneAccountHandle handle) {
481         for (AccountEntry entry : mAccounts) {
482             if (entry.getPhoneAccountHandle().equals(handle)) {
483                 return true;
484             }
485         }
486         return false;
487     }
488 
489     /**
490      * Un-registers any {@link PhoneAccount}s which are no longer present in the list
491      * {@code AccountEntry}(s).
492      */
cleanupPhoneAccounts()493     private void cleanupPhoneAccounts() {
494         ComponentName telephonyComponentName =
495                 new ComponentName(mContext, TelephonyConnectionService.class);
496         // This config indicates whether the emergency account was flagged as emergency calls only
497         // in which case we need to consider all phone accounts, not just the call capable ones.
498         final boolean emergencyCallsOnlyEmergencyAccount = mContext.getResources().getBoolean(
499                 R.bool.config_emergency_account_emergency_calls_only);
500         List<PhoneAccountHandle> accountHandles = emergencyCallsOnlyEmergencyAccount
501                 ? mTelecomManager.getAllPhoneAccountHandles()
502                 : mTelecomManager.getCallCapablePhoneAccounts(true /* includeDisabled */);
503 
504         for (PhoneAccountHandle handle : accountHandles) {
505             if (telephonyComponentName.equals(handle.getComponentName()) &&
506                     !hasAccountEntryForPhoneAccount(handle)) {
507                 Log.i(this, "Unregistering phone account %s.", handle);
508                 mTelecomManager.unregisterPhoneAccount(handle);
509             }
510         }
511     }
512 
setupAccounts()513     private void setupAccounts() {
514         // Go through SIM-based phones and register ourselves -- registering an existing account
515         // will cause the existing entry to be replaced.
516         Phone[] phones = PhoneFactory.getPhones();
517         Log.d(this, "Found %d phones.  Attempting to register.", phones.length);
518 
519         final boolean phoneAccountsEnabled = mContext.getResources().getBoolean(
520                 R.bool.config_pstn_phone_accounts_enabled);
521 
522         if (phoneAccountsEnabled) {
523             for (Phone phone : phones) {
524                 int subscriptionId = phone.getSubId();
525                 Log.d(this, "Phone with subscription id %d", subscriptionId);
526                 if (subscriptionId >= 0) {
527                     mAccounts.add(new AccountEntry(phone, false /* emergency */,
528                             false /* isDummy */));
529                 }
530             }
531         }
532 
533         // If we did not list ANY accounts, we need to provide a "default" SIM account
534         // for emergency numbers since no actual SIM is needed for dialing emergency
535         // numbers but a phone account is.
536         if (mAccounts.isEmpty()) {
537             mAccounts.add(new AccountEntry(PhoneFactory.getDefaultPhone(), true /* emergency */,
538                     false /* isDummy */));
539         }
540 
541         // Add a fake account entry.
542         if (DBG && phones.length > 0 && "TRUE".equals(System.getProperty("dummy_sim"))) {
543             mAccounts.add(new AccountEntry(phones[0], false /* emergency */, true /* isDummy */));
544         }
545 
546         // Clean up any PhoneAccounts that are no longer relevant
547         cleanupPhoneAccounts();
548 
549         // At some point, the phone account ID was switched from the subId to the iccId.
550         // If there is a default account, check if this is the case, and upgrade the default account
551         // from using the subId to iccId if so.
552         PhoneAccountHandle defaultPhoneAccount =
553                 mTelecomManager.getUserSelectedOutgoingPhoneAccount();
554         ComponentName telephonyComponentName =
555                 new ComponentName(mContext, TelephonyConnectionService.class);
556 
557         if (defaultPhoneAccount != null &&
558                 telephonyComponentName.equals(defaultPhoneAccount.getComponentName()) &&
559                 !hasAccountEntryForPhoneAccount(defaultPhoneAccount)) {
560 
561             String phoneAccountId = defaultPhoneAccount.getId();
562             if (!TextUtils.isEmpty(phoneAccountId) && TextUtils.isDigitsOnly(phoneAccountId)) {
563                 PhoneAccountHandle upgradedPhoneAccount =
564                         PhoneUtils.makePstnPhoneAccountHandle(
565                                 PhoneGlobals.getPhone(Integer.parseInt(phoneAccountId)));
566 
567                 if (hasAccountEntryForPhoneAccount(upgradedPhoneAccount)) {
568                     mTelecomManager.setUserSelectedOutgoingPhoneAccount(upgradedPhoneAccount);
569                 }
570             }
571         }
572     }
573 
tearDownAccounts()574     private void tearDownAccounts() {
575         for (AccountEntry entry : mAccounts) {
576             entry.teardown();
577         }
578         mAccounts.clear();
579     }
580 }
581