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