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