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.server.telecom; 18 19 import android.Manifest; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.content.BroadcastReceiver; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.content.pm.PackageManager; 28 import android.content.pm.ResolveInfo; 29 import android.content.pm.ServiceInfo; 30 import android.content.pm.UserInfo; 31 import android.graphics.Bitmap; 32 import android.graphics.BitmapFactory; 33 import android.graphics.drawable.Icon; 34 import android.net.Uri; 35 import android.os.Bundle; 36 import android.os.AsyncTask; 37 import android.os.PersistableBundle; 38 import android.os.Process; 39 import android.os.UserHandle; 40 import android.os.UserManager; 41 import android.provider.Settings; 42 import android.telecom.CallAudioState; 43 import android.telecom.ConnectionService; 44 import android.telecom.DefaultDialerManager; 45 import android.telecom.Log; 46 import android.telecom.PhoneAccount; 47 import android.telecom.PhoneAccountHandle; 48 import android.telephony.CarrierConfigManager; 49 import android.telephony.PhoneNumberUtils; 50 import android.telephony.SubscriptionInfo; 51 import android.telephony.SubscriptionManager; 52 import android.telephony.TelephonyManager; 53 import android.text.TextUtils; 54 import android.util.AtomicFile; 55 import android.util.Base64; 56 import android.util.EventLog; 57 import android.util.Xml; 58 59 // TODO: Needed for move to system service: import com.android.internal.R; 60 import com.android.internal.annotations.VisibleForTesting; 61 import com.android.internal.util.FastXmlSerializer; 62 import com.android.internal.util.IndentingPrintWriter; 63 import com.android.internal.util.XmlUtils; 64 65 import org.xmlpull.v1.XmlPullParser; 66 import org.xmlpull.v1.XmlPullParserException; 67 import org.xmlpull.v1.XmlSerializer; 68 69 import java.io.BufferedInputStream; 70 import java.io.ByteArrayInputStream; 71 import java.io.ByteArrayOutputStream; 72 import java.io.File; 73 import java.io.FileNotFoundException; 74 import java.io.FileOutputStream; 75 import java.io.IOException; 76 import java.io.InputStream; 77 import java.lang.Integer; 78 import java.lang.SecurityException; 79 import java.lang.String; 80 import java.util.ArrayList; 81 import java.util.Collections; 82 import java.util.Comparator; 83 import java.util.HashMap; 84 import java.util.Iterator; 85 import java.util.List; 86 import java.util.Map; 87 import java.util.Objects; 88 import java.util.Optional; 89 import java.util.concurrent.ConcurrentHashMap; 90 import java.util.concurrent.CopyOnWriteArrayList; 91 import java.util.stream.Collector; 92 import java.util.stream.Collectors; 93 import java.util.stream.Stream; 94 95 /** 96 * Handles writing and reading PhoneAccountHandle registration entries. This is a simple verbatim 97 * delegate for all the account handling methods on {@link android.telecom.TelecomManager} as 98 * implemented in {@link TelecomServiceImpl}, with the notable exception that 99 * {@link TelecomServiceImpl} is responsible for security checking to make sure that the caller has 100 * proper authority over the {@code ComponentName}s they are declaring in their 101 * {@code PhoneAccountHandle}s. 102 * 103 * 104 * -- About Users and Phone Accounts -- 105 * 106 * We store all phone accounts for all users in a single place, which means that there are three 107 * users that we have to deal with in code: 108 * 1) The Android User that is currently active on the device. 109 * 2) The user which owns/registers the phone account. 110 * 3) The user running the app that is requesting the phone account information. 111 * 112 * For example, I have a device with 2 users, primary (A) and secondary (B), and the secondary user 113 * has a work profile running as another user (B2). Each user/profile only have the visibility of 114 * phone accounts owned by them. Lets say, user B (settings) is requesting a list of phone accounts, 115 * and the list only contains phone accounts owned by user B and accounts with 116 * {@link PhoneAccount#CAPABILITY_MULTI_USER}. 117 * 118 * In practice, (2) is stored with the phone account handle and is part of the handle's ID. (1) is 119 * saved in {@link #mCurrentUserHandle} and (3) we get from Binder.getCallingUser(). We check these 120 * users for visibility before returning any phone accounts. 121 */ 122 public class PhoneAccountRegistrar { 123 124 public static final PhoneAccountHandle NO_ACCOUNT_SELECTED = 125 new PhoneAccountHandle(new ComponentName("null", "null"), "NO_ACCOUNT_SELECTED"); 126 127 public abstract static class Listener { onAccountsChanged(PhoneAccountRegistrar registrar)128 public void onAccountsChanged(PhoneAccountRegistrar registrar) {} onDefaultOutgoingChanged(PhoneAccountRegistrar registrar)129 public void onDefaultOutgoingChanged(PhoneAccountRegistrar registrar) {} onSimCallManagerChanged(PhoneAccountRegistrar registrar)130 public void onSimCallManagerChanged(PhoneAccountRegistrar registrar) {} onPhoneAccountRegistered(PhoneAccountRegistrar registrar, PhoneAccountHandle handle)131 public void onPhoneAccountRegistered(PhoneAccountRegistrar registrar, 132 PhoneAccountHandle handle) {} onPhoneAccountUnRegistered(PhoneAccountRegistrar registrar, PhoneAccountHandle handle)133 public void onPhoneAccountUnRegistered(PhoneAccountRegistrar registrar, 134 PhoneAccountHandle handle) {} onPhoneAccountChanged(PhoneAccountRegistrar registrar, PhoneAccount phoneAccount)135 public void onPhoneAccountChanged(PhoneAccountRegistrar registrar, 136 PhoneAccount phoneAccount) {} 137 } 138 139 /** 140 * Receiver for detecting when a managed profile has been removed so that PhoneAccountRegistrar 141 * can clean up orphan {@link PhoneAccount}s 142 */ 143 private final BroadcastReceiver mManagedProfileReceiver = new BroadcastReceiver() { 144 @Override 145 public void onReceive(Context context, Intent intent) { 146 Log.startSession("PARbR.oR"); 147 try { 148 synchronized (mLock) { 149 if (intent.getAction().equals(Intent.ACTION_MANAGED_PROFILE_REMOVED)) { 150 cleanupOrphanedPhoneAccounts(); 151 } 152 } 153 } finally { 154 Log.endSession(); 155 } 156 } 157 }; 158 159 public static final String FILE_NAME = "phone-account-registrar-state.xml"; 160 @VisibleForTesting 161 public static final int EXPECTED_STATE_VERSION = 9; 162 public static final int MAX_PHONE_ACCOUNT_REGISTRATIONS = 10; 163 164 /** Keep in sync with the same in SipSettings.java */ 165 private static final String SIP_SHARED_PREFERENCES = "SIP_PREFERENCES"; 166 167 private final List<Listener> mListeners = new CopyOnWriteArrayList<>(); 168 private final AtomicFile mAtomicFile; 169 private final Context mContext; 170 private final UserManager mUserManager; 171 private final TelephonyManager mTelephonyManager; 172 private final SubscriptionManager mSubscriptionManager; 173 private final DefaultDialerCache mDefaultDialerCache; 174 private final AppLabelProxy mAppLabelProxy; 175 private final TelecomSystem.SyncRoot mLock; 176 private State mState; 177 private UserHandle mCurrentUserHandle; 178 private String mTestPhoneAccountPackageNameFilter; 179 private interface PhoneAccountRegistrarWriteLock {} 180 private final PhoneAccountRegistrarWriteLock mWriteLock = 181 new PhoneAccountRegistrarWriteLock() {}; 182 183 @VisibleForTesting PhoneAccountRegistrar(Context context, TelecomSystem.SyncRoot lock, DefaultDialerCache defaultDialerCache, AppLabelProxy appLabelProxy)184 public PhoneAccountRegistrar(Context context, TelecomSystem.SyncRoot lock, 185 DefaultDialerCache defaultDialerCache, AppLabelProxy appLabelProxy) { 186 this(context, lock, FILE_NAME, defaultDialerCache, appLabelProxy); 187 } 188 189 @VisibleForTesting PhoneAccountRegistrar(Context context, TelecomSystem.SyncRoot lock, String fileName, DefaultDialerCache defaultDialerCache, AppLabelProxy appLabelProxy)190 public PhoneAccountRegistrar(Context context, TelecomSystem.SyncRoot lock, String fileName, 191 DefaultDialerCache defaultDialerCache, AppLabelProxy appLabelProxy) { 192 193 mAtomicFile = new AtomicFile(new File(context.getFilesDir(), fileName)); 194 195 mState = new State(); 196 mContext = context; 197 mLock = lock; 198 mUserManager = UserManager.get(context); 199 mDefaultDialerCache = defaultDialerCache; 200 mSubscriptionManager = SubscriptionManager.from(mContext); 201 mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 202 mAppLabelProxy = appLabelProxy; 203 mCurrentUserHandle = Process.myUserHandle(); 204 205 // register context based receiver to clean up orphan phone accounts 206 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MANAGED_PROFILE_REMOVED); 207 mContext.registerReceiver(mManagedProfileReceiver, intentFilter); 208 209 read(); 210 } 211 212 /** 213 * Retrieves the subscription id for a given phone account if it exists. Subscription ids 214 * apply only to PSTN/SIM card phone accounts so all other accounts should not have a 215 * subscription id. 216 * @param accountHandle The handle for the phone account for which to retrieve the 217 * subscription id. 218 * @return The value of the subscription id or -1 if it does not exist or is not valid. 219 */ getSubscriptionIdForPhoneAccount(PhoneAccountHandle accountHandle)220 public int getSubscriptionIdForPhoneAccount(PhoneAccountHandle accountHandle) { 221 PhoneAccount account = getPhoneAccountUnchecked(accountHandle); 222 223 if (account != null && account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) { 224 return mTelephonyManager.getSubscriptionId(accountHandle); 225 } 226 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 227 } 228 229 /** 230 * Retrieves the default outgoing phone account supporting the specified uriScheme. Note that if 231 * {@link #mCurrentUserHandle} does not have visibility into the current default, {@code null} 232 * will be returned. 233 * 234 * @param uriScheme The URI scheme for the outgoing call. 235 * @return The {@link PhoneAccountHandle} to use. 236 */ getOutgoingPhoneAccountForScheme(String uriScheme, UserHandle userHandle)237 public PhoneAccountHandle getOutgoingPhoneAccountForScheme(String uriScheme, 238 UserHandle userHandle) { 239 final PhoneAccountHandle userSelected = getUserSelectedOutgoingPhoneAccount(userHandle); 240 241 if (userSelected != null) { 242 // If there is a default PhoneAccount, ensure it supports calls to handles with the 243 // specified uriScheme. 244 final PhoneAccount userSelectedAccount = getPhoneAccountUnchecked(userSelected); 245 if (userSelectedAccount.supportsUriScheme(uriScheme)) { 246 return userSelected; 247 } 248 } 249 250 List<PhoneAccountHandle> outgoing = getCallCapablePhoneAccounts(uriScheme, false, 251 userHandle); 252 switch (outgoing.size()) { 253 case 0: 254 // There are no accounts, so there can be no default 255 return null; 256 case 1: 257 // There is only one account, which is by definition the default. 258 return outgoing.get(0); 259 default: 260 // There are multiple accounts with no selected default 261 return null; 262 } 263 } 264 getOutgoingPhoneAccountForSchemeOfCurrentUser(String uriScheme)265 public PhoneAccountHandle getOutgoingPhoneAccountForSchemeOfCurrentUser(String uriScheme) { 266 return getOutgoingPhoneAccountForScheme(uriScheme, mCurrentUserHandle); 267 } 268 269 /** 270 * @return The user-selected outgoing {@link PhoneAccount}, or null if it hasn't been set (or 271 * if it was set by another user). 272 */ 273 @VisibleForTesting getUserSelectedOutgoingPhoneAccount(UserHandle userHandle)274 public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount(UserHandle userHandle) { 275 if (userHandle == null) { 276 return null; 277 } 278 DefaultPhoneAccountHandle defaultPhoneAccountHandle = mState.defaultOutgoingAccountHandles 279 .get(userHandle); 280 if (defaultPhoneAccountHandle == null) { 281 return null; 282 } 283 // Make sure the account is still registered and owned by the user. 284 PhoneAccount account = getPhoneAccount(defaultPhoneAccountHandle.phoneAccountHandle, 285 userHandle); 286 287 if (account != null) { 288 return defaultPhoneAccountHandle.phoneAccountHandle; 289 } 290 291 Log.v(this, 292 "getUserSelectedOutgoingPhoneAccount: defaultPhoneAccountHandle" 293 + ".phoneAccountHandle=[%s] is not registered or owned by %s" 294 , defaultPhoneAccountHandle.phoneAccountHandle, userHandle); 295 296 return null; 297 } 298 299 /** 300 * @return The {@link DefaultPhoneAccountHandle} containing the user-selected default calling 301 * account and group Id for the {@link UserHandle} specified. 302 */ getUserSelectedDefaultPhoneAccount(UserHandle userHandle)303 private DefaultPhoneAccountHandle getUserSelectedDefaultPhoneAccount(UserHandle userHandle) { 304 if (userHandle == null) { 305 return null; 306 } 307 DefaultPhoneAccountHandle defaultPhoneAccountHandle = mState.defaultOutgoingAccountHandles 308 .get(userHandle); 309 if (defaultPhoneAccountHandle == null) { 310 return null; 311 } 312 313 return defaultPhoneAccountHandle; 314 } 315 316 /** 317 * @return The currently registered PhoneAccount in Telecom that has the same group Id. 318 */ getPhoneAccountByGroupId(String groupId, ComponentName groupComponentName, UserHandle userHandle, PhoneAccountHandle excludePhoneAccountHandle)319 private PhoneAccount getPhoneAccountByGroupId(String groupId, ComponentName groupComponentName, 320 UserHandle userHandle, PhoneAccountHandle excludePhoneAccountHandle) { 321 if (groupId == null || groupId.isEmpty() || userHandle == null) { 322 return null; 323 } 324 // Get the PhoneAccount with the same group Id (and same ComponentName) that is not the 325 // newAccount that was just added 326 List<PhoneAccount> accounts = getAllPhoneAccounts(userHandle).stream() 327 .filter(account -> groupId.equals(account.getGroupId()) && 328 !account.getAccountHandle().equals(excludePhoneAccountHandle) && 329 Objects.equals(account.getAccountHandle().getComponentName(), 330 groupComponentName)) 331 .collect(Collectors.toList()); 332 // There should be one or no PhoneAccounts with the same group Id 333 if (accounts.size() > 1) { 334 Log.w(this, "Found multiple PhoneAccounts registered to the same Group Id!"); 335 } 336 return accounts.isEmpty() ? null : accounts.get(0); 337 } 338 339 /** 340 * Sets the phone account with which to place all calls by default. Set by the user 341 * within phone settings. 342 */ setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle, UserHandle userHandle)343 public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle, 344 UserHandle userHandle) { 345 if (userHandle == null) { 346 return; 347 } 348 DefaultPhoneAccountHandle currentDefaultInfo = 349 mState.defaultOutgoingAccountHandles.get(userHandle); 350 PhoneAccountHandle currentDefaultPhoneAccount = currentDefaultInfo == null ? null : 351 currentDefaultInfo.phoneAccountHandle; 352 353 Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s", accountHandle); 354 355 if (Objects.equals(currentDefaultPhoneAccount, accountHandle)) { 356 Log.i(this, "setUserSelectedOutgoingPhoneAccount: " 357 + "no change in default phoneAccountHandle. current is same as new."); 358 return; 359 } 360 361 boolean isSimAccount = false; 362 if (accountHandle == null) { 363 // Asking to clear the default outgoing is a valid request 364 mState.defaultOutgoingAccountHandles.remove(userHandle); 365 } else { 366 PhoneAccount account = getPhoneAccount(accountHandle, userHandle); 367 if (account == null) { 368 Log.w(this, "Trying to set nonexistent default outgoing %s", 369 accountHandle); 370 return; 371 } 372 373 if (!account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)) { 374 Log.w(this, "Trying to set non-call-provider default outgoing %s", 375 accountHandle); 376 return; 377 } 378 379 if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) { 380 // If the account selected is a SIM account, propagate down to the subscription 381 // record. 382 isSimAccount = true; 383 } 384 385 mState.defaultOutgoingAccountHandles 386 .put(userHandle, new DefaultPhoneAccountHandle(userHandle, accountHandle, 387 account.getGroupId())); 388 } 389 390 // Potentially update the default voice subid in SubscriptionManager. 391 int newSubId = accountHandle == null ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : 392 getSubscriptionIdForPhoneAccount(accountHandle); 393 if (isSimAccount || accountHandle == null) { 394 int currentVoiceSubId = mSubscriptionManager.getDefaultVoiceSubscriptionId(); 395 if (newSubId != currentVoiceSubId) { 396 Log.i(this, "setUserSelectedOutgoingPhoneAccount: update voice sub; " 397 + "account=%s, subId=%d", accountHandle, newSubId); 398 mSubscriptionManager.setDefaultVoiceSubscriptionId(newSubId); 399 } else { 400 Log.i(this, "setUserSelectedOutgoingPhoneAccount: no change to voice sub"); 401 } 402 } else { 403 Log.i(this, "setUserSelectedOutgoingPhoneAccount: %s is not a sub", accountHandle); 404 } 405 406 write(); 407 fireDefaultOutgoingChanged(); 408 } 409 isUserSelectedSmsPhoneAccount(PhoneAccountHandle accountHandle)410 boolean isUserSelectedSmsPhoneAccount(PhoneAccountHandle accountHandle) { 411 return getSubscriptionIdForPhoneAccount(accountHandle) == 412 SubscriptionManager.getDefaultSmsSubscriptionId(); 413 } 414 getSystemSimCallManagerComponent()415 public ComponentName getSystemSimCallManagerComponent() { 416 return getSystemSimCallManagerComponent(SubscriptionManager.getDefaultSubscriptionId()); 417 } 418 getSystemSimCallManagerComponent(int subId)419 public ComponentName getSystemSimCallManagerComponent(int subId) { 420 String defaultSimCallManager = null; 421 CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService( 422 Context.CARRIER_CONFIG_SERVICE); 423 PersistableBundle configBundle = configManager.getConfigForSubId(subId); 424 if (configBundle != null) { 425 defaultSimCallManager = configBundle.getString( 426 CarrierConfigManager.KEY_DEFAULT_SIM_CALL_MANAGER_STRING); 427 } 428 return TextUtils.isEmpty(defaultSimCallManager) 429 ? null : ComponentName.unflattenFromString(defaultSimCallManager); 430 } 431 getSimCallManagerOfCurrentUser()432 public PhoneAccountHandle getSimCallManagerOfCurrentUser() { 433 return getSimCallManager(mCurrentUserHandle); 434 } 435 436 /** 437 * Returns the {@link PhoneAccountHandle} corresponding to the SIM Call Manager associated with 438 * the default Telephony Subscription ID (see 439 * {@link SubscriptionManager#getDefaultSubscriptionId()}). SIM Call Manager returned 440 * corresponds to the following priority order: 441 * 1. If a SIM Call Manager {@link PhoneAccount} is registered for the same package as the 442 * default dialer, then that one is returned. 443 * 2. If there is a SIM Call Manager {@link PhoneAccount} registered which matches the 444 * carrier configuration's default, then that one is returned. 445 * 3. Otherwise, we return null. 446 */ getSimCallManager(UserHandle userHandle)447 public PhoneAccountHandle getSimCallManager(UserHandle userHandle) { 448 return getSimCallManager(SubscriptionManager.getDefaultSubscriptionId(), userHandle); 449 } 450 451 /** 452 * Queries the SIM call manager associated with a specific subscription ID. 453 * 454 * @see #getSimCallManager(UserHandle) for more information. 455 */ getSimCallManager(int subId, UserHandle userHandle)456 public PhoneAccountHandle getSimCallManager(int subId, UserHandle userHandle) { 457 458 // Get the default dialer in case it has a connection manager associated with it. 459 String dialerPackage = mDefaultDialerCache 460 .getDefaultDialerApplication(userHandle.getIdentifier()); 461 462 // Check carrier config. 463 ComponentName systemSimCallManagerComponent = getSystemSimCallManagerComponent(subId); 464 465 PhoneAccountHandle dialerSimCallManager = null; 466 PhoneAccountHandle systemSimCallManager = null; 467 468 if (!TextUtils.isEmpty(dialerPackage) || systemSimCallManagerComponent != null) { 469 // loop through and look for any connection manager in the same package. 470 List<PhoneAccountHandle> allSimCallManagers = getPhoneAccountHandles( 471 PhoneAccount.CAPABILITY_CONNECTION_MANAGER, null, null, 472 true /* includeDisabledAccounts */, userHandle); 473 for (PhoneAccountHandle accountHandle : allSimCallManagers) { 474 ComponentName component = accountHandle.getComponentName(); 475 476 // Store the system connection manager if found 477 if (systemSimCallManager == null 478 && Objects.equals(component, systemSimCallManagerComponent) 479 && !resolveComponent(accountHandle).isEmpty()) { 480 systemSimCallManager = accountHandle; 481 482 // Store the dialer connection manager if found 483 } else if (dialerSimCallManager == null 484 && Objects.equals(component.getPackageName(), dialerPackage) 485 && !resolveComponent(accountHandle).isEmpty()) { 486 dialerSimCallManager = accountHandle; 487 } 488 } 489 } 490 491 PhoneAccountHandle retval = dialerSimCallManager != null ? 492 dialerSimCallManager : systemSimCallManager; 493 Log.i(this, "getSimCallManager: SimCallManager for subId %d queried, returning: %s", 494 subId, retval); 495 496 return retval; 497 } 498 499 /** 500 * Loops through all SIM accounts ({@link #getSimPhoneAccounts}) and returns those with SIM call 501 * manager components specified in carrier config that match {@code simCallManagerHandle}. 502 * 503 * <p>Note that this will return handles even when {@code simCallManagerHandle} has not yet been 504 * registered or was recently unregistered. 505 * 506 * <p>If the given {@code simCallManagerHandle} is not the SIM call manager for any active SIMs, 507 * returns an empty list. 508 */ getSimPhoneAccountsFromSimCallManager( @onNull PhoneAccountHandle simCallManagerHandle)509 public @NonNull List<PhoneAccountHandle> getSimPhoneAccountsFromSimCallManager( 510 @NonNull PhoneAccountHandle simCallManagerHandle) { 511 List<PhoneAccountHandle> matchingSimHandles = new ArrayList<>(); 512 for (PhoneAccountHandle simHandle : 513 getSimPhoneAccounts(simCallManagerHandle.getUserHandle())) { 514 ComponentName simCallManager = 515 getSystemSimCallManagerComponent(getSubscriptionIdForPhoneAccount(simHandle)); 516 if (simCallManager == null) continue; 517 if (simCallManager.equals(simCallManagerHandle.getComponentName())) { 518 matchingSimHandles.add(simHandle); 519 } 520 } 521 return matchingSimHandles; 522 } 523 524 /** 525 * Sets a filter for which {@link PhoneAccount}s will be returned from 526 * {@link #filterRestrictedPhoneAccounts(List)}. If non-null, only {@link PhoneAccount}s 527 * with the package name packageNameFilter will be returned. If null, no filter is set. 528 * @param packageNameFilter The package name that will be used to filter only 529 * {@link PhoneAccount}s with the same package name. 530 */ setTestPhoneAccountPackageNameFilter(String packageNameFilter)531 public void setTestPhoneAccountPackageNameFilter(String packageNameFilter) { 532 mTestPhoneAccountPackageNameFilter = packageNameFilter; 533 Log.i(this, "filter set for PhoneAccounts, packageName=" + packageNameFilter); 534 } 535 536 /** 537 * Filter the given {@link List<PhoneAccount>} and keep only {@link PhoneAccount}s that have the 538 * #mTestPhoneAccountPackageNameFilter. 539 * @param accounts List of {@link PhoneAccount}s to filter. 540 * @return new list of filtered {@link PhoneAccount}s. 541 */ filterRestrictedPhoneAccounts(List<PhoneAccount> accounts)542 public List<PhoneAccount> filterRestrictedPhoneAccounts(List<PhoneAccount> accounts) { 543 if (TextUtils.isEmpty(mTestPhoneAccountPackageNameFilter)) { 544 return new ArrayList<>(accounts); 545 } 546 // Remove all PhoneAccounts that do not have the same package name as the filter. 547 return accounts.stream().filter(account -> mTestPhoneAccountPackageNameFilter.equals( 548 account.getAccountHandle().getComponentName().getPackageName())) 549 .collect(Collectors.toList()); 550 } 551 552 /** 553 * If it is a outgoing call, sim call manager associated with the target phone account of the 554 * call is returned (if one exists). 555 * Otherwise, we return the sim call manager of the user associated with the 556 * target phone account. 557 * @return phone account handle of sim call manager based on the ongoing call. 558 */ 559 @Nullable getSimCallManagerFromCall(Call call)560 public PhoneAccountHandle getSimCallManagerFromCall(Call call) { 561 if (call == null) { 562 return null; 563 } 564 UserHandle userHandle = call.getInitiatingUser(); 565 if (userHandle == null) { 566 userHandle = call.getTargetPhoneAccount().getUserHandle(); 567 } 568 PhoneAccountHandle targetPhoneAccount = call.getTargetPhoneAccount(); 569 Log.d(this, "getSimCallManagerFromCall: callId=%s, targetPhac=%s", 570 call.getId(), targetPhoneAccount); 571 return getSimCallManagerFromHandle(targetPhoneAccount,userHandle); 572 } 573 574 /** 575 * Given a target phone account and user, determines the sim call manager (if any) which is 576 * associated with that {@link PhoneAccountHandle}. 577 * @param targetPhoneAccount The target phone account to check. 578 * @param userHandle The user handle. 579 * @return The {@link PhoneAccountHandle} of the connection manager. 580 */ getSimCallManagerFromHandle(PhoneAccountHandle targetPhoneAccount, UserHandle userHandle)581 public PhoneAccountHandle getSimCallManagerFromHandle(PhoneAccountHandle targetPhoneAccount, 582 UserHandle userHandle) { 583 // First, check if the specified target phone account handle is a connection manager; if 584 // it is, then just return it. 585 PhoneAccount phoneAccount = getPhoneAccountUnchecked(targetPhoneAccount); 586 if (phoneAccount != null 587 && phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)) { 588 return targetPhoneAccount; 589 } 590 591 int subId = getSubscriptionIdForPhoneAccount(targetPhoneAccount); 592 if (SubscriptionManager.isValidSubscriptionId(subId) 593 && subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 594 PhoneAccountHandle callManagerHandle = getSimCallManager(subId, userHandle); 595 Log.d(this, "getSimCallManagerFromHandle: targetPhac=%s, subId=%d, scm=%s", 596 targetPhoneAccount, subId, callManagerHandle); 597 return callManagerHandle; 598 } else { 599 PhoneAccountHandle callManagerHandle = getSimCallManager(userHandle); 600 Log.d(this, "getSimCallManagerFromHandle: targetPhac=%s, subId(d)=%d, scm=%s", 601 targetPhoneAccount, subId, callManagerHandle); 602 return callManagerHandle; 603 } 604 } 605 606 /** 607 * Update the current UserHandle to track when users are switched. This will allow the 608 * PhoneAccountRegistar to self-filter the PhoneAccounts to make sure we don't leak anything 609 * across users. 610 * We cannot simply check the calling user because that would always return the primary user for 611 * all invocations originating with the system process. 612 * 613 * @param userHandle The {@link UserHandle}, as delivered by 614 * {@link Intent#ACTION_USER_SWITCHED}. 615 */ setCurrentUserHandle(UserHandle userHandle)616 public void setCurrentUserHandle(UserHandle userHandle) { 617 if (userHandle == null) { 618 Log.d(this, "setCurrentUserHandle, userHandle = null"); 619 userHandle = Process.myUserHandle(); 620 } 621 Log.d(this, "setCurrentUserHandle, %s", userHandle); 622 mCurrentUserHandle = userHandle; 623 } 624 625 /** 626 * @return {@code true} if the phone account was successfully enabled/disabled, {@code false} 627 * otherwise. 628 */ enablePhoneAccount(PhoneAccountHandle accountHandle, boolean isEnabled)629 public boolean enablePhoneAccount(PhoneAccountHandle accountHandle, boolean isEnabled) { 630 PhoneAccount account = getPhoneAccountUnchecked(accountHandle); 631 Log.i(this, "Phone account %s %s.", accountHandle, isEnabled ? "enabled" : "disabled"); 632 if (account == null) { 633 Log.w(this, "Could not find account to enable: " + accountHandle); 634 return false; 635 } else if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) { 636 // We never change the enabled state of SIM-based accounts. 637 Log.w(this, "Could not change enable state of SIM account: " + accountHandle); 638 return false; 639 } 640 641 if (account.isEnabled() != isEnabled) { 642 account.setIsEnabled(isEnabled); 643 if (!isEnabled) { 644 // If the disabled account is the default, remove it. 645 removeDefaultPhoneAccountHandle(accountHandle); 646 } 647 write(); 648 fireAccountsChanged(); 649 } 650 return true; 651 } 652 removeDefaultPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle)653 private void removeDefaultPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) { 654 Iterator<Map.Entry<UserHandle, DefaultPhoneAccountHandle>> iterator = 655 mState.defaultOutgoingAccountHandles.entrySet().iterator(); 656 while (iterator.hasNext()) { 657 Map.Entry<UserHandle, DefaultPhoneAccountHandle> entry = iterator.next(); 658 if (phoneAccountHandle.equals(entry.getValue().phoneAccountHandle)) { 659 iterator.remove(); 660 } 661 } 662 } 663 isVisibleForUser(PhoneAccount account, UserHandle userHandle, boolean acrossProfiles)664 private boolean isVisibleForUser(PhoneAccount account, UserHandle userHandle, 665 boolean acrossProfiles) { 666 if (account == null) { 667 return false; 668 } 669 670 if (userHandle == null) { 671 Log.w(this, "userHandle is null in isVisibleForUser"); 672 return false; 673 } 674 675 // If this PhoneAccount has CAPABILITY_MULTI_USER, it should be visible to all users and 676 // all profiles. Only Telephony and SIP accounts should have this capability. 677 if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) { 678 return true; 679 } 680 681 UserHandle phoneAccountUserHandle = account.getAccountHandle().getUserHandle(); 682 if (phoneAccountUserHandle == null) { 683 return false; 684 } 685 686 if (mCurrentUserHandle == null) { 687 // In case we need to have emergency phone calls from the lock screen. 688 Log.d(this, "Current user is null; assuming true"); 689 return true; 690 } 691 692 if (acrossProfiles) { 693 return UserManager.get(mContext).isSameProfileGroup(userHandle.getIdentifier(), 694 phoneAccountUserHandle.getIdentifier()); 695 } else { 696 return phoneAccountUserHandle.equals(userHandle); 697 } 698 } 699 resolveComponent(PhoneAccountHandle phoneAccountHandle)700 private List<ResolveInfo> resolveComponent(PhoneAccountHandle phoneAccountHandle) { 701 return resolveComponent(phoneAccountHandle.getComponentName(), 702 phoneAccountHandle.getUserHandle()); 703 } 704 resolveComponent(ComponentName componentName, UserHandle userHandle)705 private List<ResolveInfo> resolveComponent(ComponentName componentName, 706 UserHandle userHandle) { 707 PackageManager pm = mContext.getPackageManager(); 708 Intent intent = new Intent(ConnectionService.SERVICE_INTERFACE); 709 intent.setComponent(componentName); 710 try { 711 if (userHandle != null) { 712 return pm.queryIntentServicesAsUser(intent, 0, userHandle.getIdentifier()); 713 } else { 714 return pm.queryIntentServices(intent, 0); 715 } 716 } catch (SecurityException e) { 717 Log.e(this, e, "%s is not visible for the calling user", componentName); 718 return Collections.EMPTY_LIST; 719 } 720 } 721 722 /** 723 * Retrieves a list of all {@link PhoneAccountHandle}s registered. 724 * Only returns accounts which are enabled. 725 * 726 * @return The list of {@link PhoneAccountHandle}s. 727 */ getAllPhoneAccountHandles(UserHandle userHandle)728 public List<PhoneAccountHandle> getAllPhoneAccountHandles(UserHandle userHandle) { 729 return getPhoneAccountHandles(0, null, null, false, userHandle); 730 } 731 getAllPhoneAccounts(UserHandle userHandle)732 public List<PhoneAccount> getAllPhoneAccounts(UserHandle userHandle) { 733 return getPhoneAccounts(0, null, null, false, userHandle); 734 } 735 getAllPhoneAccountsOfCurrentUser()736 public List<PhoneAccount> getAllPhoneAccountsOfCurrentUser() { 737 return getAllPhoneAccounts(mCurrentUserHandle); 738 } 739 740 /** 741 * Retrieves a list of all phone account call provider phone accounts supporting the 742 * specified URI scheme. 743 * 744 * @param uriScheme The URI scheme. 745 * @param includeDisabledAccounts {@code} if disabled {@link PhoneAccount}s should be included 746 * in the results. 747 * @param userHandle The {@link UserHandle} to retrieve the {@link PhoneAccount}s for. 748 * @return The phone account handles. 749 */ getCallCapablePhoneAccounts( String uriScheme, boolean includeDisabledAccounts, UserHandle userHandle)750 public List<PhoneAccountHandle> getCallCapablePhoneAccounts( 751 String uriScheme, boolean includeDisabledAccounts, UserHandle userHandle) { 752 return getCallCapablePhoneAccounts(uriScheme, includeDisabledAccounts, userHandle, 753 0 /* capabilities */, PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY); 754 } 755 756 /** 757 * Retrieves a list of all phone account call provider phone accounts supporting the 758 * specified URI scheme. 759 * 760 * @param uriScheme The URI scheme. 761 * @param includeDisabledAccounts {@code} if disabled {@link PhoneAccount}s should be included 762 * in the results. 763 * @param userHandle The {@link UserHandle} to retrieve the {@link PhoneAccount}s for. 764 * @param capabilities Extra {@link PhoneAccount} capabilities which matching 765 * {@link PhoneAccount}s must have. 766 * @return The phone account handles. 767 */ getCallCapablePhoneAccounts( String uriScheme, boolean includeDisabledAccounts, UserHandle userHandle, int capabilities, int excludedCapabilities)768 public List<PhoneAccountHandle> getCallCapablePhoneAccounts( 769 String uriScheme, boolean includeDisabledAccounts, UserHandle userHandle, 770 int capabilities, int excludedCapabilities) { 771 return getPhoneAccountHandles( 772 PhoneAccount.CAPABILITY_CALL_PROVIDER | capabilities, 773 excludedCapabilities /*excludedCapabilities*/, 774 uriScheme, null, includeDisabledAccounts, userHandle); 775 } 776 777 /** 778 * Retrieves a list of all phone accounts which have 779 * {@link PhoneAccount#CAPABILITY_SELF_MANAGED}. 780 * <p> 781 * Returns only the {@link PhoneAccount}s which are enabled as self-managed accounts are 782 * automatically enabled by default (see {@link #registerPhoneAccount(PhoneAccount)}). 783 * 784 * @param userHandle User handle of phone account owner. 785 * @return The phone account handles. 786 */ getSelfManagedPhoneAccounts(UserHandle userHandle)787 public List<PhoneAccountHandle> getSelfManagedPhoneAccounts(UserHandle userHandle) { 788 return getPhoneAccountHandles( 789 PhoneAccount.CAPABILITY_SELF_MANAGED, 790 PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY /* excludedCapabilities */, 791 null /* uriScheme */, null /* packageName */, false /* includeDisabledAccounts */, 792 userHandle); 793 } 794 getCallCapablePhoneAccountsOfCurrentUser( String uriScheme, boolean includeDisabledAccounts)795 public List<PhoneAccountHandle> getCallCapablePhoneAccountsOfCurrentUser( 796 String uriScheme, boolean includeDisabledAccounts) { 797 return getCallCapablePhoneAccounts(uriScheme, includeDisabledAccounts, mCurrentUserHandle); 798 } 799 800 /** 801 * Retrieves a list of all the SIM-based phone accounts. 802 */ getSimPhoneAccounts(UserHandle userHandle)803 public List<PhoneAccountHandle> getSimPhoneAccounts(UserHandle userHandle) { 804 return getPhoneAccountHandles( 805 PhoneAccount.CAPABILITY_CALL_PROVIDER | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION, 806 null, null, false, userHandle); 807 } 808 getSimPhoneAccountsOfCurrentUser()809 public List<PhoneAccountHandle> getSimPhoneAccountsOfCurrentUser() { 810 return getSimPhoneAccounts(mCurrentUserHandle); 811 } 812 813 /** 814 * Retrieves a list of all phone accounts registered by a specified package. 815 * 816 * @param packageName The name of the package that registered the phone accounts. 817 * @return The phone account handles. 818 */ getPhoneAccountsForPackage(String packageName, UserHandle userHandle)819 public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName, 820 UserHandle userHandle) { 821 return getPhoneAccountHandles(0, null, packageName, false, userHandle); 822 } 823 824 /** 825 * Retrieves a list of all {@link PhoneAccount#CAPABILITY_SELF_MANAGED} phone accounts 826 * registered by a specified package. 827 * 828 * @param packageName The name of the package that registered the phone accounts. 829 * @return The self-managed phone account handles for the given package. 830 */ getSelfManagedPhoneAccountsForPackage(String packageName, UserHandle userHandle)831 public List<PhoneAccountHandle> getSelfManagedPhoneAccountsForPackage(String packageName, 832 UserHandle userHandle) { 833 List<PhoneAccountHandle> phoneAccountsHandles = new ArrayList<>(); 834 for (PhoneAccountHandle pah : getPhoneAccountsForPackage(packageName, 835 userHandle)) { 836 if (isSelfManagedPhoneAccount(pah)) { 837 phoneAccountsHandles.add(pah); 838 } 839 } 840 return phoneAccountsHandles; 841 } 842 843 /** 844 * Determines if a {@link PhoneAccountHandle} is for a self-managed {@link ConnectionService}. 845 * @param handle The handle. 846 * @return {@code true} if for a self-managed {@link ConnectionService}, {@code false} 847 * otherwise. 848 */ isSelfManagedPhoneAccount(@onNull PhoneAccountHandle handle)849 public boolean isSelfManagedPhoneAccount(@NonNull PhoneAccountHandle handle) { 850 PhoneAccount account = getPhoneAccountUnchecked(handle); 851 if (account == null) { 852 return false; 853 } 854 855 return account.isSelfManaged(); 856 } 857 858 /** 859 * Performs checks before calling addOrReplacePhoneAccount(PhoneAccount) 860 * 861 * @param account The {@code PhoneAccount} to add or replace. 862 * @throws SecurityException if package does not have BIND_TELECOM_CONNECTION_SERVICE permission 863 * @throws IllegalArgumentException if MAX_PHONE_ACCOUNT_REGISTRATIONS are reached 864 */ registerPhoneAccount(PhoneAccount account)865 public void registerPhoneAccount(PhoneAccount account) { 866 // Enforce the requirement that a connection service for a phone account has the correct 867 // permission. 868 if (!phoneAccountRequiresBindPermission(account.getAccountHandle())) { 869 Log.w(this, 870 "Phone account %s does not have BIND_TELECOM_CONNECTION_SERVICE permission.", 871 account.getAccountHandle()); 872 throw new SecurityException("PhoneAccount connection service requires " 873 + "BIND_TELECOM_CONNECTION_SERVICE permission."); 874 } 875 //Enforce an upper bound on the number of PhoneAccount's a package can register. 876 // Most apps should only require 1-2. 877 if (getPhoneAccountsForPackage( 878 account.getAccountHandle().getComponentName().getPackageName(), 879 account.getAccountHandle().getUserHandle()).size() 880 >= MAX_PHONE_ACCOUNT_REGISTRATIONS) { 881 Log.w(this, "Phone account %s reached max registration limit for package", 882 account.getAccountHandle()); 883 throw new IllegalArgumentException( 884 "Error, cannot register phone account " + account.getAccountHandle() 885 + " because the limit, " + MAX_PHONE_ACCOUNT_REGISTRATIONS 886 + ", has been reached"); 887 } 888 889 addOrReplacePhoneAccount(account); 890 } 891 892 /** 893 * Adds a {@code PhoneAccount}, replacing an existing one if found. 894 * 895 * @param account The {@code PhoneAccount} to add or replace. 896 */ addOrReplacePhoneAccount(PhoneAccount account)897 private void addOrReplacePhoneAccount(PhoneAccount account) { 898 Log.d(this, "addOrReplacePhoneAccount(%s -> %s)", 899 account.getAccountHandle(), account); 900 901 // Start _enabled_ property as false. 902 // !!! IMPORTANT !!! It is important that we do not read the enabled state that the 903 // source app provides or else an third party app could enable itself. 904 boolean isEnabled = false; 905 boolean isNewAccount; 906 907 PhoneAccount oldAccount = getPhoneAccountUnchecked(account.getAccountHandle()); 908 if (oldAccount != null) { 909 enforceSelfManagedAccountUnmodified(account, oldAccount); 910 mState.accounts.remove(oldAccount); 911 isEnabled = oldAccount.isEnabled(); 912 Log.i(this, "Modify account: %s", getAccountDiffString(account, oldAccount)); 913 isNewAccount = false; 914 } else { 915 Log.i(this, "New phone account registered: " + account); 916 isNewAccount = true; 917 } 918 919 // When registering a self-managed PhoneAccount we enforce the rule that the label that the 920 // app uses is also its phone account label. Also ensure it does not attempt to declare 921 // itself as a sim acct, call manager or call provider. 922 if (account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)) { 923 // Turn off bits we don't want to be able to set (TelecomServiceImpl protects against 924 // this but we'll also prevent it from happening here, just to be safe). 925 int newCapabilities = account.getCapabilities() & 926 ~(PhoneAccount.CAPABILITY_CALL_PROVIDER | 927 PhoneAccount.CAPABILITY_CONNECTION_MANAGER | 928 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION); 929 930 // Ensure name is correct. 931 CharSequence newLabel = mAppLabelProxy.getAppLabel( 932 account.getAccountHandle().getComponentName().getPackageName()); 933 934 account = account.toBuilder() 935 .setLabel(newLabel) 936 .setCapabilities(newCapabilities) 937 .build(); 938 } 939 940 mState.accounts.add(account); 941 // Set defaults and replace based on the group Id. 942 maybeReplaceOldAccount(account); 943 // Reset enabled state to whatever the value was if the account was already registered, 944 // or _true_ if this is a SIM-based account. All SIM-based accounts are always enabled, 945 // as are all self-managed phone accounts. 946 account.setIsEnabled( 947 isEnabled || account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 948 || account.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)); 949 950 write(); 951 fireAccountsChanged(); 952 if (isNewAccount) { 953 fireAccountRegistered(account.getAccountHandle()); 954 } else { 955 fireAccountChanged(account); 956 } 957 // If this is the SIM call manager, tell telephony when the voice ServiceState override 958 // needs to be updated. 959 maybeNotifyTelephonyForVoiceServiceState(account, /* registered= */ true); 960 } 961 unregisterPhoneAccount(PhoneAccountHandle accountHandle)962 public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) { 963 PhoneAccount account = getPhoneAccountUnchecked(accountHandle); 964 if (account != null) { 965 if (mState.accounts.remove(account)) { 966 write(); 967 fireAccountsChanged(); 968 fireAccountUnRegistered(accountHandle); 969 // If this is the SIM call manager, tell telephony when the voice ServiceState 970 // override needs to be updated. 971 maybeNotifyTelephonyForVoiceServiceState(account, /* registered= */ false); 972 } 973 } 974 } 975 enforceSelfManagedAccountUnmodified(PhoneAccount newAccount, PhoneAccount oldAccount)976 private void enforceSelfManagedAccountUnmodified(PhoneAccount newAccount, 977 PhoneAccount oldAccount) { 978 if (oldAccount.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) && 979 (!newAccount.hasCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED))) { 980 EventLog.writeEvent(0x534e4554, "246930197"); 981 Log.w(this, "Self-managed phone account %s replaced by a non self-managed one", 982 newAccount.getAccountHandle()); 983 throw new IllegalArgumentException("Error, cannot change a self-managed " 984 + "phone account " + newAccount.getAccountHandle() 985 + " to other kinds of phone account"); 986 } 987 } 988 989 /** 990 * Un-registers all phone accounts associated with a specified package. 991 * 992 * @param packageName The package for which phone accounts will be removed. 993 * @param userHandle The {@link UserHandle} the package is running under. 994 */ clearAccounts(String packageName, UserHandle userHandle)995 public void clearAccounts(String packageName, UserHandle userHandle) { 996 boolean accountsRemoved = false; 997 Iterator<PhoneAccount> it = mState.accounts.iterator(); 998 while (it.hasNext()) { 999 PhoneAccount phoneAccount = it.next(); 1000 PhoneAccountHandle handle = phoneAccount.getAccountHandle(); 1001 if (Objects.equals(packageName, handle.getComponentName().getPackageName()) 1002 && Objects.equals(userHandle, handle.getUserHandle())) { 1003 Log.i(this, "Removing phone account " + phoneAccount.getLabel()); 1004 mState.accounts.remove(phoneAccount); 1005 accountsRemoved = true; 1006 } 1007 } 1008 1009 if (accountsRemoved) { 1010 write(); 1011 fireAccountsChanged(); 1012 } 1013 } 1014 isVoiceMailNumber(PhoneAccountHandle accountHandle, String number)1015 public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number) { 1016 int subId = getSubscriptionIdForPhoneAccount(accountHandle); 1017 return PhoneNumberUtils.isVoiceMailNumber(mContext, subId, number); 1018 } 1019 addListener(Listener l)1020 public void addListener(Listener l) { 1021 mListeners.add(l); 1022 } 1023 removeListener(Listener l)1024 public void removeListener(Listener l) { 1025 if (l != null) { 1026 mListeners.remove(l); 1027 } 1028 } 1029 fireAccountRegistered(PhoneAccountHandle handle)1030 private void fireAccountRegistered(PhoneAccountHandle handle) { 1031 for (Listener l : mListeners) { 1032 l.onPhoneAccountRegistered(this, handle); 1033 } 1034 } 1035 fireAccountChanged(PhoneAccount account)1036 private void fireAccountChanged(PhoneAccount account) { 1037 for (Listener l : mListeners) { 1038 l.onPhoneAccountChanged(this, account); 1039 } 1040 } 1041 fireAccountUnRegistered(PhoneAccountHandle handle)1042 private void fireAccountUnRegistered(PhoneAccountHandle handle) { 1043 for (Listener l : mListeners) { 1044 l.onPhoneAccountUnRegistered(this, handle); 1045 } 1046 } 1047 fireAccountsChanged()1048 private void fireAccountsChanged() { 1049 for (Listener l : mListeners) { 1050 l.onAccountsChanged(this); 1051 } 1052 } 1053 fireDefaultOutgoingChanged()1054 private void fireDefaultOutgoingChanged() { 1055 for (Listener l : mListeners) { 1056 l.onDefaultOutgoingChanged(this); 1057 } 1058 } 1059 getAccountDiffString(PhoneAccount account1, PhoneAccount account2)1060 private String getAccountDiffString(PhoneAccount account1, PhoneAccount account2) { 1061 if (account1 == null || account2 == null) { 1062 return "Diff: " + account1 + ", " + account2; 1063 } 1064 1065 StringBuffer sb = new StringBuffer(); 1066 sb.append("[").append(account1.getAccountHandle()); 1067 appendDiff(sb, "addr", Log.piiHandle(account1.getAddress()), 1068 Log.piiHandle(account2.getAddress())); 1069 appendDiff(sb, "cap", account1.capabilitiesToString(), account2.capabilitiesToString()); 1070 appendDiff(sb, "hl", account1.getHighlightColor(), account2.getHighlightColor()); 1071 appendDiff(sb, "lbl", account1.getLabel(), account2.getLabel()); 1072 appendDiff(sb, "desc", account1.getShortDescription(), account2.getShortDescription()); 1073 appendDiff(sb, "subAddr", Log.piiHandle(account1.getSubscriptionAddress()), 1074 Log.piiHandle(account2.getSubscriptionAddress())); 1075 appendDiff(sb, "uris", account1.getSupportedUriSchemes(), 1076 account2.getSupportedUriSchemes()); 1077 sb.append("]"); 1078 return sb.toString(); 1079 } 1080 appendDiff(StringBuffer sb, String attrName, Object obj1, Object obj2)1081 private void appendDiff(StringBuffer sb, String attrName, Object obj1, Object obj2) { 1082 if (!Objects.equals(obj1, obj2)) { 1083 sb.append("(") 1084 .append(attrName) 1085 .append(": ") 1086 .append(obj1) 1087 .append(" -> ") 1088 .append(obj2) 1089 .append(")"); 1090 } 1091 } 1092 maybeReplaceOldAccount(PhoneAccount newAccount)1093 private void maybeReplaceOldAccount(PhoneAccount newAccount) { 1094 UserHandle newAccountUserHandle = newAccount.getAccountHandle().getUserHandle(); 1095 DefaultPhoneAccountHandle defaultHandle = 1096 getUserSelectedDefaultPhoneAccount(newAccountUserHandle); 1097 if (defaultHandle == null || defaultHandle.groupId.isEmpty()) { 1098 Log.v(this, "maybeReplaceOldAccount: Not replacing PhoneAccount, no group Id or " + 1099 "default."); 1100 return; 1101 } 1102 if (!defaultHandle.groupId.equals(newAccount.getGroupId())) { 1103 Log.v(this, "maybeReplaceOldAccount: group Ids are not equal."); 1104 return; 1105 } 1106 if (Objects.equals(newAccount.getAccountHandle().getComponentName(), 1107 defaultHandle.phoneAccountHandle.getComponentName())) { 1108 // Move default calling account over to new user, since the ComponentNames and Group Ids 1109 // are the same. 1110 setUserSelectedOutgoingPhoneAccount(newAccount.getAccountHandle(), 1111 newAccountUserHandle); 1112 } else { 1113 Log.v(this, "maybeReplaceOldAccount: group Ids are equal, but ComponentName is not" + 1114 " the same as the default. Not replacing default PhoneAccount."); 1115 } 1116 PhoneAccount replacementAccount = getPhoneAccountByGroupId(newAccount.getGroupId(), 1117 newAccount.getAccountHandle().getComponentName(), newAccountUserHandle, 1118 newAccount.getAccountHandle()); 1119 if (replacementAccount != null) { 1120 // Unregister the old PhoneAccount. 1121 Log.v(this, "maybeReplaceOldAccount: Unregistering old PhoneAccount: " + 1122 replacementAccount.getAccountHandle()); 1123 unregisterPhoneAccount(replacementAccount.getAccountHandle()); 1124 } 1125 } 1126 maybeNotifyTelephonyForVoiceServiceState( @onNull PhoneAccount account, boolean registered)1127 private void maybeNotifyTelephonyForVoiceServiceState( 1128 @NonNull PhoneAccount account, boolean registered) { 1129 // TODO(b/215419665) what about SIM_SUBSCRIPTION accounts? They could theoretically also use 1130 // these capabilities, but don't today. If they do start using them, then there will need to 1131 // be a kind of "or" logic between SIM_SUBSCRIPTION and CONNECTION_MANAGER accounts to get 1132 // the correct value of hasService for a given SIM. 1133 boolean hasService = false; 1134 List<PhoneAccountHandle> simHandlesToNotify; 1135 if (account.hasCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)) { 1136 // When we unregister the SIM call manager account, we always set hasService back to 1137 // false since it is no longer providing OTT calling capability once unregistered. 1138 if (registered) { 1139 // Note: we do *not* early return when the SUPPORTS capability is not present 1140 // because it's possible the SIM call manager could remove either capability at 1141 // runtime and re-register. However, it is an error to use the AVAILABLE capability 1142 // without also setting SUPPORTS. 1143 hasService = 1144 account.hasCapabilities( 1145 PhoneAccount.CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS 1146 | PhoneAccount.CAPABILITY_VOICE_CALLING_AVAILABLE); 1147 } 1148 // Notify for all SIMs that named this component as their SIM call manager in carrier 1149 // config, since there may be more than one impacted SIM here. 1150 simHandlesToNotify = getSimPhoneAccountsFromSimCallManager(account.getAccountHandle()); 1151 } else if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) { 1152 // When new SIMs get registered, we notify them of their current voice status override. 1153 // If there is no SIM call manager for this SIM, we treat that as hasService = false and 1154 // still notify to ensure consistency. 1155 if (!registered) { 1156 // We don't do anything when SIMs are unregistered because we won't have an active 1157 // subId to map back to phoneId and tell telephony about; that case is handled by 1158 // telephony internally. 1159 return; 1160 } 1161 PhoneAccountHandle simCallManagerHandle = 1162 getSimCallManagerFromHandle( 1163 account.getAccountHandle(), account.getAccountHandle().getUserHandle()); 1164 if (simCallManagerHandle != null) { 1165 PhoneAccount simCallManager = getPhoneAccountUnchecked(simCallManagerHandle); 1166 hasService = 1167 simCallManager != null 1168 && simCallManager.hasCapabilities( 1169 PhoneAccount.CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS 1170 | PhoneAccount.CAPABILITY_VOICE_CALLING_AVAILABLE); 1171 } 1172 simHandlesToNotify = Collections.singletonList(account.getAccountHandle()); 1173 } else { 1174 // Not a relevant account - we only care about CONNECTION_MANAGER and SIM_SUBSCRIPTION. 1175 return; 1176 } 1177 if (simHandlesToNotify.isEmpty()) return; 1178 Log.i( 1179 this, 1180 "Notifying telephony of voice service override change for %d SIMs, hasService = %b", 1181 simHandlesToNotify.size(), 1182 hasService); 1183 for (PhoneAccountHandle simHandle : simHandlesToNotify) { 1184 // This may be null if there are no active SIMs but the device is still camped for 1185 // emergency calls and registered a SIM_SUBSCRIPTION for that purpose. 1186 TelephonyManager simTm = mTelephonyManager.createForPhoneAccountHandle(simHandle); 1187 if (simTm == null) continue; 1188 simTm.setVoiceServiceStateOverride(hasService); 1189 } 1190 } 1191 1192 /** 1193 * Determines if the connection service specified by a {@link PhoneAccountHandle} requires the 1194 * {@link Manifest.permission#BIND_TELECOM_CONNECTION_SERVICE} permission. 1195 * 1196 * @param phoneAccountHandle The phone account to check. 1197 * @return {@code True} if the phone account has permission. 1198 */ phoneAccountRequiresBindPermission(PhoneAccountHandle phoneAccountHandle)1199 public boolean phoneAccountRequiresBindPermission(PhoneAccountHandle phoneAccountHandle) { 1200 List<ResolveInfo> resolveInfos = resolveComponent(phoneAccountHandle); 1201 if (resolveInfos.isEmpty()) { 1202 Log.w(this, "phoneAccount %s not found", phoneAccountHandle.getComponentName()); 1203 return false; 1204 } 1205 for (ResolveInfo resolveInfo : resolveInfos) { 1206 ServiceInfo serviceInfo = resolveInfo.serviceInfo; 1207 if (serviceInfo == null) { 1208 return false; 1209 } 1210 1211 if (!Manifest.permission.BIND_CONNECTION_SERVICE.equals(serviceInfo.permission) && 1212 !Manifest.permission.BIND_TELECOM_CONNECTION_SERVICE.equals( 1213 serviceInfo.permission)) { 1214 // The ConnectionService must require either the deprecated BIND_CONNECTION_SERVICE, 1215 // or the public BIND_TELECOM_CONNECTION_SERVICE permissions, both of which are 1216 // system/signature only. 1217 return false; 1218 } 1219 } 1220 return true; 1221 } 1222 1223 // 1224 // Methods for retrieving PhoneAccounts and PhoneAccountHandles 1225 // 1226 1227 /** 1228 * Returns the PhoneAccount for the specified handle. Does no user checking. 1229 * 1230 * @param handle 1231 * @return The corresponding phone account if one exists. 1232 */ getPhoneAccountUnchecked(PhoneAccountHandle handle)1233 public PhoneAccount getPhoneAccountUnchecked(PhoneAccountHandle handle) { 1234 for (PhoneAccount m : mState.accounts) { 1235 if (Objects.equals(handle, m.getAccountHandle())) { 1236 return m; 1237 } 1238 } 1239 return null; 1240 } 1241 1242 /** 1243 * Like getPhoneAccount, but checks to see if the current user is allowed to see the phone 1244 * account before returning it. The current user is the active user on the actual android 1245 * device. 1246 */ getPhoneAccount(PhoneAccountHandle handle, UserHandle userHandle)1247 public PhoneAccount getPhoneAccount(PhoneAccountHandle handle, UserHandle userHandle) { 1248 return getPhoneAccount(handle, userHandle, /* acrossProfiles */ false); 1249 } 1250 getPhoneAccount(PhoneAccountHandle handle, UserHandle userHandle, boolean acrossProfiles)1251 public PhoneAccount getPhoneAccount(PhoneAccountHandle handle, 1252 UserHandle userHandle, boolean acrossProfiles) { 1253 PhoneAccount account = getPhoneAccountUnchecked(handle); 1254 if (account != null && (isVisibleForUser(account, userHandle, acrossProfiles))) { 1255 return account; 1256 } 1257 return null; 1258 } 1259 getPhoneAccountOfCurrentUser(PhoneAccountHandle handle)1260 public PhoneAccount getPhoneAccountOfCurrentUser(PhoneAccountHandle handle) { 1261 return getPhoneAccount(handle, mCurrentUserHandle); 1262 } 1263 getPhoneAccountHandles( int capabilities, String uriScheme, String packageName, boolean includeDisabledAccounts, UserHandle userHandle)1264 private List<PhoneAccountHandle> getPhoneAccountHandles( 1265 int capabilities, 1266 String uriScheme, 1267 String packageName, 1268 boolean includeDisabledAccounts, 1269 UserHandle userHandle) { 1270 return getPhoneAccountHandles(capabilities, 0 /*excludedCapabilities*/, uriScheme, 1271 packageName, includeDisabledAccounts, userHandle); 1272 } 1273 1274 /** 1275 * Returns a list of phone account handles with the specified capabilities, uri scheme, 1276 * and package name. 1277 */ getPhoneAccountHandles( int capabilities, int excludedCapabilities, String uriScheme, String packageName, boolean includeDisabledAccounts, UserHandle userHandle)1278 private List<PhoneAccountHandle> getPhoneAccountHandles( 1279 int capabilities, 1280 int excludedCapabilities, 1281 String uriScheme, 1282 String packageName, 1283 boolean includeDisabledAccounts, 1284 UserHandle userHandle) { 1285 List<PhoneAccountHandle> handles = new ArrayList<>(); 1286 1287 for (PhoneAccount account : getPhoneAccounts( 1288 capabilities, excludedCapabilities, uriScheme, packageName, 1289 includeDisabledAccounts, userHandle)) { 1290 handles.add(account.getAccountHandle()); 1291 } 1292 return handles; 1293 } 1294 getPhoneAccounts( int capabilities, String uriScheme, String packageName, boolean includeDisabledAccounts, UserHandle userHandle)1295 private List<PhoneAccount> getPhoneAccounts( 1296 int capabilities, 1297 String uriScheme, 1298 String packageName, 1299 boolean includeDisabledAccounts, 1300 UserHandle userHandle) { 1301 return getPhoneAccounts(capabilities, 0 /*excludedCapabilities*/, uriScheme, packageName, 1302 includeDisabledAccounts, userHandle); 1303 } 1304 1305 /** 1306 * Returns a list of phone account handles with the specified flag, supporting the specified 1307 * URI scheme, within the specified package name. 1308 * 1309 * @param capabilities Capabilities which the {@code PhoneAccount} must have. Ignored if 0. 1310 * @param excludedCapabilities Capabilities which the {@code PhoneAccount} must not have. 1311 * Ignored if 0. 1312 * @param uriScheme URI schemes the PhoneAccount must handle. {@code null} bypasses the 1313 * URI scheme check. 1314 * @param packageName Package name of the PhoneAccount. {@code null} bypasses packageName check. 1315 */ getPhoneAccounts( int capabilities, int excludedCapabilities, String uriScheme, String packageName, boolean includeDisabledAccounts, UserHandle userHandle)1316 private List<PhoneAccount> getPhoneAccounts( 1317 int capabilities, 1318 int excludedCapabilities, 1319 String uriScheme, 1320 String packageName, 1321 boolean includeDisabledAccounts, 1322 UserHandle userHandle) { 1323 List<PhoneAccount> accounts = new ArrayList<>(mState.accounts.size()); 1324 for (PhoneAccount m : mState.accounts) { 1325 if (!(m.isEnabled() || includeDisabledAccounts)) { 1326 // Do not include disabled accounts. 1327 continue; 1328 } 1329 1330 if ((m.getCapabilities() & excludedCapabilities) != 0) { 1331 // If an excluded capability is present, skip. 1332 continue; 1333 } 1334 1335 if (capabilities != 0 && !m.hasCapabilities(capabilities)) { 1336 // Account doesn't have the right capabilities; skip this one. 1337 continue; 1338 } 1339 if (uriScheme != null && !m.supportsUriScheme(uriScheme)) { 1340 // Account doesn't support this URI scheme; skip this one. 1341 continue; 1342 } 1343 PhoneAccountHandle handle = m.getAccountHandle(); 1344 1345 if (resolveComponent(handle).isEmpty()) { 1346 // This component cannot be resolved anymore; skip this one. 1347 continue; 1348 } 1349 if (packageName != null && 1350 !packageName.equals(handle.getComponentName().getPackageName())) { 1351 // Not the right package name; skip this one. 1352 continue; 1353 } 1354 if (!isVisibleForUser(m, userHandle, false)) { 1355 // Account is not visible for the current user; skip this one. 1356 continue; 1357 } 1358 accounts.add(m); 1359 } 1360 return accounts; 1361 } 1362 1363 /** 1364 * Clean up the orphan {@code PhoneAccount}. An orphan {@code PhoneAccount} is a phone 1365 * account that does not have a {@code UserHandle} or belongs to a deleted package. 1366 * 1367 * @return the number of orphan {@code PhoneAccount} deleted. 1368 */ cleanupOrphanedPhoneAccounts()1369 public int cleanupOrphanedPhoneAccounts() { 1370 ArrayList<PhoneAccount> badAccountsList = new ArrayList<>(); 1371 HashMap<String, Boolean> packageLookup = new HashMap<>(); 1372 HashMap<PhoneAccount, Boolean> userHandleLookup = new HashMap<>(); 1373 1374 // iterate over all accounts in registrar 1375 for (PhoneAccount pa : mState.accounts) { 1376 String packageName = pa.getAccountHandle().getComponentName().getPackageName(); 1377 1378 // check if the package for the PhoneAccount is uninstalled 1379 if (packageLookup.computeIfAbsent(packageName, 1380 pn -> isPackageUninstalled(pn))) { 1381 badAccountsList.add(pa); 1382 } 1383 // check if PhoneAccount does not have a valid UserHandle (user was deleted) 1384 else if (userHandleLookup.computeIfAbsent(pa, 1385 a -> isUserHandleDeletedForPhoneAccount(a))) { 1386 badAccountsList.add(pa); 1387 } 1388 } 1389 1390 mState.accounts.removeAll(badAccountsList); 1391 1392 return badAccountsList.size(); 1393 } 1394 isPackageUninstalled(String packageName)1395 public Boolean isPackageUninstalled(String packageName) { 1396 try { 1397 mContext.getPackageManager().getPackageInfo(packageName, 0); 1398 return false; 1399 } catch (PackageManager.NameNotFoundException e) { 1400 return true; 1401 } 1402 } 1403 isUserHandleDeletedForPhoneAccount(PhoneAccount phoneAccount)1404 private Boolean isUserHandleDeletedForPhoneAccount(PhoneAccount phoneAccount) { 1405 UserHandle userHandle = phoneAccount.getAccountHandle().getUserHandle(); 1406 return (userHandle == null) || 1407 (mUserManager.getSerialNumberForUser(userHandle) == -1L); 1408 } 1409 1410 // 1411 // State Implementation for PhoneAccountRegistrar 1412 // 1413 1414 /** 1415 * The state of this {@code PhoneAccountRegistrar}. 1416 */ 1417 @VisibleForTesting 1418 public static class State { 1419 /** 1420 * Store the default phone account handle of users. If no record of a user can be found in 1421 * the map, it means that no default phone account handle is set in that user. 1422 */ 1423 public final Map<UserHandle, DefaultPhoneAccountHandle> defaultOutgoingAccountHandles 1424 = new ConcurrentHashMap<>(); 1425 1426 /** 1427 * The complete list of {@code PhoneAccount}s known to the Telecom subsystem. 1428 */ 1429 public final List<PhoneAccount> accounts = new CopyOnWriteArrayList<>(); 1430 1431 /** 1432 * The version number of the State data. 1433 */ 1434 public int versionNumber; 1435 } 1436 1437 /** 1438 * The default {@link PhoneAccountHandle} of a user. 1439 */ 1440 public static class DefaultPhoneAccountHandle { 1441 1442 public final UserHandle userHandle; 1443 1444 public PhoneAccountHandle phoneAccountHandle; 1445 1446 public final String groupId; 1447 DefaultPhoneAccountHandle(UserHandle userHandle, PhoneAccountHandle phoneAccountHandle, String groupId)1448 public DefaultPhoneAccountHandle(UserHandle userHandle, 1449 PhoneAccountHandle phoneAccountHandle, String groupId) { 1450 this.userHandle = userHandle; 1451 this.phoneAccountHandle = phoneAccountHandle; 1452 this.groupId = groupId; 1453 } 1454 } 1455 1456 /** 1457 * Dumps the state of the {@link CallsManager}. 1458 * 1459 * @param pw The {@code IndentingPrintWriter} to write the state to. 1460 */ dump(IndentingPrintWriter pw)1461 public void dump(IndentingPrintWriter pw) { 1462 if (mState != null) { 1463 pw.println("xmlVersion: " + mState.versionNumber); 1464 DefaultPhoneAccountHandle defaultPhoneAccountHandle 1465 = mState.defaultOutgoingAccountHandles.get(Process.myUserHandle()); 1466 pw.println("defaultOutgoing: " + (defaultPhoneAccountHandle == null ? "none" : 1467 defaultPhoneAccountHandle.phoneAccountHandle)); 1468 PhoneAccountHandle defaultOutgoing = 1469 getOutgoingPhoneAccountForScheme(PhoneAccount.SCHEME_TEL, mCurrentUserHandle); 1470 pw.print("outgoingPhoneAccountForTelScheme: "); 1471 if (defaultOutgoing == null) { 1472 pw.println("none"); 1473 } else { 1474 pw.println(defaultOutgoing); 1475 } 1476 pw.println("simCallManager: " + getSimCallManager(mCurrentUserHandle)); 1477 pw.println("phoneAccounts:"); 1478 pw.increaseIndent(); 1479 for (PhoneAccount phoneAccount : mState.accounts) { 1480 pw.println(phoneAccount); 1481 } 1482 pw.decreaseIndent(); 1483 pw.increaseIndent(); 1484 pw.println("test emergency PhoneAccount filter: " + mTestPhoneAccountPackageNameFilter); 1485 pw.decreaseIndent(); 1486 } 1487 } 1488 sortPhoneAccounts()1489 private void sortPhoneAccounts() { 1490 if (mState.accounts.size() > 1) { 1491 // Sort the phone accounts using sort order: 1492 // 1) SIM accounts first, followed by non-sim accounts 1493 // 2) Sort order, with those specifying no sort order last. 1494 // 3) Label 1495 1496 // Comparator to sort SIM subscriptions before non-sim subscriptions. 1497 Comparator<PhoneAccount> bySimCapability = (p1, p2) -> { 1498 if (p1.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 1499 && !p2.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) { 1500 return -1; 1501 } else if (!p1.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 1502 && p2.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) { 1503 return 1; 1504 } else { 1505 return 0; 1506 } 1507 }; 1508 1509 // Create a string comparator which will sort strings, placing nulls last. 1510 Comparator<String> nullSafeStringComparator = Comparator.nullsLast( 1511 String::compareTo); 1512 1513 // Comparator which places PhoneAccounts with a specified sort order first, followed by 1514 // those with no sort order. 1515 Comparator<PhoneAccount> bySortOrder = (p1, p2) -> { 1516 int sort1 = p1.getExtras() == null ? Integer.MAX_VALUE: 1517 p1.getExtras().getInt(PhoneAccount.EXTRA_SORT_ORDER, Integer.MAX_VALUE); 1518 int sort2 = p2.getExtras() == null ? Integer.MAX_VALUE: 1519 p2.getExtras().getInt(PhoneAccount.EXTRA_SORT_ORDER, Integer.MAX_VALUE); 1520 return Integer.compare(sort1, sort2); 1521 }; 1522 1523 // Comparator which sorts PhoneAccounts by label. 1524 Comparator<PhoneAccount> byLabel = (p1, p2) -> { 1525 String s1 = p1.getLabel() == null ? null : p1.getLabel().toString(); 1526 String s2 = p2.getLabel() == null ? null : p2.getLabel().toString(); 1527 return nullSafeStringComparator.compare(s1, s2); 1528 }; 1529 1530 // Sort the phone accounts. 1531 mState.accounts.sort(bySimCapability.thenComparing(bySortOrder.thenComparing(byLabel))); 1532 } 1533 } 1534 1535 //////////////////////////////////////////////////////////////////////////////////////////////// 1536 // 1537 // State management 1538 // 1539 1540 private class AsyncXmlWriter extends AsyncTask<ByteArrayOutputStream, Void, Void> { 1541 @Override doInBackground(ByteArrayOutputStream... args)1542 public Void doInBackground(ByteArrayOutputStream... args) { 1543 final ByteArrayOutputStream buffer = args[0]; 1544 FileOutputStream fileOutput = null; 1545 try { 1546 synchronized (mWriteLock) { 1547 fileOutput = mAtomicFile.startWrite(); 1548 buffer.writeTo(fileOutput); 1549 mAtomicFile.finishWrite(fileOutput); 1550 } 1551 } catch (IOException e) { 1552 Log.e(this, e, "Writing state to XML file"); 1553 mAtomicFile.failWrite(fileOutput); 1554 } 1555 return null; 1556 } 1557 } 1558 write()1559 private void write() { 1560 try { 1561 sortPhoneAccounts(); 1562 ByteArrayOutputStream os = new ByteArrayOutputStream(); 1563 XmlSerializer serializer = Xml.resolveSerializer(os); 1564 writeToXml(mState, serializer, mContext); 1565 serializer.flush(); 1566 new AsyncXmlWriter().execute(os); 1567 } catch (IOException e) { 1568 Log.e(this, e, "Writing state to XML buffer"); 1569 } 1570 } 1571 read()1572 private void read() { 1573 final InputStream is; 1574 try { 1575 is = mAtomicFile.openRead(); 1576 } catch (FileNotFoundException ex) { 1577 return; 1578 } 1579 1580 boolean versionChanged = false; 1581 1582 try { 1583 XmlPullParser parser = Xml.resolvePullParser(is); 1584 parser.nextTag(); 1585 mState = readFromXml(parser, mContext); 1586 migratePhoneAccountHandle(mState); 1587 versionChanged = mState.versionNumber < EXPECTED_STATE_VERSION; 1588 1589 } catch (IOException | XmlPullParserException e) { 1590 Log.e(this, e, "Reading state from XML file"); 1591 mState = new State(); 1592 } finally { 1593 try { 1594 is.close(); 1595 } catch (IOException e) { 1596 Log.e(this, e, "Closing InputStream"); 1597 } 1598 } 1599 1600 // Verify all of the UserHandles. 1601 List<PhoneAccount> badAccounts = new ArrayList<>(); 1602 for (PhoneAccount phoneAccount : mState.accounts) { 1603 UserHandle userHandle = phoneAccount.getAccountHandle().getUserHandle(); 1604 if (userHandle == null) { 1605 Log.w(this, "Missing UserHandle for %s", phoneAccount); 1606 badAccounts.add(phoneAccount); 1607 } else if (mUserManager.getSerialNumberForUser(userHandle) == -1) { 1608 Log.w(this, "User does not exist for %s", phoneAccount); 1609 badAccounts.add(phoneAccount); 1610 } 1611 } 1612 mState.accounts.removeAll(badAccounts); 1613 1614 // If an upgrade occurred, write out the changed data. 1615 if (versionChanged || !badAccounts.isEmpty()) { 1616 write(); 1617 } 1618 } 1619 1620 private static void writeToXml(State state, XmlSerializer serializer, Context context) 1621 throws IOException { 1622 sStateXml.writeToXml(state, serializer, context); 1623 } 1624 1625 private static State readFromXml(XmlPullParser parser, Context context) 1626 throws IOException, XmlPullParserException { 1627 State s = sStateXml.readFromXml(parser, 0, context); 1628 return s != null ? s : new State(); 1629 } 1630 1631 /** 1632 * Try to migrate the ID of default phone account handle from IccId to SubId. 1633 */ 1634 @VisibleForTesting 1635 public void migratePhoneAccountHandle(State state) { 1636 if (mSubscriptionManager == null) { 1637 return; 1638 } 1639 // Use getAllSubscirptionInfoList() to get the mapping between iccId and subId 1640 // from the subscription database 1641 List<SubscriptionInfo> subscriptionInfos = mSubscriptionManager 1642 .getAllSubscriptionInfoList(); 1643 Map<UserHandle, DefaultPhoneAccountHandle> defaultPhoneAccountHandles 1644 = state.defaultOutgoingAccountHandles; 1645 for (Map.Entry<UserHandle, DefaultPhoneAccountHandle> entry 1646 : defaultPhoneAccountHandles.entrySet()) { 1647 DefaultPhoneAccountHandle defaultPhoneAccountHandle = entry.getValue(); 1648 1649 // Migrate Telephony PhoneAccountHandle only 1650 String telephonyComponentName = 1651 "com.android.phone/com.android.services.telephony.TelephonyConnectionService"; 1652 if (!defaultPhoneAccountHandle.phoneAccountHandle.getComponentName() 1653 .flattenToString().equals(telephonyComponentName)) { 1654 continue; 1655 } 1656 // Migrate from IccId to SubId 1657 for (SubscriptionInfo subscriptionInfo : subscriptionInfos) { 1658 String phoneAccountHandleId = defaultPhoneAccountHandle.phoneAccountHandle.getId(); 1659 // Some phone account handle would store phone account handle id with the IccId 1660 // string plus "F", and the getIccId() returns IccId string itself without "F", 1661 // so here need to use "startsWith" to match. 1662 if (phoneAccountHandleId != null && phoneAccountHandleId.startsWith( 1663 subscriptionInfo.getIccId())) { 1664 Log.i(this, "Found subscription ID to migrate: " 1665 + subscriptionInfo.getSubscriptionId()); 1666 defaultPhoneAccountHandle.phoneAccountHandle = new PhoneAccountHandle( 1667 defaultPhoneAccountHandle.phoneAccountHandle.getComponentName(), 1668 Integer.toString(subscriptionInfo.getSubscriptionId())); 1669 break; 1670 } 1671 } 1672 } 1673 } 1674 1675 //////////////////////////////////////////////////////////////////////////////////////////////// 1676 // 1677 // XML serialization 1678 // 1679 1680 @VisibleForTesting 1681 public abstract static class XmlSerialization<T> { 1682 private static final String TAG_VALUE = "value"; 1683 private static final String ATTRIBUTE_LENGTH = "length"; 1684 private static final String ATTRIBUTE_KEY = "key"; 1685 private static final String ATTRIBUTE_VALUE_TYPE = "type"; 1686 private static final String VALUE_TYPE_STRING = "string"; 1687 private static final String VALUE_TYPE_INTEGER = "integer"; 1688 private static final String VALUE_TYPE_BOOLEAN = "boolean"; 1689 1690 /** 1691 * Write the supplied object to XML 1692 */ 1693 public abstract void writeToXml(T o, XmlSerializer serializer, Context context) 1694 throws IOException; 1695 1696 /** 1697 * Read from the supplied XML into a new object, returning null in case of an 1698 * unrecoverable schema mismatch or other data error. 'parser' must be already 1699 * positioned at the first tag that is expected to have been emitted by this 1700 * object's writeToXml(). This object tries to fail early without modifying 1701 * 'parser' if it does not recognize the data it sees. 1702 */ 1703 public abstract T readFromXml(XmlPullParser parser, int version, Context context) 1704 throws IOException, XmlPullParserException; 1705 1706 protected void writeTextIfNonNull(String tagName, Object value, XmlSerializer serializer) 1707 throws IOException { 1708 if (value != null) { 1709 serializer.startTag(null, tagName); 1710 serializer.text(Objects.toString(value)); 1711 serializer.endTag(null, tagName); 1712 } 1713 } 1714 1715 /** 1716 * Serializes a string array. 1717 * 1718 * @param tagName The tag name for the string array. 1719 * @param values The string values to serialize. 1720 * @param serializer The serializer. 1721 * @throws IOException 1722 */ 1723 protected void writeStringList(String tagName, List<String> values, 1724 XmlSerializer serializer) 1725 throws IOException { 1726 1727 serializer.startTag(null, tagName); 1728 if (values != null) { 1729 serializer.attribute(null, ATTRIBUTE_LENGTH, Objects.toString(values.size())); 1730 for (String toSerialize : values) { 1731 serializer.startTag(null, TAG_VALUE); 1732 if (toSerialize != null ){ 1733 serializer.text(toSerialize); 1734 } 1735 serializer.endTag(null, TAG_VALUE); 1736 } 1737 } else { 1738 serializer.attribute(null, ATTRIBUTE_LENGTH, "0"); 1739 } 1740 serializer.endTag(null, tagName); 1741 } 1742 1743 protected void writeBundle(String tagName, Bundle values, XmlSerializer serializer) 1744 throws IOException { 1745 1746 serializer.startTag(null, tagName); 1747 if (values != null) { 1748 for (String key : values.keySet()) { 1749 Object value = values.get(key); 1750 1751 if (value == null) { 1752 continue; 1753 } 1754 1755 String valueType; 1756 if (value instanceof String) { 1757 valueType = VALUE_TYPE_STRING; 1758 } else if (value instanceof Integer) { 1759 valueType = VALUE_TYPE_INTEGER; 1760 } else if (value instanceof Boolean) { 1761 valueType = VALUE_TYPE_BOOLEAN; 1762 } else { 1763 Log.w(this, 1764 "PhoneAccounts support only string, integer and boolean extras TY."); 1765 continue; 1766 } 1767 1768 serializer.startTag(null, TAG_VALUE); 1769 serializer.attribute(null, ATTRIBUTE_KEY, key); 1770 serializer.attribute(null, ATTRIBUTE_VALUE_TYPE, valueType); 1771 serializer.text(Objects.toString(value)); 1772 serializer.endTag(null, TAG_VALUE); 1773 } 1774 } 1775 serializer.endTag(null, tagName); 1776 } 1777 1778 protected void writeIconIfNonNull(String tagName, Icon value, XmlSerializer serializer) 1779 throws IOException { 1780 if (value != null) { 1781 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 1782 value.writeToStream(stream); 1783 byte[] iconByteArray = stream.toByteArray(); 1784 String text = Base64.encodeToString(iconByteArray, 0, iconByteArray.length, 0); 1785 1786 serializer.startTag(null, tagName); 1787 serializer.text(text); 1788 serializer.endTag(null, tagName); 1789 } 1790 } 1791 1792 protected void writeLong(String tagName, long value, XmlSerializer serializer) 1793 throws IOException { 1794 serializer.startTag(null, tagName); 1795 serializer.text(Long.valueOf(value).toString()); 1796 serializer.endTag(null, tagName); 1797 } 1798 1799 protected void writeNonNullString(String tagName, String value, XmlSerializer serializer) 1800 throws IOException { 1801 serializer.startTag(null, tagName); 1802 serializer.text(value != null ? value : ""); 1803 serializer.endTag(null, tagName); 1804 } 1805 1806 /** 1807 * Reads a string array from the XML parser. 1808 * 1809 * @param parser The XML parser. 1810 * @return String array containing the parsed values. 1811 * @throws IOException Exception related to IO. 1812 * @throws XmlPullParserException Exception related to parsing. 1813 */ 1814 protected List<String> readStringList(XmlPullParser parser) 1815 throws IOException, XmlPullParserException { 1816 1817 int length = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_LENGTH)); 1818 List<String> arrayEntries = new ArrayList<String>(length); 1819 String value = null; 1820 1821 if (length == 0) { 1822 return arrayEntries; 1823 } 1824 1825 int outerDepth = parser.getDepth(); 1826 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 1827 if (parser.getName().equals(TAG_VALUE)) { 1828 parser.next(); 1829 value = parser.getText(); 1830 arrayEntries.add(value); 1831 } 1832 } 1833 1834 return arrayEntries; 1835 } 1836 1837 /** 1838 * Reads a bundle from the XML parser. 1839 * 1840 * @param parser The XML parser. 1841 * @return Bundle containing the parsed values. 1842 * @throws IOException Exception related to IO. 1843 * @throws XmlPullParserException Exception related to parsing. 1844 */ 1845 protected Bundle readBundle(XmlPullParser parser) 1846 throws IOException, XmlPullParserException { 1847 1848 Bundle bundle = null; 1849 int outerDepth = parser.getDepth(); 1850 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 1851 if (parser.getName().equals(TAG_VALUE)) { 1852 String valueType = parser.getAttributeValue(null, ATTRIBUTE_VALUE_TYPE); 1853 String key = parser.getAttributeValue(null, ATTRIBUTE_KEY); 1854 parser.next(); 1855 String value = parser.getText(); 1856 1857 if (bundle == null) { 1858 bundle = new Bundle(); 1859 } 1860 1861 // Do not write null values to the bundle. 1862 if (value == null) { 1863 continue; 1864 } 1865 1866 if (VALUE_TYPE_STRING.equals(valueType)) { 1867 bundle.putString(key, value); 1868 } else if (VALUE_TYPE_INTEGER.equals(valueType)) { 1869 try { 1870 int intValue = Integer.parseInt(value); 1871 bundle.putInt(key, intValue); 1872 } catch (NumberFormatException nfe) { 1873 Log.w(this, "Invalid integer PhoneAccount extra."); 1874 } 1875 } else if (VALUE_TYPE_BOOLEAN.equals(valueType)) { 1876 boolean boolValue = Boolean.parseBoolean(value); 1877 bundle.putBoolean(key, boolValue); 1878 } else { 1879 Log.w(this, "Invalid type " + valueType + " for PhoneAccount bundle."); 1880 } 1881 } 1882 } 1883 return bundle; 1884 } 1885 1886 protected Bitmap readBitmap(XmlPullParser parser) { 1887 byte[] imageByteArray = Base64.decode(parser.getText(), 0); 1888 return BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length); 1889 } 1890 1891 @Nullable 1892 protected Icon readIcon(XmlPullParser parser) throws IOException { 1893 try { 1894 byte[] iconByteArray = Base64.decode(parser.getText(), 0); 1895 ByteArrayInputStream stream = new ByteArrayInputStream(iconByteArray); 1896 return Icon.createFromStream(stream); 1897 } catch (IllegalArgumentException e) { 1898 Log.e(this, e, "Bitmap must not be null."); 1899 return null; 1900 } 1901 } 1902 } 1903 1904 @VisibleForTesting 1905 public static final XmlSerialization<State> sStateXml = 1906 new XmlSerialization<State>() { 1907 private static final String CLASS_STATE = "phone_account_registrar_state"; 1908 private static final String DEFAULT_OUTGOING = "default_outgoing"; 1909 private static final String ACCOUNTS = "accounts"; 1910 private static final String VERSION = "version"; 1911 1912 @Override 1913 public void writeToXml(State o, XmlSerializer serializer, Context context) 1914 throws IOException { 1915 if (o != null) { 1916 serializer.startTag(null, CLASS_STATE); 1917 serializer.attribute(null, VERSION, Objects.toString(EXPECTED_STATE_VERSION)); 1918 1919 serializer.startTag(null, DEFAULT_OUTGOING); 1920 for (DefaultPhoneAccountHandle defaultPhoneAccountHandle : o 1921 .defaultOutgoingAccountHandles.values()) { 1922 sDefaultPhoneAcountHandleXml 1923 .writeToXml(defaultPhoneAccountHandle, serializer, context); 1924 } 1925 serializer.endTag(null, DEFAULT_OUTGOING); 1926 1927 serializer.startTag(null, ACCOUNTS); 1928 for (PhoneAccount m : o.accounts) { 1929 sPhoneAccountXml.writeToXml(m, serializer, context); 1930 } 1931 serializer.endTag(null, ACCOUNTS); 1932 1933 serializer.endTag(null, CLASS_STATE); 1934 } 1935 } 1936 1937 @Override 1938 public State readFromXml(XmlPullParser parser, int version, Context context) 1939 throws IOException, XmlPullParserException { 1940 if (parser.getName().equals(CLASS_STATE)) { 1941 State s = new State(); 1942 1943 String rawVersion = parser.getAttributeValue(null, VERSION); 1944 s.versionNumber = TextUtils.isEmpty(rawVersion) ? 1 : Integer.parseInt(rawVersion); 1945 1946 int outerDepth = parser.getDepth(); 1947 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 1948 if (parser.getName().equals(DEFAULT_OUTGOING)) { 1949 if (s.versionNumber < 9) { 1950 // Migrate old default phone account handle here by assuming the 1951 // default phone account handle belongs to the primary user. Also, 1952 // assume there are no groups. 1953 parser.nextTag(); 1954 PhoneAccountHandle phoneAccountHandle = sPhoneAccountHandleXml 1955 .readFromXml(parser, s.versionNumber, context); 1956 UserManager userManager = UserManager.get(context); 1957 UserInfo primaryUser = userManager.getPrimaryUser(); 1958 if (primaryUser != null) { 1959 UserHandle userHandle = primaryUser.getUserHandle(); 1960 DefaultPhoneAccountHandle defaultPhoneAccountHandle 1961 = new DefaultPhoneAccountHandle(userHandle, 1962 phoneAccountHandle, "" /* groupId */); 1963 s.defaultOutgoingAccountHandles 1964 .put(userHandle, defaultPhoneAccountHandle); 1965 } 1966 } else { 1967 int defaultAccountHandlesDepth = parser.getDepth(); 1968 while (XmlUtils.nextElementWithin(parser, defaultAccountHandlesDepth)) { 1969 DefaultPhoneAccountHandle accountHandle 1970 = sDefaultPhoneAcountHandleXml 1971 .readFromXml(parser, s.versionNumber, context); 1972 if (accountHandle != null && s.accounts != null) { 1973 s.defaultOutgoingAccountHandles 1974 .put(accountHandle.userHandle, accountHandle); 1975 } 1976 } 1977 } 1978 } else if (parser.getName().equals(ACCOUNTS)) { 1979 int accountsDepth = parser.getDepth(); 1980 while (XmlUtils.nextElementWithin(parser, accountsDepth)) { 1981 PhoneAccount account = sPhoneAccountXml.readFromXml(parser, 1982 s.versionNumber, context); 1983 1984 if (account != null && s.accounts != null) { 1985 s.accounts.add(account); 1986 } 1987 } 1988 } 1989 } 1990 return s; 1991 } 1992 return null; 1993 } 1994 }; 1995 1996 @VisibleForTesting 1997 public static final XmlSerialization<DefaultPhoneAccountHandle> sDefaultPhoneAcountHandleXml = 1998 new XmlSerialization<DefaultPhoneAccountHandle>() { 1999 private static final String CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE 2000 = "default_outgoing_phone_account_handle"; 2001 private static final String USER_SERIAL_NUMBER = "user_serial_number"; 2002 private static final String GROUP_ID = "group_id"; 2003 private static final String ACCOUNT_HANDLE = "account_handle"; 2004 2005 @Override 2006 public void writeToXml(DefaultPhoneAccountHandle o, XmlSerializer serializer, 2007 Context context) throws IOException { 2008 if (o != null) { 2009 final UserManager userManager = UserManager.get(context); 2010 final long serialNumber = userManager.getSerialNumberForUser(o.userHandle); 2011 if (serialNumber != -1) { 2012 serializer.startTag(null, CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE); 2013 writeLong(USER_SERIAL_NUMBER, serialNumber, serializer); 2014 writeNonNullString(GROUP_ID, o.groupId, serializer); 2015 serializer.startTag(null, ACCOUNT_HANDLE); 2016 sPhoneAccountHandleXml.writeToXml(o.phoneAccountHandle, serializer, 2017 context); 2018 serializer.endTag(null, ACCOUNT_HANDLE); 2019 serializer.endTag(null, CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE); 2020 } 2021 } 2022 } 2023 2024 @Override 2025 public DefaultPhoneAccountHandle readFromXml(XmlPullParser parser, int version, 2026 Context context) 2027 throws IOException, XmlPullParserException { 2028 if (parser.getName().equals(CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE)) { 2029 int outerDepth = parser.getDepth(); 2030 PhoneAccountHandle accountHandle = null; 2031 String userSerialNumberString = null; 2032 String groupId = ""; 2033 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 2034 if (parser.getName().equals(ACCOUNT_HANDLE)) { 2035 parser.nextTag(); 2036 accountHandle = sPhoneAccountHandleXml.readFromXml(parser, version, 2037 context); 2038 } else if (parser.getName().equals(USER_SERIAL_NUMBER)) { 2039 parser.next(); 2040 userSerialNumberString = parser.getText(); 2041 } else if (parser.getName().equals(GROUP_ID)) { 2042 if (parser.next() == XmlPullParser.TEXT) { 2043 groupId = parser.getText(); 2044 } 2045 } 2046 } 2047 UserHandle userHandle = null; 2048 if (userSerialNumberString != null) { 2049 try { 2050 long serialNumber = Long.parseLong(userSerialNumberString); 2051 userHandle = UserManager.get(context) 2052 .getUserForSerialNumber(serialNumber); 2053 } catch (NumberFormatException e) { 2054 Log.e(this, e, 2055 "Could not parse UserHandle " + userSerialNumberString); 2056 } 2057 } 2058 if (accountHandle != null && userHandle != null && groupId != null) { 2059 return new DefaultPhoneAccountHandle(userHandle, accountHandle, 2060 groupId); 2061 } 2062 } 2063 return null; 2064 } 2065 }; 2066 2067 2068 @VisibleForTesting 2069 public static final XmlSerialization<PhoneAccount> sPhoneAccountXml = 2070 new XmlSerialization<PhoneAccount>() { 2071 private static final String CLASS_PHONE_ACCOUNT = "phone_account"; 2072 private static final String ACCOUNT_HANDLE = "account_handle"; 2073 private static final String ADDRESS = "handle"; 2074 private static final String SUBSCRIPTION_ADDRESS = "subscription_number"; 2075 private static final String CAPABILITIES = "capabilities"; 2076 private static final String SUPPORTED_AUDIO_ROUTES = "supported_audio_routes"; 2077 private static final String ICON_RES_ID = "icon_res_id"; 2078 private static final String ICON_PACKAGE_NAME = "icon_package_name"; 2079 private static final String ICON_BITMAP = "icon_bitmap"; 2080 private static final String ICON_TINT = "icon_tint"; 2081 private static final String HIGHLIGHT_COLOR = "highlight_color"; 2082 private static final String LABEL = "label"; 2083 private static final String SHORT_DESCRIPTION = "short_description"; 2084 private static final String SUPPORTED_URI_SCHEMES = "supported_uri_schemes"; 2085 private static final String ICON = "icon"; 2086 private static final String EXTRAS = "extras"; 2087 private static final String ENABLED = "enabled"; 2088 2089 @Override 2090 public void writeToXml(PhoneAccount o, XmlSerializer serializer, Context context) 2091 throws IOException { 2092 if (o != null) { 2093 serializer.startTag(null, CLASS_PHONE_ACCOUNT); 2094 2095 if (o.getAccountHandle() != null) { 2096 serializer.startTag(null, ACCOUNT_HANDLE); 2097 sPhoneAccountHandleXml.writeToXml(o.getAccountHandle(), serializer, context); 2098 serializer.endTag(null, ACCOUNT_HANDLE); 2099 } 2100 2101 writeTextIfNonNull(ADDRESS, o.getAddress(), serializer); 2102 writeTextIfNonNull(SUBSCRIPTION_ADDRESS, o.getSubscriptionAddress(), serializer); 2103 writeTextIfNonNull(CAPABILITIES, Integer.toString(o.getCapabilities()), serializer); 2104 writeIconIfNonNull(ICON, o.getIcon(), serializer); 2105 writeTextIfNonNull(HIGHLIGHT_COLOR, 2106 Integer.toString(o.getHighlightColor()), serializer); 2107 writeTextIfNonNull(LABEL, o.getLabel(), serializer); 2108 writeTextIfNonNull(SHORT_DESCRIPTION, o.getShortDescription(), serializer); 2109 writeStringList(SUPPORTED_URI_SCHEMES, o.getSupportedUriSchemes(), serializer); 2110 writeBundle(EXTRAS, o.getExtras(), serializer); 2111 writeTextIfNonNull(ENABLED, o.isEnabled() ? "true" : "false" , serializer); 2112 writeTextIfNonNull(SUPPORTED_AUDIO_ROUTES, Integer.toString( 2113 o.getSupportedAudioRoutes()), serializer); 2114 2115 serializer.endTag(null, CLASS_PHONE_ACCOUNT); 2116 } 2117 } 2118 2119 public PhoneAccount readFromXml(XmlPullParser parser, int version, Context context) 2120 throws IOException, XmlPullParserException { 2121 if (parser.getName().equals(CLASS_PHONE_ACCOUNT)) { 2122 int outerDepth = parser.getDepth(); 2123 PhoneAccountHandle accountHandle = null; 2124 Uri address = null; 2125 Uri subscriptionAddress = null; 2126 int capabilities = 0; 2127 int supportedAudioRoutes = 0; 2128 int iconResId = PhoneAccount.NO_RESOURCE_ID; 2129 String iconPackageName = null; 2130 Bitmap iconBitmap = null; 2131 int iconTint = PhoneAccount.NO_ICON_TINT; 2132 int highlightColor = PhoneAccount.NO_HIGHLIGHT_COLOR; 2133 String label = null; 2134 String shortDescription = null; 2135 List<String> supportedUriSchemes = null; 2136 Icon icon = null; 2137 boolean enabled = false; 2138 Bundle extras = null; 2139 2140 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 2141 if (parser.getName().equals(ACCOUNT_HANDLE)) { 2142 parser.nextTag(); 2143 accountHandle = sPhoneAccountHandleXml.readFromXml(parser, version, 2144 context); 2145 } else if (parser.getName().equals(ADDRESS)) { 2146 parser.next(); 2147 address = Uri.parse(parser.getText()); 2148 } else if (parser.getName().equals(SUBSCRIPTION_ADDRESS)) { 2149 parser.next(); 2150 String nextText = parser.getText(); 2151 subscriptionAddress = nextText == null ? null : Uri.parse(nextText); 2152 } else if (parser.getName().equals(CAPABILITIES)) { 2153 parser.next(); 2154 capabilities = Integer.parseInt(parser.getText()); 2155 } else if (parser.getName().equals(ICON_RES_ID)) { 2156 parser.next(); 2157 iconResId = Integer.parseInt(parser.getText()); 2158 } else if (parser.getName().equals(ICON_PACKAGE_NAME)) { 2159 parser.next(); 2160 iconPackageName = parser.getText(); 2161 } else if (parser.getName().equals(ICON_BITMAP)) { 2162 parser.next(); 2163 iconBitmap = readBitmap(parser); 2164 } else if (parser.getName().equals(ICON_TINT)) { 2165 parser.next(); 2166 iconTint = Integer.parseInt(parser.getText()); 2167 } else if (parser.getName().equals(HIGHLIGHT_COLOR)) { 2168 parser.next(); 2169 highlightColor = Integer.parseInt(parser.getText()); 2170 } else if (parser.getName().equals(LABEL)) { 2171 parser.next(); 2172 label = parser.getText(); 2173 } else if (parser.getName().equals(SHORT_DESCRIPTION)) { 2174 parser.next(); 2175 shortDescription = parser.getText(); 2176 } else if (parser.getName().equals(SUPPORTED_URI_SCHEMES)) { 2177 supportedUriSchemes = readStringList(parser); 2178 } else if (parser.getName().equals(ICON)) { 2179 parser.next(); 2180 icon = readIcon(parser); 2181 } else if (parser.getName().equals(ENABLED)) { 2182 parser.next(); 2183 enabled = "true".equalsIgnoreCase(parser.getText()); 2184 } else if (parser.getName().equals(EXTRAS)) { 2185 extras = readBundle(parser); 2186 } else if (parser.getName().equals(SUPPORTED_AUDIO_ROUTES)) { 2187 parser.next(); 2188 supportedAudioRoutes = Integer.parseInt(parser.getText()); 2189 } 2190 } 2191 2192 ComponentName pstnComponentName = new ComponentName("com.android.phone", 2193 "com.android.services.telephony.TelephonyConnectionService"); 2194 ComponentName sipComponentName = new ComponentName("com.android.phone", 2195 "com.android.services.telephony.sip.SipConnectionService"); 2196 2197 // Upgrade older phone accounts to specify the supported URI schemes. 2198 if (version < 2) { 2199 supportedUriSchemes = new ArrayList<>(); 2200 2201 // Handle the SIP connection service. 2202 // Check the system settings to see if it also should handle "tel" calls. 2203 if (accountHandle.getComponentName().equals(sipComponentName)) { 2204 boolean useSipForPstn = useSipForPstnCalls(context); 2205 supportedUriSchemes.add(PhoneAccount.SCHEME_SIP); 2206 if (useSipForPstn) { 2207 supportedUriSchemes.add(PhoneAccount.SCHEME_TEL); 2208 } 2209 } else { 2210 supportedUriSchemes.add(PhoneAccount.SCHEME_TEL); 2211 supportedUriSchemes.add(PhoneAccount.SCHEME_VOICEMAIL); 2212 } 2213 } 2214 2215 // Upgrade older phone accounts with explicit package name 2216 if (version < 5) { 2217 if (iconBitmap == null) { 2218 iconPackageName = accountHandle.getComponentName().getPackageName(); 2219 } 2220 } 2221 2222 if (version < 6) { 2223 // Always enable all SIP accounts on upgrade to version 6 2224 if (accountHandle.getComponentName().equals(sipComponentName)) { 2225 enabled = true; 2226 } 2227 } 2228 if (version < 7) { 2229 // Always enabled all PSTN acocunts on upgrade to version 7 2230 if (accountHandle.getComponentName().equals(pstnComponentName)) { 2231 enabled = true; 2232 } 2233 } 2234 if (version < 8) { 2235 // Migrate the SIP account handle ids to use SIP username instead of SIP URI. 2236 if (accountHandle.getComponentName().equals(sipComponentName)) { 2237 Uri accountUri = Uri.parse(accountHandle.getId()); 2238 if (accountUri.getScheme() != null && 2239 accountUri.getScheme().equals(PhoneAccount.SCHEME_SIP)) { 2240 accountHandle = new PhoneAccountHandle(accountHandle.getComponentName(), 2241 accountUri.getSchemeSpecificPart(), 2242 accountHandle.getUserHandle()); 2243 } 2244 } 2245 } 2246 2247 if (version < 9) { 2248 // Set supported audio routes to all by default 2249 supportedAudioRoutes = CallAudioState.ROUTE_ALL; 2250 } 2251 2252 PhoneAccount.Builder builder = PhoneAccount.builder(accountHandle, label) 2253 .setAddress(address) 2254 .setSubscriptionAddress(subscriptionAddress) 2255 .setCapabilities(capabilities) 2256 .setSupportedAudioRoutes(supportedAudioRoutes) 2257 .setShortDescription(shortDescription) 2258 .setSupportedUriSchemes(supportedUriSchemes) 2259 .setHighlightColor(highlightColor) 2260 .setExtras(extras) 2261 .setIsEnabled(enabled); 2262 2263 if (icon != null) { 2264 builder.setIcon(icon); 2265 } else if (iconBitmap != null) { 2266 builder.setIcon(Icon.createWithBitmap(iconBitmap)); 2267 } else if (!TextUtils.isEmpty(iconPackageName)) { 2268 builder.setIcon(Icon.createWithResource(iconPackageName, iconResId)); 2269 // TODO: Need to set tint. 2270 } 2271 2272 return builder.build(); 2273 } 2274 return null; 2275 } 2276 2277 /** 2278 * Determines if the SIP call settings specify to use SIP for all calls, including PSTN 2279 * calls. 2280 * 2281 * @param context The context. 2282 * @return {@code True} if SIP should be used for all calls. 2283 */ 2284 private boolean useSipForPstnCalls(Context context) { 2285 String option = Settings.System.getStringForUser(context.getContentResolver(), 2286 Settings.System.SIP_CALL_OPTIONS, context.getUserId()); 2287 option = (option != null) ? option : Settings.System.SIP_ADDRESS_ONLY; 2288 return option.equals(Settings.System.SIP_ALWAYS); 2289 } 2290 }; 2291 2292 @VisibleForTesting 2293 public static final XmlSerialization<PhoneAccountHandle> sPhoneAccountHandleXml = 2294 new XmlSerialization<PhoneAccountHandle>() { 2295 private static final String CLASS_PHONE_ACCOUNT_HANDLE = "phone_account_handle"; 2296 private static final String COMPONENT_NAME = "component_name"; 2297 private static final String ID = "id"; 2298 private static final String USER_SERIAL_NUMBER = "user_serial_number"; 2299 2300 @Override 2301 public void writeToXml(PhoneAccountHandle o, XmlSerializer serializer, Context context) 2302 throws IOException { 2303 if (o != null) { 2304 serializer.startTag(null, CLASS_PHONE_ACCOUNT_HANDLE); 2305 2306 if (o.getComponentName() != null) { 2307 writeTextIfNonNull( 2308 COMPONENT_NAME, o.getComponentName().flattenToString(), serializer); 2309 } 2310 2311 writeTextIfNonNull(ID, o.getId(), serializer); 2312 2313 if (o.getUserHandle() != null && context != null) { 2314 UserManager userManager = UserManager.get(context); 2315 writeLong(USER_SERIAL_NUMBER, 2316 userManager.getSerialNumberForUser(o.getUserHandle()), serializer); 2317 } 2318 2319 serializer.endTag(null, CLASS_PHONE_ACCOUNT_HANDLE); 2320 } 2321 } 2322 2323 @Override 2324 public PhoneAccountHandle readFromXml(XmlPullParser parser, int version, Context context) 2325 throws IOException, XmlPullParserException { 2326 if (parser.getName().equals(CLASS_PHONE_ACCOUNT_HANDLE)) { 2327 String componentNameString = null; 2328 String idString = null; 2329 String userSerialNumberString = null; 2330 int outerDepth = parser.getDepth(); 2331 2332 UserManager userManager = UserManager.get(context); 2333 2334 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 2335 if (parser.getName().equals(COMPONENT_NAME)) { 2336 parser.next(); 2337 componentNameString = parser.getText(); 2338 } else if (parser.getName().equals(ID)) { 2339 parser.next(); 2340 idString = parser.getText(); 2341 } else if (parser.getName().equals(USER_SERIAL_NUMBER)) { 2342 parser.next(); 2343 userSerialNumberString = parser.getText(); 2344 } 2345 } 2346 if (componentNameString != null) { 2347 UserHandle userHandle = null; 2348 if (userSerialNumberString != null) { 2349 try { 2350 long serialNumber = Long.parseLong(userSerialNumberString); 2351 userHandle = userManager.getUserForSerialNumber(serialNumber); 2352 } catch (NumberFormatException e) { 2353 Log.e(this, e, "Could not parse UserHandle " + userSerialNumberString); 2354 } 2355 } 2356 return new PhoneAccountHandle( 2357 ComponentName.unflattenFromString(componentNameString), 2358 idString, 2359 userHandle); 2360 } 2361 } 2362 return null; 2363 } 2364 }; 2365 2366 private String nullToEmpty(String str) { 2367 return str == null ? "" : str; 2368 } 2369 } 2370