1176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon/*
2176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon * Copyright (C) 2014 The Android Open Source Project
3176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon *
4176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
5176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon * you may not use this file except in compliance with the License.
6176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon * You may obtain a copy of the License at
7176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon *
8176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
9176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon *
10176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon * Unless required by applicable law or agreed to in writing, software
11176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
12176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon * See the License for the specific language governing permissions and
14176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon * limitations under the License.
15176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon */
16176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom;
18176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
19cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunnimport android.Manifest;
20105d977687d1d0de7cd9420fc140b01404261df1Evan Charltonimport android.content.ComponentName;
21105d977687d1d0de7cd9420fc140b01404261df1Evan Charltonimport android.content.Context;
22af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport android.content.Intent;
23af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport android.content.pm.PackageManager;
24af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport android.content.pm.ResolveInfo;
25cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunnimport android.content.pm.ServiceInfo;
264a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Makimport android.content.pm.UserInfo;
27d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awadimport android.graphics.Bitmap;
28d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awadimport android.graphics.BitmapFactory;
299c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordonimport android.graphics.drawable.Icon;
30105d977687d1d0de7cd9420fc140b01404261df1Evan Charltonimport android.net.Uri;
31369c8740adecbb47a17171f861322a76588a6319Tyler Gunnimport android.os.Bundle;
323f7f64d6042f32bfda99b13d053bd49997a08306Hall Liuimport android.os.AsyncTask;
33aecfa9be525bd91902f975d7f7011ef2dd2d950cSailesh Nepalimport android.os.PersistableBundle;
34105d977687d1d0de7cd9420fc140b01404261df1Evan Charltonimport android.os.Process;
35105d977687d1d0de7cd9420fc140b01404261df1Evan Charltonimport android.os.UserHandle;
36105d977687d1d0de7cd9420fc140b01404261df1Evan Charltonimport android.os.UserManager;
378425357e131867f33587641f23a1d1a328acf139Tyler Gunnimport android.provider.Settings;
3896a0be67619944378d95cdedc64b004aadb341e2Christine Hallstromimport android.telecom.CallAudioState;
397cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.ConnectionService;
4059c21a747c31773a67a32675be29c4d0537a3513Santos Cordonimport android.telecom.DefaultDialerManager;
417cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccount;
427cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccountHandle;
43aecfa9be525bd91902f975d7f7011ef2dd2d950cSailesh Nepalimport android.telephony.CarrierConfigManager;
44140004a104402fde514f8a2182dc2d10a4f6917dNancy Chenimport android.telephony.PhoneNumberUtils;
455a36b6e9dcf9b5d5d065b6e1e705d67b94a388afNancy Chenimport android.telephony.SubscriptionManager;
46479b3025ef8be1a115468fd6c113afa24cca2790Santos Cordonimport android.telephony.TelephonyManager;
47af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport android.text.TextUtils;
48b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport android.util.AtomicFile;
49d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awadimport android.util.Base64;
50b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport android.util.Xml;
51b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
5291d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn// TODO: Needed for move to system service: import com.android.internal.R;
530e1dc5a99042dd05b94b16a41461a3632a3fe5eeSailesh Nepalimport com.android.internal.annotations.VisibleForTesting;
540e1dc5a99042dd05b94b16a41461a3632a3fe5eeSailesh Nepalimport com.android.internal.util.FastXmlSerializer;
559787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunnimport com.android.internal.util.IndentingPrintWriter;
560e1dc5a99042dd05b94b16a41461a3632a3fe5eeSailesh Nepalimport com.android.internal.util.XmlUtils;
570e1dc5a99042dd05b94b16a41461a3632a3fe5eeSailesh Nepal
58af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport org.xmlpull.v1.XmlPullParser;
59af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport org.xmlpull.v1.XmlPullParserException;
60af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport org.xmlpull.v1.XmlSerializer;
61af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton
62b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.BufferedInputStream;
639c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordonimport java.io.ByteArrayInputStream;
64d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awadimport java.io.ByteArrayOutputStream;
65b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.File;
66b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.FileNotFoundException;
67b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.FileOutputStream;
68b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.IOException;
69b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.InputStream;
708425357e131867f33587641f23a1d1a328acf139Tyler Gunnimport java.lang.Integer;
71cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunnimport java.lang.SecurityException;
72d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunnimport java.lang.String;
73176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordonimport java.util.ArrayList;
7491fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepalimport java.util.Collections;
75d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunnimport java.util.Iterator;
76176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordonimport java.util.List;
774a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Makimport java.util.Map;
78176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordonimport java.util.Objects;
790c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebingerimport java.util.Optional;
804a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Makimport java.util.concurrent.ConcurrentHashMap;
81b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.util.concurrent.CopyOnWriteArrayList;
820c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebingerimport java.util.stream.Collector;
830c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebingerimport java.util.stream.Collectors;
840c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebingerimport java.util.stream.Stream;
85176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
86176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon/**
8789176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton * Handles writing and reading PhoneAccountHandle registration entries. This is a simple verbatim
886a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * delegate for all the account handling methods on {@link android.telecom.TelecomManager} as
896a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * implemented in {@link TelecomServiceImpl}, with the notable exception that
906a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * {@link TelecomServiceImpl} is responsible for security checking to make sure that the caller has
916a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * proper authority over the {@code ComponentName}s they are declaring in their
926a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * {@code PhoneAccountHandle}s.
936a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon *
946a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon *
956a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon *  -- About Users and Phone Accounts --
966a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon *
979c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon * We store all phone accounts for all users in a single place, which means that there are three
989c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon * users that we have to deal with in code:
996a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * 1) The Android User that is currently active on the device.
1006a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * 2) The user which owns/registers the phone account.
1016a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * 3) The user running the app that is requesting the phone account information.
1026a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon *
1036a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * For example, I have a device with 2 users, primary (A) and secondary (B), and the secondary user
104240656f19c078b4f703d0502ce29114de0d45a50Tony Mak * has a work profile running as another user (B2). Each user/profile only have the visibility of
105240656f19c078b4f703d0502ce29114de0d45a50Tony Mak * phone accounts owned by them. Lets say, user B (settings) is requesting a list of phone accounts,
106240656f19c078b4f703d0502ce29114de0d45a50Tony Mak * and the list only contains phone accounts owned by user B and accounts with
107240656f19c078b4f703d0502ce29114de0d45a50Tony Mak * {@link PhoneAccount#CAPABILITY_MULTI_USER}.
1086a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon *
1096a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * In practice, (2) is stored with the phone account handle and is part of the handle's ID. (1) is
1106a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * saved in {@link #mCurrentUserHandle} and (3) we get from Binder.getCallingUser(). We check these
1116a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon * users for visibility before returning any phone accounts.
112176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon */
1135385513ae43b4d5896245bf076a83b27dbf32a25Brad Ebingerpublic class PhoneAccountRegistrar {
114176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
1155e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee    public static final PhoneAccountHandle NO_ACCOUNT_SELECTED =
1165e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee            new PhoneAccountHandle(new ComponentName("null", "null"), "NO_ACCOUNT_SELECTED");
1175e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee
118b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    public abstract static class Listener {
119b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        public void onAccountsChanged(PhoneAccountRegistrar registrar) {}
120b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        public void onDefaultOutgoingChanged(PhoneAccountRegistrar registrar) {}
121b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        public void onSimCallManagerChanged(PhoneAccountRegistrar registrar) {}
122b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    }
123b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
124b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    private static final String FILE_NAME = "phone-account-registrar-state.xml";
1258425357e131867f33587641f23a1d1a328acf139Tyler Gunn    @VisibleForTesting
1264a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak    public static final int EXPECTED_STATE_VERSION = 9;
1278425357e131867f33587641f23a1d1a328acf139Tyler Gunn
1288425357e131867f33587641f23a1d1a328acf139Tyler Gunn    /** Keep in sync with the same in SipSettings.java */
1298425357e131867f33587641f23a1d1a328acf139Tyler Gunn    private static final String SIP_SHARED_PREFERENCES = "SIP_PREFERENCES";
130b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
131b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    private final List<Listener> mListeners = new CopyOnWriteArrayList<>();
132b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    private final AtomicFile mAtomicFile;
133afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon    private final Context mContext;
134105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    private final UserManager mUserManager;
13533c05d3d8bf97bc8748d573858f2330c69902922Wink Saville    private final SubscriptionManager mSubscriptionManager;
136b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    private State mState;
137105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    private UserHandle mCurrentUserHandle;
1383f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu    private interface PhoneAccountRegistrarWriteLock {}
1393f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu    private final PhoneAccountRegistrarWriteLock mWriteLock =
1403f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            new PhoneAccountRegistrarWriteLock() {};
141176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
14206ce062a2ceb7ca73560edd6b2f85d0f16a17667Nancy Chen    @VisibleForTesting
1432692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad    public PhoneAccountRegistrar(Context context) {
144b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        this(context, FILE_NAME);
145b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    }
146b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
147b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    @VisibleForTesting
148b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    public PhoneAccountRegistrar(Context context, String fileName) {
14991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        // TODO: This file path is subject to change -- it is storing the phone account registry
15091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        // state file in the path /data/system/users/0/, which is likely not correct in a
15191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        // multi-user setting.
15291d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        /** UNCOMMENT_FOR_MOVE_TO_SYSTEM_SERVICE
15391d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        String filePath = Environment.getUserSystemDirectory(UserHandle.myUserId()).
15491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                getAbsolutePath();
15591d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        mAtomicFile = new AtomicFile(new File(filePath, fileName));
15691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn         UNCOMMENT_FOR_MOVE_TO_SYSTEM_SERVICE */
157b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        mAtomicFile = new AtomicFile(new File(context.getFilesDir(), fileName));
15891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn
159b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        mState = new State();
160afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon        mContext = context;
161105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        mUserManager = UserManager.get(context);
16233c05d3d8bf97bc8748d573858f2330c69902922Wink Saville        mSubscriptionManager = SubscriptionManager.from(mContext);
163105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        mCurrentUserHandle = Process.myUserHandle();
164b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        read();
165104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad    }
166176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
1678425357e131867f33587641f23a1d1a328acf139Tyler Gunn    /**
168140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen     * Retrieves the subscription id for a given phone account if it exists. Subscription ids
169140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen     * apply only to PSTN/SIM card phone accounts so all other accounts should not have a
170140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen     * subscription id.
171140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen     * @param accountHandle The handle for the phone account for which to retrieve the
172140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen     * subscription id.
173358506069eedd8840ff8a332362682f18e1668e7Wink Saville     * @return The value of the subscription id or -1 if it does not exist or is not valid.
174140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen     */
175358506069eedd8840ff8a332362682f18e1668e7Wink Saville    public int getSubscriptionIdForPhoneAccount(PhoneAccountHandle accountHandle) {
176240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        PhoneAccount account = getPhoneAccountUnchecked(accountHandle);
177479b3025ef8be1a115468fd6c113afa24cca2790Santos Cordon
1786a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        if (account != null && account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
179479b3025ef8be1a115468fd6c113afa24cca2790Santos Cordon            TelephonyManager tm =
180479b3025ef8be1a115468fd6c113afa24cca2790Santos Cordon                    (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
181479b3025ef8be1a115468fd6c113afa24cca2790Santos Cordon            return tm.getSubIdForPhoneAccount(account);
182140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen        }
183479b3025ef8be1a115468fd6c113afa24cca2790Santos Cordon        return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
184140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen    }
185140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen
186140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen    /**
187105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     * Retrieves the default outgoing phone account supporting the specified uriScheme. Note that if
188105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     * {@link #mCurrentUserHandle} does not have visibility into the current default, {@code null}
189105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     * will be returned.
190105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     *
1918425357e131867f33587641f23a1d1a328acf139Tyler Gunn     * @param uriScheme The URI scheme for the outgoing call.
1928425357e131867f33587641f23a1d1a328acf139Tyler Gunn     * @return The {@link PhoneAccountHandle} to use.
1938425357e131867f33587641f23a1d1a328acf139Tyler Gunn     */
194240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public PhoneAccountHandle getOutgoingPhoneAccountForScheme(String uriScheme,
195240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            UserHandle userHandle) {
196240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        final PhoneAccountHandle userSelected = getUserSelectedOutgoingPhoneAccount(userHandle);
1978425357e131867f33587641f23a1d1a328acf139Tyler Gunn
1985e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee        if (userSelected != null) {
1998425357e131867f33587641f23a1d1a328acf139Tyler Gunn            // If there is a default PhoneAccount, ensure it supports calls to handles with the
2008425357e131867f33587641f23a1d1a328acf139Tyler Gunn            // specified uriScheme.
201240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            final PhoneAccount userSelectedAccount = getPhoneAccountUnchecked(userSelected);
2026a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            if (userSelectedAccount.supportsUriScheme(uriScheme)) {
2038425357e131867f33587641f23a1d1a328acf139Tyler Gunn                return userSelected;
2048425357e131867f33587641f23a1d1a328acf139Tyler Gunn            }
205293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        }
206293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
207240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        List<PhoneAccountHandle> outgoing = getCallCapablePhoneAccounts(uriScheme, false,
208240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                userHandle);
2096fb37c87836b5245046bd3b14320823ab839a10cIhab Awad        switch (outgoing.size()) {
210293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad            case 0:
211293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad                // There are no accounts, so there can be no default
212293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad                return null;
213293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad            case 1:
214105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                // There is only one account, which is by definition the default.
2156a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                return outgoing.get(0);
216293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad            default:
217293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad                // There are multiple accounts with no selected default
218293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad                return null;
219f2a8491d71915c621518ac8a40bed3c2a35272a9Ihab Awad        }
220104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad    }
221104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
222240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public PhoneAccountHandle getOutgoingPhoneAccountForSchemeOfCurrentUser(String uriScheme) {
223240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        return getOutgoingPhoneAccountForScheme(uriScheme, mCurrentUserHandle);
224240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    }
225240656f19c078b4f703d0502ce29114de0d45a50Tony Mak
226105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    /**
227105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     * @return The user-selected outgoing {@link PhoneAccount}, or null if it hasn't been set (or
228105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     *      if it was set by another user).
229105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     */
230ecda55454f4993003e71e09a63d20f94a216cc47Hall Liu    @VisibleForTesting
231ecda55454f4993003e71e09a63d20f94a216cc47Hall Liu    public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount(UserHandle userHandle) {
2324a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        if (userHandle == null) {
2334a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            return null;
2344a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        }
2354a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        DefaultPhoneAccountHandle defaultPhoneAccountHandle = mState.defaultOutgoingAccountHandles
2364a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                .get(userHandle);
2374a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        if (defaultPhoneAccountHandle == null) {
2384a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            return null;
2394a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        }
2404a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        // Make sure the account is still registered and owned by the user.
2414a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        PhoneAccount account = getPhoneAccount(defaultPhoneAccountHandle.phoneAccountHandle,
2424a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                userHandle);
243ecda55454f4993003e71e09a63d20f94a216cc47Hall Liu
2446a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        if (account != null) {
2454a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            return defaultPhoneAccountHandle.phoneAccountHandle;
2465e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee        }
2475e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee        return null;
2485e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee    }
2495e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee
2506a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    /**
2510c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger     * @return The {@link DefaultPhoneAccountHandle} containing the user-selected default calling
2520c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger     * account and group Id for the {@link UserHandle} specified.
2530c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger     */
2540c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger    private DefaultPhoneAccountHandle getUserSelectedDefaultPhoneAccount(UserHandle userHandle) {
2550c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        if (userHandle == null) {
2560c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            return null;
2570c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        }
2580c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        DefaultPhoneAccountHandle defaultPhoneAccountHandle = mState.defaultOutgoingAccountHandles
2590c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                .get(userHandle);
2600c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        if (defaultPhoneAccountHandle == null) {
2610c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            return null;
2620c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        }
2630c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger
2640c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        return defaultPhoneAccountHandle;
2650c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger    }
2660c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger
2670c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger    /**
2680c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger     * @return The currently registered PhoneAccount in Telecom that has the same group Id.
2690c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger     */
2700c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger    private PhoneAccount getPhoneAccountByGroupId(String groupId, ComponentName groupComponentName,
2710c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            UserHandle userHandle, PhoneAccountHandle excludePhoneAccountHandle) {
2720c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        if (groupId == null || groupId.isEmpty() || userHandle == null) {
2730c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            return null;
2740c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        }
2750c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        // Get the PhoneAccount with the same group Id (and same ComponentName) that is not the
2760c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        // newAccount that was just added
2770c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        List<PhoneAccount> accounts = getAllPhoneAccounts(userHandle).stream()
2780c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                .filter(account -> groupId.equals(account.getGroupId()) &&
2790c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                        !account.getAccountHandle().equals(excludePhoneAccountHandle) &&
2800c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                        Objects.equals(account.getAccountHandle().getComponentName(),
2810c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                                groupComponentName))
2820c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                .collect(Collectors.toList());
2830c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        // There should be one or no PhoneAccounts with the same group Id
2840c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        if (accounts.size() > 1) {
2850c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            Log.w(this, "Found multiple PhoneAccounts registered to the same Group Id!");
2860c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        }
2870c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        return accounts.isEmpty() ? null : accounts.get(0);
2880c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger    }
2890c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger
2900c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger    /**
2916a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * Sets the phone account with which to place all calls by default. Set by the user
2926a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * within phone settings.
2936a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     */
2944a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak    public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle,
2954a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            UserHandle userHandle) {
2964a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        if (userHandle == null) {
2974a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            return;
2984a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        }
29989176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton        if (accountHandle == null) {
300104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad            // Asking to clear the default outgoing is a valid request
3014a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            mState.defaultOutgoingAccountHandles.remove(userHandle);
302104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        } else {
3034a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            PhoneAccount account = getPhoneAccount(accountHandle, userHandle);
3046a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            if (account == null) {
305b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                Log.w(this, "Trying to set nonexistent default outgoing %s",
306b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        accountHandle);
307b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                return;
308b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            }
309b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
3106a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            if (!account.hasCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)) {
311b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                Log.w(this, "Trying to set non-call-provider default outgoing %s",
31289176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton                        accountHandle);
313104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad                return;
314104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad            }
315104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
3166a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
3175a36b6e9dcf9b5d5d065b6e1e705d67b94a388afNancy Chen                // If the account selected is a SIM account, propagate down to the subscription
3185a36b6e9dcf9b5d5d065b6e1e705d67b94a388afNancy Chen                // record.
3197ce6e78563893ef8da687787bd96d9b7d4af1aceWink Saville                int subId = getSubscriptionIdForPhoneAccount(accountHandle);
32033c05d3d8bf97bc8748d573858f2330c69902922Wink Saville                mSubscriptionManager.setDefaultVoiceSubId(subId);
3215a36b6e9dcf9b5d5d065b6e1e705d67b94a388afNancy Chen            }
3225a36b6e9dcf9b5d5d065b6e1e705d67b94a388afNancy Chen
3234a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            mState.defaultOutgoingAccountHandles
3240c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                    .put(userHandle, new DefaultPhoneAccountHandle(userHandle, accountHandle,
3250c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                            account.getGroupId()));
326293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        }
327293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
328293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        write();
329b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        fireDefaultOutgoingChanged();
330293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    }
331293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
332668dee01ed4fb495c3711f6fd041a520b60a9a7fNancy Chen    boolean isUserSelectedSmsPhoneAccount(PhoneAccountHandle accountHandle) {
333ce68874475498dcb69a543559177d69ac6dae215Shishir Agrawal        return getSubscriptionIdForPhoneAccount(accountHandle) ==
334ce68874475498dcb69a543559177d69ac6dae215Shishir Agrawal                SubscriptionManager.getDefaultSmsSubscriptionId();
335fc43ea86697d3d052415cbb4feda7bd508563532Sailesh Nepal    }
336fc43ea86697d3d052415cbb4feda7bd508563532Sailesh Nepal
3378ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal    public ComponentName getSystemSimCallManagerComponent() {
3388ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal        String defaultSimCallManager = null;
3398ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal        CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(
3408ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal                Context.CARRIER_CONFIG_SERVICE);
3418ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal        PersistableBundle configBundle = configManager.getConfig();
3428ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal        if (configBundle != null) {
3438ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal            defaultSimCallManager = configBundle.getString(
3448ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal                    CarrierConfigManager.KEY_DEFAULT_SIM_CALL_MANAGER_STRING);
3458ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal        }
3468ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal        return TextUtils.isEmpty(defaultSimCallManager)
3478ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal            ?  null : ComponentName.unflattenFromString(defaultSimCallManager);
3488ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal    }
3498ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal
350240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public PhoneAccountHandle getSimCallManagerOfCurrentUser() {
351240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        return getSimCallManager(mCurrentUserHandle);
352240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    }
353240656f19c078b4f703d0502ce29114de0d45a50Tony Mak
354fc43ea86697d3d052415cbb4feda7bd508563532Sailesh Nepal    /**
355fc43ea86697d3d052415cbb4feda7bd508563532Sailesh Nepal     * Returns the {@link PhoneAccountHandle} corresponding to the currently active SIM Call
356fc43ea86697d3d052415cbb4feda7bd508563532Sailesh Nepal     * Manager. SIM Call Manager returned corresponds to the following priority order:
357fc43ea86697d3d052415cbb4feda7bd508563532Sailesh Nepal     * 1. If a SIM Call Manager {@link PhoneAccount} is registered for the same package as the
358fc43ea86697d3d052415cbb4feda7bd508563532Sailesh Nepal     * default dialer, then that one is returned.
359fc43ea86697d3d052415cbb4feda7bd508563532Sailesh Nepal     * 2. If there is a SIM Call Manager {@link PhoneAccount} registered which matches the
360fc43ea86697d3d052415cbb4feda7bd508563532Sailesh Nepal     * carrier configuration's default, then that one is returned.
361fc43ea86697d3d052415cbb4feda7bd508563532Sailesh Nepal     * 3. Otherwise, we return null.
362fc43ea86697d3d052415cbb4feda7bd508563532Sailesh Nepal     */
363240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public PhoneAccountHandle getSimCallManager(UserHandle userHandle) {
36459c21a747c31773a67a32675be29c4d0537a3513Santos Cordon        // Get the default dialer in case it has a connection manager associated with it.
365240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        String dialerPackage = DefaultDialerManager
366240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                .getDefaultDialerApplication(mContext, userHandle.getIdentifier());
367af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton
368aecfa9be525bd91902f975d7f7011ef2dd2d950cSailesh Nepal        // Check carrier config.
3698ed7eeb62df48943eae3caac3005beaefa53330cSailesh Nepal        ComponentName systemSimCallManagerComponent = getSystemSimCallManagerComponent();
37059c21a747c31773a67a32675be29c4d0537a3513Santos Cordon
37159c21a747c31773a67a32675be29c4d0537a3513Santos Cordon        PhoneAccountHandle dialerSimCallManager = null;
37259c21a747c31773a67a32675be29c4d0537a3513Santos Cordon        PhoneAccountHandle systemSimCallManager = null;
37359c21a747c31773a67a32675be29c4d0537a3513Santos Cordon
37459c21a747c31773a67a32675be29c4d0537a3513Santos Cordon        if (!TextUtils.isEmpty(dialerPackage) || systemSimCallManagerComponent != null) {
37559c21a747c31773a67a32675be29c4d0537a3513Santos Cordon            // loop through and look for any connection manager in the same package.
37659c21a747c31773a67a32675be29c4d0537a3513Santos Cordon            List<PhoneAccountHandle> allSimCallManagers = getPhoneAccountHandles(
37759c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                    PhoneAccount.CAPABILITY_CONNECTION_MANAGER, null, null,
378240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                    true /* includeDisabledAccounts */, userHandle);
37959c21a747c31773a67a32675be29c4d0537a3513Santos Cordon            for (PhoneAccountHandle accountHandle : allSimCallManagers) {
38059c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                ComponentName component = accountHandle.getComponentName();
38159c21a747c31773a67a32675be29c4d0537a3513Santos Cordon
38259c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                // Store the system connection manager if found
38359c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                if (systemSimCallManager == null
38459c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                        && Objects.equals(component, systemSimCallManagerComponent)
38559c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                        && !resolveComponent(accountHandle).isEmpty()) {
38659c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                    systemSimCallManager = accountHandle;
38759c21a747c31773a67a32675be29c4d0537a3513Santos Cordon
38859c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                // Store the dialer connection manager if found
38959c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                } else if (dialerSimCallManager == null
39059c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                        && Objects.equals(component.getPackageName(), dialerPackage)
39159c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                        && !resolveComponent(accountHandle).isEmpty()) {
39259c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                    dialerSimCallManager = accountHandle;
393af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton                }
394af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton            }
395af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton        }
396af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton
39759c21a747c31773a67a32675be29c4d0537a3513Santos Cordon        PhoneAccountHandle retval = dialerSimCallManager != null ?
39859c21a747c31773a67a32675be29c4d0537a3513Santos Cordon                dialerSimCallManager : systemSimCallManager;
39959c21a747c31773a67a32675be29c4d0537a3513Santos Cordon
40059c21a747c31773a67a32675be29c4d0537a3513Santos Cordon        Log.i(this, "SimCallManager queried, returning: %s", retval);
40159c21a747c31773a67a32675be29c4d0537a3513Santos Cordon
402b3ccd7e4ea41b733b46be5d15fb351faa3aa7645Sailesh Nepal        return retval;
403293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    }
404293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
405105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    /**
406240656f19c078b4f703d0502ce29114de0d45a50Tony Mak     * If it is a outgoing call, sim call manager of call-initiating user is returned.
407240656f19c078b4f703d0502ce29114de0d45a50Tony Mak     * Otherwise, we return the sim call manager of the user associated with the
408240656f19c078b4f703d0502ce29114de0d45a50Tony Mak     * target phone account.
409240656f19c078b4f703d0502ce29114de0d45a50Tony Mak     * @return phone account handle of sim call manager based on the ongoing call.
410240656f19c078b4f703d0502ce29114de0d45a50Tony Mak     */
411240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public PhoneAccountHandle getSimCallManagerFromCall(Call call) {
412240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        if (call == null) {
413240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            return null;
414240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        }
415240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        UserHandle userHandle = call.getInitiatingUser();
416240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        if (userHandle == null) {
417240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            userHandle = call.getTargetPhoneAccount().getUserHandle();
418240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        }
419240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        return getSimCallManager(userHandle);
420240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    }
421240656f19c078b4f703d0502ce29114de0d45a50Tony Mak
422240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    /**
423105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     * Update the current UserHandle to track when users are switched. This will allow the
424105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     * PhoneAccountRegistar to self-filter the PhoneAccounts to make sure we don't leak anything
425105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     * across users.
4266a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * We cannot simply check the calling user because that would always return the primary user for
4276a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * all invocations originating with the system process.
428105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     *
429105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     * @param userHandle The {@link UserHandle}, as delivered by
430105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     *          {@link Intent#ACTION_USER_SWITCHED}.
431105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     */
432105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    public void setCurrentUserHandle(UserHandle userHandle) {
433105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        if (userHandle == null) {
434105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            Log.d(this, "setCurrentUserHandle, userHandle = null");
435105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            userHandle = Process.myUserHandle();
436105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        }
437105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        Log.d(this, "setCurrentUserHandle, %s", userHandle);
438105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        mCurrentUserHandle = userHandle;
439105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    }
440105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
44171734c2db8a4e412d833b267777dd011e04cc942Yorke Lee    /**
44271734c2db8a4e412d833b267777dd011e04cc942Yorke Lee     * @return {@code true} if the phone account was successfully enabled/disabled, {@code false}
44371734c2db8a4e412d833b267777dd011e04cc942Yorke Lee     *         otherwise.
44471734c2db8a4e412d833b267777dd011e04cc942Yorke Lee     */
44571734c2db8a4e412d833b267777dd011e04cc942Yorke Lee    public boolean enablePhoneAccount(PhoneAccountHandle accountHandle, boolean isEnabled) {
44698e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        PhoneAccount account = getPhoneAccountUnchecked(accountHandle);
447638f05cb620a17ae7334486d2f53e223ac65eef5Santos Cordon        if (account == null) {
448638f05cb620a17ae7334486d2f53e223ac65eef5Santos Cordon            Log.w(this, "Could not find account to enable: " + accountHandle);
44971734c2db8a4e412d833b267777dd011e04cc942Yorke Lee            return false;
450638f05cb620a17ae7334486d2f53e223ac65eef5Santos Cordon        } else if (account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
451ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            // We never change the enabled state of SIM-based accounts.
452638f05cb620a17ae7334486d2f53e223ac65eef5Santos Cordon            Log.w(this, "Could not change enable state of SIM account: " + accountHandle);
45371734c2db8a4e412d833b267777dd011e04cc942Yorke Lee            return false;
454ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        }
455ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon
456638f05cb620a17ae7334486d2f53e223ac65eef5Santos Cordon        if (account.isEnabled() != isEnabled) {
457ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            account.setIsEnabled(isEnabled);
458483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak            if (!isEnabled) {
459483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak                // If the disabled account is the default, remove it.
460483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak                removeDefaultPhoneAccountHandle(accountHandle);
461483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak            }
462ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            write();
463ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            fireAccountsChanged();
464ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        }
46571734c2db8a4e412d833b267777dd011e04cc942Yorke Lee        return true;
466ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon    }
467ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon
468483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak    private void removeDefaultPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
469483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak        Iterator<Map.Entry<UserHandle, DefaultPhoneAccountHandle>> iterator =
470483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak                mState.defaultOutgoingAccountHandles.entrySet().iterator();
471483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak        while (iterator.hasNext()) {
472483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak            Map.Entry<UserHandle, DefaultPhoneAccountHandle> entry = iterator.next();
473483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak            if (phoneAccountHandle.equals(entry.getValue().phoneAccountHandle)) {
474483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak                iterator.remove();
475483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak            }
476483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak        }
477483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak    }
478483671620a809b5fc00bde3b694bdffb0fb72437Tony Mak
479240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    private boolean isVisibleForUser(PhoneAccount account, UserHandle userHandle,
480240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            boolean acrossProfiles) {
481105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        if (account == null) {
482105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            return false;
483105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        }
484105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
485240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        if (userHandle == null) {
486240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            Log.w(this, "userHandle is null in isVisibleForUser");
487240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            return false;
488240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        }
489240656f19c078b4f703d0502ce29114de0d45a50Tony Mak
490105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        // If this PhoneAccount has CAPABILITY_MULTI_USER, it should be visible to all users and
491105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        // all profiles. Only Telephony and SIP accounts should have this capability.
492105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        if (account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
493105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            return true;
494105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        }
495105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
496105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        UserHandle phoneAccountUserHandle = account.getAccountHandle().getUserHandle();
497105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        if (phoneAccountUserHandle == null) {
498105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            return false;
499105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        }
500105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
501105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        if (mCurrentUserHandle == null) {
502240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            // In case we need to have emergency phone calls from the lock screen.
503105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            Log.d(this, "Current user is null; assuming true");
504105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            return true;
505105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        }
506105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
507240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        if (acrossProfiles) {
508240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            return UserManager.get(mContext).isSameProfileGroup(userHandle.getIdentifier(),
509240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                    phoneAccountUserHandle.getIdentifier());
510240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        } else {
511240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            return phoneAccountUserHandle.equals(userHandle);
51291fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal        }
513105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    }
514105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
515105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    private List<ResolveInfo> resolveComponent(PhoneAccountHandle phoneAccountHandle) {
516105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        return resolveComponent(phoneAccountHandle.getComponentName(),
517240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                phoneAccountHandle.getUserHandle());
518105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    }
519105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
520105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    private List<ResolveInfo> resolveComponent(ComponentName componentName,
521105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            UserHandle userHandle) {
52210a5831cf61b3ab3b126329044ea05dc3181fa63mike dooley        PackageManager pm = mContext.getPackageManager();
52310a5831cf61b3ab3b126329044ea05dc3181fa63mike dooley        Intent intent = new Intent(ConnectionService.SERVICE_INTERFACE);
52410a5831cf61b3ab3b126329044ea05dc3181fa63mike dooley        intent.setComponent(componentName);
52591fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal        try {
52691fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal            if (userHandle != null) {
52791fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal                return pm.queryIntentServicesAsUser(intent, 0, userHandle.getIdentifier());
52891fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal            } else {
52991fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal                return pm.queryIntentServices(intent, 0);
53091fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal            }
53191fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal        } catch (SecurityException e) {
5323188b364c360f83631fe1c7623c0e4252088b3c6Santos Cordon            Log.e(this, e, "%s is not visible for the calling user", componentName);
53391fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal            return Collections.EMPTY_LIST;
534105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        }
53510a5831cf61b3ab3b126329044ea05dc3181fa63mike dooley    }
53610a5831cf61b3ab3b126329044ea05dc3181fa63mike dooley
5378e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn    /**
5388e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     * Retrieves a list of all {@link PhoneAccountHandle}s registered.
539ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon     * Only returns accounts which are enabled.
5408e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     *
5418e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     * @return The list of {@link PhoneAccountHandle}s.
5428e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     */
543240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public List<PhoneAccountHandle> getAllPhoneAccountHandles(UserHandle userHandle) {
544240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        return getPhoneAccountHandles(0, null, null, false, userHandle);
545240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    }
546240656f19c078b4f703d0502ce29114de0d45a50Tony Mak
547240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public List<PhoneAccount> getAllPhoneAccounts(UserHandle userHandle) {
548240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        return getPhoneAccounts(0, null, null, false, userHandle);
549293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    }
550104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
551240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public List<PhoneAccount> getAllPhoneAccountsOfCurrentUser() {
552240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        return getAllPhoneAccounts(mCurrentUserHandle);
553afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon    }
554afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon
5558e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn    /**
556309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen     * Retrieves a list of all phone account call provider phone accounts supporting the
5578e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     * specified URI scheme.
5588e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     *
5598e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     * @param uriScheme The URI scheme.
5608e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     * @return The phone account handles.
5618e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     */
562ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon    public List<PhoneAccountHandle> getCallCapablePhoneAccounts(
563240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            String uriScheme, boolean includeDisabledAccounts, UserHandle userHandle) {
564ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        return getPhoneAccountHandles(
565a0bb705db62a254741629942e29c61da663449ffBryce Lee                PhoneAccount.CAPABILITY_CALL_PROVIDER,
566a0bb705db62a254741629942e29c61da663449ffBryce Lee                PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY /*excludedCapabilities*/,
567240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                uriScheme, null, includeDisabledAccounts, userHandle);
568240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    }
569240656f19c078b4f703d0502ce29114de0d45a50Tony Mak
570240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public List<PhoneAccountHandle> getCallCapablePhoneAccountsOfCurrentUser(
571240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            String uriScheme, boolean includeDisabledAccounts) {
572240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        return getCallCapablePhoneAccounts(uriScheme, includeDisabledAccounts, mCurrentUserHandle);
5736a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    }
5746a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon
5756a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    /**
5766a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * Retrieves a list of all the SIM-based phone accounts.
5776a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     */
578240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public List<PhoneAccountHandle> getSimPhoneAccounts(UserHandle userHandle) {
5796a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        return getPhoneAccountHandles(
5806a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                PhoneAccount.CAPABILITY_CALL_PROVIDER | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION,
581240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                null, null, false, userHandle);
5828425357e131867f33587641f23a1d1a328acf139Tyler Gunn    }
5838425357e131867f33587641f23a1d1a328acf139Tyler Gunn
584240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public List<PhoneAccountHandle> getSimPhoneAccountsOfCurrentUser() {
585240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        return getSimPhoneAccounts(mCurrentUserHandle);
586240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    }
587240656f19c078b4f703d0502ce29114de0d45a50Tony Mak
588240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        /**
589240656f19c078b4f703d0502ce29114de0d45a50Tony Mak         * Retrieves a list of all phone accounts registered by a specified package.
590240656f19c078b4f703d0502ce29114de0d45a50Tony Mak         *
591240656f19c078b4f703d0502ce29114de0d45a50Tony Mak         * @param packageName The name of the package that registered the phone accounts.
592240656f19c078b4f703d0502ce29114de0d45a50Tony Mak         * @return The phone account handles.
593240656f19c078b4f703d0502ce29114de0d45a50Tony Mak         */
594240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName,
595240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            UserHandle userHandle) {
596240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        return getPhoneAccountHandles(0, null, packageName, false, userHandle);
5971c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen    }
5981c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen
599104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad    // TODO: Should we implement an artificial limit for # of accounts associated with a single
600104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad    // ComponentName?
601293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    public void registerPhoneAccount(PhoneAccount account) {
602cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn        // Enforce the requirement that a connection service for a phone account has the correct
603cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn        // permission.
6046a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        if (!phoneAccountRequiresBindPermission(account.getAccountHandle())) {
6057bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee            Log.w(this,
6067bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                    "Phone account %s does not have BIND_TELECOM_CONNECTION_SERVICE permission.",
607cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn                    account.getAccountHandle());
6087bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee            throw new SecurityException("PhoneAccount connection service requires "
6097bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                    + "BIND_TELECOM_CONNECTION_SERVICE permission.");
610cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn        }
611cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn
6128e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn        addOrReplacePhoneAccount(account);
6138e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn    }
6148e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn
6158e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn    /**
6168e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     * Adds a {@code PhoneAccount}, replacing an existing one if found.
6178e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     *
6188e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     * @param account The {@code PhoneAccount} to add or replace.
6198e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn     */
6208e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn    private void addOrReplacePhoneAccount(PhoneAccount account) {
6217e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad        Log.d(this, "addOrReplacePhoneAccount(%s -> %s)",
6227e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                account.getAccountHandle(), account);
6237e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad
624ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        // Start _enabled_ property as false.
625ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        // !!! IMPORTANT !!! It is important that we do not read the enabled state that the
626ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        // source app provides or else an third party app could enable itself.
627ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        boolean isEnabled = false;
628ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon
62998e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        PhoneAccount oldAccount = getPhoneAccountUnchecked(account.getAccountHandle());
6306a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        if (oldAccount != null) {
6316a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            mState.accounts.remove(oldAccount);
632ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            isEnabled = oldAccount.isEnabled();
6335fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon            Log.i(this, getAccountDiffString(account, oldAccount));
6345fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        } else {
6355fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon            Log.i(this, "New phone account registered: " + account);
636176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon        }
637ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon
6386a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        mState.accounts.add(account);
6390c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        // Set defaults and replace based on the group Id.
6400c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        maybeReplaceOldAccount(account);
641ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        // Reset enabled state to whatever the value was if the account was already registered,
642ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        // or _true_ if this is a SIM-based account.  All SIM-based accounts are always enabled.
643ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        account.setIsEnabled(
644ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon                isEnabled || account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION));
645176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
646293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        write();
647b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        fireAccountsChanged();
648176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon    }
649176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
650293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
65198e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        PhoneAccount account = getPhoneAccountUnchecked(accountHandle);
6526a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        if (account != null) {
6536a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            if (mState.accounts.remove(account)) {
6546a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                write();
6556a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                fireAccountsChanged();
656176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon            }
657176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon        }
658176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon    }
659176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
660d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn    /**
661d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn     * Un-registers all phone accounts associated with a specified package.
662d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn     *
663d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn     * @param packageName The package for which phone accounts will be removed.
664105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     * @param userHandle The {@link UserHandle} the package is running under.
665d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn     */
666105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    public void clearAccounts(String packageName, UserHandle userHandle) {
667d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn        boolean accountsRemoved = false;
668d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn        Iterator<PhoneAccount> it = mState.accounts.iterator();
669d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn        while (it.hasNext()) {
670d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn            PhoneAccount phoneAccount = it.next();
671105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            PhoneAccountHandle handle = phoneAccount.getAccountHandle();
672105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            if (Objects.equals(packageName, handle.getComponentName().getPackageName())
673105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                    && Objects.equals(userHandle, handle.getUserHandle())) {
674d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn                Log.i(this, "Removing phone account " + phoneAccount.getLabel());
6758f89f8d2a01385ca2972d2254b1b8c653e1bbe30Shriram Ganesh                mState.accounts.remove(phoneAccount);
676d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn                accountsRemoved = true;
677176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon            }
678176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon        }
679176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
680d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn        if (accountsRemoved) {
681d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn            write();
682d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn            fireAccountsChanged();
683d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn        }
684b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    }
685b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
686140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen    public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number) {
687358506069eedd8840ff8a332362682f18e1668e7Wink Saville        int subId = getSubscriptionIdForPhoneAccount(accountHandle);
688b195723690b08ec025690b40497813ecc1b459bfYorke Lee        return PhoneNumberUtils.isVoiceMailNumber(mContext, subId, number);
689140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen    }
690140004a104402fde514f8a2182dc2d10a4f6917dNancy Chen
691b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    public void addListener(Listener l) {
692b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        mListeners.add(l);
693b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    }
694b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
695b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    public void removeListener(Listener l) {
696a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner        if (l != null) {
697a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner            mListeners.remove(l);
698a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner        }
699b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    }
700b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
701b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    private void fireAccountsChanged() {
702b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        for (Listener l : mListeners) {
703b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            l.onAccountsChanged(this);
704b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        }
705b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    }
706b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
707b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    private void fireDefaultOutgoingChanged() {
708b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        for (Listener l : mListeners) {
709b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            l.onDefaultOutgoingChanged(this);
710b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        }
711b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    }
712b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
7135fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon    private String getAccountDiffString(PhoneAccount account1, PhoneAccount account2) {
7145fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        if (account1 == null || account2 == null) {
7155fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon            return "Diff: " + account1 + ", " + account2;
7165fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        }
7175fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon
7185fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        StringBuffer sb = new StringBuffer();
7195fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        sb.append("[").append(account1.getAccountHandle());
7207c64a4ee56436c6e3d2492f6c1d1076e10c862eeAnthony Lee        appendDiff(sb, "addr", Log.piiHandle(account1.getAddress()),
7217c64a4ee56436c6e3d2492f6c1d1076e10c862eeAnthony Lee                Log.piiHandle(account2.getAddress()));
7225fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        appendDiff(sb, "cap", account1.getCapabilities(), account2.getCapabilities());
7235fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        appendDiff(sb, "hl", account1.getHighlightColor(), account2.getHighlightColor());
7245fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        appendDiff(sb, "icon", account1.getIcon(), account2.getIcon());
7255fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        appendDiff(sb, "lbl", account1.getLabel(), account2.getLabel());
7265fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        appendDiff(sb, "desc", account1.getShortDescription(), account2.getShortDescription());
7277c64a4ee56436c6e3d2492f6c1d1076e10c862eeAnthony Lee        appendDiff(sb, "subAddr", Log.piiHandle(account1.getSubscriptionAddress()),
7287c64a4ee56436c6e3d2492f6c1d1076e10c862eeAnthony Lee                Log.piiHandle(account2.getSubscriptionAddress()));
7295fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        appendDiff(sb, "uris", account1.getSupportedUriSchemes(),
7305fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon                account2.getSupportedUriSchemes());
7315fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        sb.append("]");
7325fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        return sb.toString();
7335fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon    }
7345fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon
7355fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon    private void appendDiff(StringBuffer sb, String attrName, Object obj1, Object obj2) {
7365fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        if (!Objects.equals(obj1, obj2)) {
7375fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon            sb.append("(")
7385fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon                .append(attrName)
7395fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon                .append(": ")
7405fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon                .append(obj1)
7415fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon                .append(" -> ")
7425fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon                .append(obj2)
7435fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon                .append(")");
7445fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon        }
7455fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon    }
7465fa4e4f1eb98f052cc0ee4b3ad0f6acb8e92c719Santos Cordon
7470c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger    private void maybeReplaceOldAccount(PhoneAccount newAccount) {
7480c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        UserHandle newAccountUserHandle = newAccount.getAccountHandle().getUserHandle();
7490c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        DefaultPhoneAccountHandle defaultHandle =
7500c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                getUserSelectedDefaultPhoneAccount(newAccountUserHandle);
7510c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        if (defaultHandle == null || defaultHandle.groupId.isEmpty()) {
7520c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            Log.v(this, "maybeReplaceOldAccount: Not replacing PhoneAccount, no group Id or " +
7530c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                    "default.");
7540c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            return;
7550c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        }
7560c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        if (!defaultHandle.groupId.equals(newAccount.getGroupId())) {
7570c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            Log.v(this, "maybeReplaceOldAccount: group Ids are not equal.");
7580c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            return;
7590c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        }
7600c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        if (Objects.equals(newAccount.getAccountHandle().getComponentName(),
7610c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                defaultHandle.phoneAccountHandle.getComponentName())) {
7620c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            // Move default calling account over to new user, since the ComponentNames and Group Ids
7630c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            // are the same.
7640c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            setUserSelectedOutgoingPhoneAccount(newAccount.getAccountHandle(),
7650c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                    newAccountUserHandle);
7660c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        } else {
7670c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            Log.v(this, "maybeReplaceOldAccount: group Ids are equal, but ComponentName is not" +
7680c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                    " the same as the default. Not replacing default PhoneAccount.");
7690c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        }
7700c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        PhoneAccount replacementAccount = getPhoneAccountByGroupId(newAccount.getGroupId(),
7710c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                newAccount.getAccountHandle().getComponentName(), newAccountUserHandle,
7720c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                newAccount.getAccountHandle());
7730c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        if (replacementAccount != null) {
7740c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            // Unregister the old PhoneAccount.
7750c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            Log.v(this, "maybeReplaceOldAccount: Unregistering old PhoneAccount: " +
7760c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                    replacementAccount.getAccountHandle());
7770c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            unregisterPhoneAccount(replacementAccount.getAccountHandle());
7780c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        }
7790c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger    }
7800c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger
781cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn    /**
7826a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * Determines if the connection service specified by a {@link PhoneAccountHandle} requires the
7837bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee     * {@link Manifest.permission#BIND_TELECOM_CONNECTION_SERVICE} permission.
784cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn     *
785cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn     * @param phoneAccountHandle The phone account to check.
786cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn     * @return {@code True} if the phone account has permission.
787cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn     */
7886a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    public boolean phoneAccountRequiresBindPermission(PhoneAccountHandle phoneAccountHandle) {
78991fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal        List<ResolveInfo> resolveInfos = resolveComponent(phoneAccountHandle);
79091fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal        if (resolveInfos.isEmpty()) {
79191fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal            Log.w(this, "phoneAccount %s not found", phoneAccountHandle.getComponentName());
792cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn            return false;
793cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn        }
79491fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal        for (ResolveInfo resolveInfo : resolveInfos) {
79591fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal            ServiceInfo serviceInfo = resolveInfo.serviceInfo;
7967bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee            if (serviceInfo == null) {
7977bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                return false;
7987bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee            }
7997bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee
8007bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee            if (!Manifest.permission.BIND_CONNECTION_SERVICE.equals(serviceInfo.permission) &&
8017bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                    !Manifest.permission.BIND_TELECOM_CONNECTION_SERVICE.equals(
8027bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                            serviceInfo.permission)) {
8037bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                // The ConnectionService must require either the deprecated BIND_CONNECTION_SERVICE,
8047bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                // or the public BIND_TELECOM_CONNECTION_SERVICE permissions, both of which are
8057bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee                // system/signature only.
80691fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal                return false;
80791fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal            }
80891fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal        }
80991fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal        return true;
810cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn    }
811cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn
8126a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    //
8136a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    // Methods for retrieving PhoneAccounts and PhoneAccountHandles
8146a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    //
815293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
816afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon    /**
8176a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * Returns the PhoneAccount for the specified handle.  Does no user checking.
8188425357e131867f33587641f23a1d1a328acf139Tyler Gunn     *
8196a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * @param handle
8206a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * @return The corresponding phone account if one exists.
821afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon     */
82298e6bdc795585b0d332a7eb86245926c8d80609aTony Mak    public PhoneAccount getPhoneAccountUnchecked(PhoneAccountHandle handle) {
8236a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        for (PhoneAccount m : mState.accounts) {
8246a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            if (Objects.equals(handle, m.getAccountHandle())) {
8256a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                return m;
8266a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            }
8276a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        }
8286a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        return null;
8296a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    }
8306a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon
8316a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    /**
8326a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * Like getPhoneAccount, but checks to see if the current user is allowed to see the phone
8336a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * account before returning it. The current user is the active user on the actual android
8346a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * device.
8356a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     */
836240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public PhoneAccount getPhoneAccount(PhoneAccountHandle handle, UserHandle userHandle) {
837240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        return getPhoneAccount(handle, userHandle, /* acrossProfiles */ false);
838240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    }
839240656f19c078b4f703d0502ce29114de0d45a50Tony Mak
840240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public PhoneAccount getPhoneAccount(PhoneAccountHandle handle,
841240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            UserHandle userHandle, boolean acrossProfiles) {
84298e6bdc795585b0d332a7eb86245926c8d80609aTony Mak        PhoneAccount account = getPhoneAccountUnchecked(handle);
843240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        if (account != null && (isVisibleForUser(account, userHandle, acrossProfiles))) {
8446a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            return account;
8456a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        }
8466a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        return null;
8476a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    }
8486a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon
849240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    public PhoneAccount getPhoneAccountOfCurrentUser(PhoneAccountHandle handle) {
850240656f19c078b4f703d0502ce29114de0d45a50Tony Mak        return getPhoneAccount(handle, mCurrentUserHandle);
851240656f19c078b4f703d0502ce29114de0d45a50Tony Mak    }
852240656f19c078b4f703d0502ce29114de0d45a50Tony Mak
853a0bb705db62a254741629942e29c61da663449ffBryce Lee    private List<PhoneAccountHandle> getPhoneAccountHandles(
854a0bb705db62a254741629942e29c61da663449ffBryce Lee            int capabilities,
855a0bb705db62a254741629942e29c61da663449ffBryce Lee            String uriScheme,
856a0bb705db62a254741629942e29c61da663449ffBryce Lee            String packageName,
857240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            boolean includeDisabledAccounts,
858240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            UserHandle userHandle) {
859a0bb705db62a254741629942e29c61da663449ffBryce Lee        return getPhoneAccountHandles(capabilities, 0 /*excludedCapabilities*/, uriScheme,
860240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                packageName, includeDisabledAccounts, userHandle);
861a0bb705db62a254741629942e29c61da663449ffBryce Lee    }
862a0bb705db62a254741629942e29c61da663449ffBryce Lee
8636a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    /**
8646a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * Returns a list of phone account handles with the specified capabilities, uri scheme,
8656a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * and package name.
8666a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     */
8676a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    private List<PhoneAccountHandle> getPhoneAccountHandles(
868ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            int capabilities,
869a0bb705db62a254741629942e29c61da663449ffBryce Lee            int excludedCapabilities,
870ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            String uriScheme,
871ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            String packageName,
872240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            boolean includeDisabledAccounts,
873240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            UserHandle userHandle) {
8746a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        List<PhoneAccountHandle> handles = new ArrayList<>();
875ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon
876ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        for (PhoneAccount account : getPhoneAccounts(
877a0bb705db62a254741629942e29c61da663449ffBryce Lee                capabilities, excludedCapabilities, uriScheme, packageName,
878240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                includeDisabledAccounts, userHandle)) {
8796a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            handles.add(account.getAccountHandle());
8806a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        }
8816a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        return handles;
8828425357e131867f33587641f23a1d1a328acf139Tyler Gunn    }
8838425357e131867f33587641f23a1d1a328acf139Tyler Gunn
884a0bb705db62a254741629942e29c61da663449ffBryce Lee    private List<PhoneAccount> getPhoneAccounts(
885a0bb705db62a254741629942e29c61da663449ffBryce Lee            int capabilities,
886a0bb705db62a254741629942e29c61da663449ffBryce Lee            String uriScheme,
887a0bb705db62a254741629942e29c61da663449ffBryce Lee            String packageName,
888240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            boolean includeDisabledAccounts,
889240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            UserHandle userHandle) {
890a0bb705db62a254741629942e29c61da663449ffBryce Lee        return getPhoneAccounts(capabilities, 0 /*excludedCapabilities*/, uriScheme, packageName,
891240656f19c078b4f703d0502ce29114de0d45a50Tony Mak                includeDisabledAccounts, userHandle);
892a0bb705db62a254741629942e29c61da663449ffBryce Lee    }
893a0bb705db62a254741629942e29c61da663449ffBryce Lee
8948425357e131867f33587641f23a1d1a328acf139Tyler Gunn    /**
8958425357e131867f33587641f23a1d1a328acf139Tyler Gunn     * Returns a list of phone account handles with the specified flag, supporting the specified
8966a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * URI scheme, within the specified package name.
8978425357e131867f33587641f23a1d1a328acf139Tyler Gunn     *
8986a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * @param capabilities Capabilities which the {@code PhoneAccount} must have. Ignored if 0.
899a0bb705db62a254741629942e29c61da663449ffBryce Lee     * @param excludedCapabilities Capabilities which the {@code PhoneAccount} must not have.
900a0bb705db62a254741629942e29c61da663449ffBryce Lee     *                             Ignored if 0.
9016a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * @param uriScheme URI schemes the PhoneAccount must handle.  {@code null} bypasses the
9028425357e131867f33587641f23a1d1a328acf139Tyler Gunn     *                  URI scheme check.
9036a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon     * @param packageName Package name of the PhoneAccount. {@code null} bypasses packageName check.
9048425357e131867f33587641f23a1d1a328acf139Tyler Gunn     */
9056a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    private List<PhoneAccount> getPhoneAccounts(
906ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            int capabilities,
907a0bb705db62a254741629942e29c61da663449ffBryce Lee            int excludedCapabilities,
908ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            String uriScheme,
909ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            String packageName,
910240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            boolean includeDisabledAccounts,
911240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            UserHandle userHandle) {
9126a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        List<PhoneAccount> accounts = new ArrayList<>(mState.accounts.size());
913293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        for (PhoneAccount m : mState.accounts) {
914ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            if (!(m.isEnabled() || includeDisabledAccounts)) {
915ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon                // Do not include disabled accounts.
916ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon                continue;
917ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon            }
918ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon
919a0bb705db62a254741629942e29c61da663449ffBryce Lee            if ((m.getCapabilities() & excludedCapabilities) != 0) {
920a0bb705db62a254741629942e29c61da663449ffBryce Lee                // If an excluded capability is present, skip.
921a0bb705db62a254741629942e29c61da663449ffBryce Lee                continue;
922a0bb705db62a254741629942e29c61da663449ffBryce Lee            }
923a0bb705db62a254741629942e29c61da663449ffBryce Lee
9246a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            if (capabilities != 0 && !m.hasCapabilities(capabilities)) {
925105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                // Account doesn't have the right capabilities; skip this one.
926105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                continue;
927105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            }
928105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            if (uriScheme != null && !m.supportsUriScheme(uriScheme)) {
929105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                // Account doesn't support this URI scheme; skip this one.
930105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                continue;
931f2a8491d71915c621518ac8a40bed3c2a35272a9Ihab Awad            }
9326a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            PhoneAccountHandle handle = m.getAccountHandle();
9336a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon
9346a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            if (resolveComponent(handle).isEmpty()) {
935105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                // This component cannot be resolved anymore; skip this one.
936105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                continue;
937105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            }
9386a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            if (packageName != null &&
9396a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                    !packageName.equals(handle.getComponentName().getPackageName())) {
9406a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                // Not the right package name; skip this one.
9416a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                continue;
9426a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            }
943240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            if (!isVisibleForUser(m, userHandle, false)) {
944105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                // Account is not visible for the current user; skip this one.
945105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                continue;
946105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            }
9476a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            accounts.add(m);
948104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        }
9496a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        return accounts;
950104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad    }
951176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
9526a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    //
9536a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    // State Implementation for PhoneAccountRegistrar
9546a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon    //
9556a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon
956293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    /**
957293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad     * The state of this {@code PhoneAccountRegistrar}.
958293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad     */
959b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    @VisibleForTesting
960b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    public static class State {
961293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        /**
9624a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak         * Store the default phone account handle of users. If no record of a user can be found in
9634a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak         * the map, it means that no default phone account handle is set in that user.
964293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad         */
9654a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        public final Map<UserHandle, DefaultPhoneAccountHandle> defaultOutgoingAccountHandles
9664a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                = new ConcurrentHashMap<>();
967293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
968293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad        /**
9697cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn         * The complete list of {@code PhoneAccount}s known to the Telecom subsystem.
970293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad         */
9718f89f8d2a01385ca2972d2254b1b8c653e1bbe30Shriram Ganesh        public final List<PhoneAccount> accounts = new CopyOnWriteArrayList<>();
9728425357e131867f33587641f23a1d1a328acf139Tyler Gunn
9738425357e131867f33587641f23a1d1a328acf139Tyler Gunn        /**
9748425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * The version number of the State data.
9758425357e131867f33587641f23a1d1a328acf139Tyler Gunn         */
9768425357e131867f33587641f23a1d1a328acf139Tyler Gunn        public int versionNumber;
977293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    }
978293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
9799787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn    /**
9804a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak     * The default {@link PhoneAccountHandle} of a user.
9814a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak     */
9824a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak    public static class DefaultPhoneAccountHandle {
9834a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak
9844a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        public final UserHandle userHandle;
9854a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak
9864a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        public final PhoneAccountHandle phoneAccountHandle;
9874a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak
9880c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        public final String groupId;
9890c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger
9904a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        public DefaultPhoneAccountHandle(UserHandle userHandle,
9910c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                PhoneAccountHandle phoneAccountHandle, String groupId) {
9924a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            this.userHandle = userHandle;
9934a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            this.phoneAccountHandle = phoneAccountHandle;
9940c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            this.groupId = groupId;
9954a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak        }
9964a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak    }
9974a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak
9984a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak    /**
9999787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn     * Dumps the state of the {@link CallsManager}.
10009787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn     *
10019787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn     * @param pw The {@code IndentingPrintWriter} to write the state to.
10029787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn     */
10039787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn    public void dump(IndentingPrintWriter pw) {
10049787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn        if (mState != null) {
10059787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn            pw.println("xmlVersion: " + mState.versionNumber);
10064a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            DefaultPhoneAccountHandle defaultPhoneAccountHandle
10074a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                    = mState.defaultOutgoingAccountHandles.get(Process.myUserHandle());
10084a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            pw.println("defaultOutgoing: " + (defaultPhoneAccountHandle == null ? "none" :
10094a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                    defaultPhoneAccountHandle.phoneAccountHandle));
1010240656f19c078b4f703d0502ce29114de0d45a50Tony Mak            pw.println("simCallManager: " + getSimCallManager(mCurrentUserHandle));
10119787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn            pw.println("phoneAccounts:");
10129787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn            pw.increaseIndent();
10139787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn            for (PhoneAccount phoneAccount : mState.accounts) {
10149787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn                pw.println(phoneAccount);
10159787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn            }
10169787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn            pw.decreaseIndent();
10179787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn        }
10189787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn    }
10199787e0e80d8960cf8b0ca74c7cdc4c4aac97187aTyler Gunn
1020293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    ////////////////////////////////////////////////////////////////////////////////////////////////
1021293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    //
1022293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    // State management
1023293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    //
1024293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad
10253f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu    private class AsyncXmlWriter extends AsyncTask<ByteArrayOutputStream, Void, Void> {
10263f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu        @Override
10273f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu        public Void doInBackground(ByteArrayOutputStream... args) {
10283f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            final ByteArrayOutputStream buffer = args[0];
10293f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            FileOutputStream fileOutput = null;
1030b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            try {
10313f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu                synchronized (mWriteLock) {
10323f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu                    fileOutput = mAtomicFile.startWrite();
10333f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu                    buffer.writeTo(fileOutput);
10343f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu                    mAtomicFile.finishWrite(fileOutput);
1035b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                }
10363f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            } catch (IOException e) {
10373f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu                Log.e(this, e, "Writing state to XML file");
10383f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu                mAtomicFile.failWrite(fileOutput);
1039b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            }
10403f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            return null;
10413f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu        }
10423f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu    }
10433f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu
10443f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu    private void write() {
10453f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu        try {
10463f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            ByteArrayOutputStream os = new ByteArrayOutputStream();
10473f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            XmlSerializer serializer = new FastXmlSerializer();
10483f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            serializer.setOutput(os, "utf-8");
10493f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            writeToXml(mState, serializer, mContext);
10503f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            serializer.flush();
10513f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            new AsyncXmlWriter().execute(os);
1052b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        } catch (IOException e) {
10533f7f64d6042f32bfda99b13d053bd49997a08306Hall Liu            Log.e(this, e, "Writing state to XML buffer");
1054176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon        }
1055104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad    }
1056176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
1057b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    private void read() {
1058b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        final InputStream is;
1059104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        try {
1060b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            is = mAtomicFile.openRead();
1061b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        } catch (FileNotFoundException ex) {
1062b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            return;
1063104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        }
1064176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
10658425357e131867f33587641f23a1d1a328acf139Tyler Gunn        boolean versionChanged = false;
10668425357e131867f33587641f23a1d1a328acf139Tyler Gunn
1067b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        XmlPullParser parser;
1068b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        try {
1069b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            parser = Xml.newPullParser();
1070b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            parser.setInput(new BufferedInputStream(is), null);
1071b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            parser.nextTag();
10728425357e131867f33587641f23a1d1a328acf139Tyler Gunn            mState = readFromXml(parser, mContext);
10738425357e131867f33587641f23a1d1a328acf139Tyler Gunn            versionChanged = mState.versionNumber < EXPECTED_STATE_VERSION;
10748425357e131867f33587641f23a1d1a328acf139Tyler Gunn
1075b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        } catch (IOException | XmlPullParserException e) {
1076b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            Log.e(this, e, "Reading state from XML file");
1077b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            mState = new State();
1078b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        } finally {
1079b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            try {
1080b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                is.close();
1081b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            } catch (IOException e) {
1082b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                Log.e(this, e, "Closing InputStream");
1083b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            }
1084b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        }
10858425357e131867f33587641f23a1d1a328acf139Tyler Gunn
1086105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        // Verify all of the UserHandles.
1087105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        List<PhoneAccount> badAccounts = new ArrayList<>();
1088105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        for (PhoneAccount phoneAccount : mState.accounts) {
1089105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            UserHandle userHandle = phoneAccount.getAccountHandle().getUserHandle();
1090105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            if (userHandle == null) {
1091105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                Log.w(this, "Missing UserHandle for %s", phoneAccount);
1092105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                badAccounts.add(phoneAccount);
1093105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            } else if (mUserManager.getSerialNumberForUser(userHandle) == -1) {
1094105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                Log.w(this, "User does not exist for %s", phoneAccount);
1095105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                badAccounts.add(phoneAccount);
1096105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            }
1097105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        }
1098105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        mState.accounts.removeAll(badAccounts);
1099105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
11008425357e131867f33587641f23a1d1a328acf139Tyler Gunn        // If an upgrade occurred, write out the changed data.
1101105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        if (versionChanged || !badAccounts.isEmpty()) {
11028425357e131867f33587641f23a1d1a328acf139Tyler Gunn            write();
11038425357e131867f33587641f23a1d1a328acf139Tyler Gunn        }
1104176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon    }
1105176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
1106105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton    private static void writeToXml(State state, XmlSerializer serializer, Context context)
1107b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            throws IOException {
1108105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        sStateXml.writeToXml(state, serializer, context);
1109176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon    }
1110176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
11118425357e131867f33587641f23a1d1a328acf139Tyler Gunn    private static State readFromXml(XmlPullParser parser, Context context)
1112b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            throws IOException, XmlPullParserException {
11138425357e131867f33587641f23a1d1a328acf139Tyler Gunn        State s = sStateXml.readFromXml(parser, 0, context);
1114b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        return s != null ? s : new State();
1115176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon    }
1116176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon
1117293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad    ////////////////////////////////////////////////////////////////////////////////////////////////
1118104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad    //
1119b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    // XML serialization
1120104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad    //
1121104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
1122b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    @VisibleForTesting
11232692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad    public abstract static class XmlSerialization<T> {
1124369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        private static final String TAG_VALUE = "value";
1125369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        private static final String ATTRIBUTE_LENGTH = "length";
1126369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        private static final String ATTRIBUTE_KEY = "key";
1127369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        private static final String ATTRIBUTE_VALUE_TYPE = "type";
1128369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        private static final String VALUE_TYPE_STRING = "string";
1129369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        private static final String VALUE_TYPE_INTEGER = "integer";
1130369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        private static final String VALUE_TYPE_BOOLEAN = "boolean";
11318425357e131867f33587641f23a1d1a328acf139Tyler Gunn
1132b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        /**
1133b78b27693afbe9736f0a54ec473328955251f885Ihab Awad         * Write the supplied object to XML
1134b78b27693afbe9736f0a54ec473328955251f885Ihab Awad         */
1135105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        public abstract void writeToXml(T o, XmlSerializer serializer, Context context)
11362692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                throws IOException;
1137b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
1138b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        /**
1139b78b27693afbe9736f0a54ec473328955251f885Ihab Awad         * Read from the supplied XML into a new object, returning null in case of an
1140b78b27693afbe9736f0a54ec473328955251f885Ihab Awad         * unrecoverable schema mismatch or other data error. 'parser' must be already
1141b78b27693afbe9736f0a54ec473328955251f885Ihab Awad         * positioned at the first tag that is expected to have been emitted by this
1142b78b27693afbe9736f0a54ec473328955251f885Ihab Awad         * object's writeToXml(). This object tries to fail early without modifying
1143b78b27693afbe9736f0a54ec473328955251f885Ihab Awad         * 'parser' if it does not recognize the data it sees.
1144b78b27693afbe9736f0a54ec473328955251f885Ihab Awad         */
11458425357e131867f33587641f23a1d1a328acf139Tyler Gunn        public abstract T readFromXml(XmlPullParser parser, int version, Context context)
11462692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                throws IOException, XmlPullParserException;
11472692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad
1148d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad        protected void writeTextIfNonNull(String tagName, Object value, XmlSerializer serializer)
11492692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                throws IOException {
11502692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad            if (value != null) {
11512692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                serializer.startTag(null, tagName);
11522692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                serializer.text(Objects.toString(value));
11532692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                serializer.endTag(null, tagName);
11542692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad            }
11552692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad        }
11568425357e131867f33587641f23a1d1a328acf139Tyler Gunn
11578425357e131867f33587641f23a1d1a328acf139Tyler Gunn        /**
11588425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * Serializes a string array.
11598425357e131867f33587641f23a1d1a328acf139Tyler Gunn         *
11608425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * @param tagName The tag name for the string array.
11618425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * @param values The string values to serialize.
11628425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * @param serializer The serializer.
11638425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * @throws IOException
11648425357e131867f33587641f23a1d1a328acf139Tyler Gunn         */
11658425357e131867f33587641f23a1d1a328acf139Tyler Gunn        protected void writeStringList(String tagName, List<String> values,
11668425357e131867f33587641f23a1d1a328acf139Tyler Gunn                XmlSerializer serializer)
11678425357e131867f33587641f23a1d1a328acf139Tyler Gunn                throws IOException {
11688425357e131867f33587641f23a1d1a328acf139Tyler Gunn
11698425357e131867f33587641f23a1d1a328acf139Tyler Gunn            serializer.startTag(null, tagName);
11708425357e131867f33587641f23a1d1a328acf139Tyler Gunn            if (values != null) {
1171369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                serializer.attribute(null, ATTRIBUTE_LENGTH, Objects.toString(values.size()));
11728425357e131867f33587641f23a1d1a328acf139Tyler Gunn                for (String toSerialize : values) {
1173369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    serializer.startTag(null, TAG_VALUE);
11748425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    if (toSerialize != null ){
11758425357e131867f33587641f23a1d1a328acf139Tyler Gunn                        serializer.text(toSerialize);
11768425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    }
1177369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    serializer.endTag(null, TAG_VALUE);
11788425357e131867f33587641f23a1d1a328acf139Tyler Gunn                }
11798425357e131867f33587641f23a1d1a328acf139Tyler Gunn            } else {
1180369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                serializer.attribute(null, ATTRIBUTE_LENGTH, "0");
1181369c8740adecbb47a17171f861322a76588a6319Tyler Gunn            }
1182369c8740adecbb47a17171f861322a76588a6319Tyler Gunn            serializer.endTag(null, tagName);
1183369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        }
1184369c8740adecbb47a17171f861322a76588a6319Tyler Gunn
1185369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        protected void writeBundle(String tagName, Bundle values, XmlSerializer serializer)
1186369c8740adecbb47a17171f861322a76588a6319Tyler Gunn            throws IOException {
1187369c8740adecbb47a17171f861322a76588a6319Tyler Gunn
1188369c8740adecbb47a17171f861322a76588a6319Tyler Gunn            serializer.startTag(null, tagName);
1189369c8740adecbb47a17171f861322a76588a6319Tyler Gunn            if (values != null) {
1190369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                for (String key : values.keySet()) {
1191369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    Object value = values.get(key);
1192369c8740adecbb47a17171f861322a76588a6319Tyler Gunn
1193369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    if (value == null) {
1194369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        continue;
1195369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    }
1196369c8740adecbb47a17171f861322a76588a6319Tyler Gunn
1197369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    String valueType;
1198369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    if (value instanceof String) {
1199369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        valueType = VALUE_TYPE_STRING;
1200369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    } else if (value instanceof Integer) {
1201369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        valueType = VALUE_TYPE_INTEGER;
1202369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    } else if (value instanceof Boolean) {
1203369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        valueType = VALUE_TYPE_BOOLEAN;
1204369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    } else {
1205369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        Log.w(this,
1206369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                                "PhoneAccounts support only string, integer and boolean extras TY.");
1207369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        continue;
1208369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    }
1209369c8740adecbb47a17171f861322a76588a6319Tyler Gunn
1210369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    serializer.startTag(null, TAG_VALUE);
1211369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    serializer.attribute(null, ATTRIBUTE_KEY, key);
1212369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    serializer.attribute(null, ATTRIBUTE_VALUE_TYPE, valueType);
1213369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    serializer.text(Objects.toString(value));
1214369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    serializer.endTag(null, TAG_VALUE);
1215369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                }
12168425357e131867f33587641f23a1d1a328acf139Tyler Gunn            }
12178425357e131867f33587641f23a1d1a328acf139Tyler Gunn            serializer.endTag(null, tagName);
1218d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad        }
1219d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad
12209c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon        protected void writeIconIfNonNull(String tagName, Icon value, XmlSerializer serializer)
1221d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                throws IOException {
12229c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon            if (value != null) {
1223d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                ByteArrayOutputStream stream = new ByteArrayOutputStream();
12249c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                value.writeToStream(stream);
12259c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                byte[] iconByteArray = stream.toByteArray();
12269c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                String text = Base64.encodeToString(iconByteArray, 0, iconByteArray.length, 0);
12278425357e131867f33587641f23a1d1a328acf139Tyler Gunn
1228d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                serializer.startTag(null, tagName);
1229d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                serializer.text(text);
1230d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                serializer.endTag(null, tagName);
1231d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad            }
12328425357e131867f33587641f23a1d1a328acf139Tyler Gunn        }
12338425357e131867f33587641f23a1d1a328acf139Tyler Gunn
1234105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        protected void writeLong(String tagName, long value, XmlSerializer serializer)
1235105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                throws IOException {
1236105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            serializer.startTag(null, tagName);
1237105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            serializer.text(Long.valueOf(value).toString());
1238105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            serializer.endTag(null, tagName);
1239105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        }
1240105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
12410c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        protected void writeNonNullString(String tagName, String value, XmlSerializer serializer)
12420c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                throws IOException {
12430c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            serializer.startTag(null, tagName);
12440c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            serializer.text(value != null ? value : "");
12450c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger            serializer.endTag(null, tagName);
12460c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger        }
12470c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger
12488425357e131867f33587641f23a1d1a328acf139Tyler Gunn        /**
12498425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * Reads a string array from the XML parser.
12508425357e131867f33587641f23a1d1a328acf139Tyler Gunn         *
12518425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * @param parser The XML parser.
12528425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * @return String array containing the parsed values.
12538425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * @throws IOException Exception related to IO.
12548425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * @throws XmlPullParserException Exception related to parsing.
12558425357e131867f33587641f23a1d1a328acf139Tyler Gunn         */
12568425357e131867f33587641f23a1d1a328acf139Tyler Gunn        protected List<String> readStringList(XmlPullParser parser)
12578425357e131867f33587641f23a1d1a328acf139Tyler Gunn                throws IOException, XmlPullParserException {
12588425357e131867f33587641f23a1d1a328acf139Tyler Gunn
1259369c8740adecbb47a17171f861322a76588a6319Tyler Gunn            int length = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_LENGTH));
12608425357e131867f33587641f23a1d1a328acf139Tyler Gunn            List<String> arrayEntries = new ArrayList<String>(length);
12618425357e131867f33587641f23a1d1a328acf139Tyler Gunn            String value = null;
12628425357e131867f33587641f23a1d1a328acf139Tyler Gunn
12638425357e131867f33587641f23a1d1a328acf139Tyler Gunn            if (length == 0) {
12648425357e131867f33587641f23a1d1a328acf139Tyler Gunn                return arrayEntries;
12658425357e131867f33587641f23a1d1a328acf139Tyler Gunn            }
12668425357e131867f33587641f23a1d1a328acf139Tyler Gunn
12678425357e131867f33587641f23a1d1a328acf139Tyler Gunn            int outerDepth = parser.getDepth();
12688425357e131867f33587641f23a1d1a328acf139Tyler Gunn            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
1269369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                if (parser.getName().equals(TAG_VALUE)) {
12708e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn                    parser.next();
12718425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    value = parser.getText();
12728425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    arrayEntries.add(value);
12738425357e131867f33587641f23a1d1a328acf139Tyler Gunn                }
12748425357e131867f33587641f23a1d1a328acf139Tyler Gunn            }
12758425357e131867f33587641f23a1d1a328acf139Tyler Gunn
12768425357e131867f33587641f23a1d1a328acf139Tyler Gunn            return arrayEntries;
12778425357e131867f33587641f23a1d1a328acf139Tyler Gunn        }
1278d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad
1279369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        /**
1280369c8740adecbb47a17171f861322a76588a6319Tyler Gunn         * Reads a bundle from the XML parser.
1281369c8740adecbb47a17171f861322a76588a6319Tyler Gunn         *
1282369c8740adecbb47a17171f861322a76588a6319Tyler Gunn         * @param parser The XML parser.
1283369c8740adecbb47a17171f861322a76588a6319Tyler Gunn         * @return Bundle containing the parsed values.
1284369c8740adecbb47a17171f861322a76588a6319Tyler Gunn         * @throws IOException Exception related to IO.
1285369c8740adecbb47a17171f861322a76588a6319Tyler Gunn         * @throws XmlPullParserException Exception related to parsing.
1286369c8740adecbb47a17171f861322a76588a6319Tyler Gunn         */
1287369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        protected Bundle readBundle(XmlPullParser parser)
1288369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                throws IOException, XmlPullParserException {
1289369c8740adecbb47a17171f861322a76588a6319Tyler Gunn
1290369c8740adecbb47a17171f861322a76588a6319Tyler Gunn            Bundle bundle = null;
1291369c8740adecbb47a17171f861322a76588a6319Tyler Gunn            int outerDepth = parser.getDepth();
1292369c8740adecbb47a17171f861322a76588a6319Tyler Gunn            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
1293369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                if (parser.getName().equals(TAG_VALUE)) {
1294369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    String valueType = parser.getAttributeValue(null, ATTRIBUTE_VALUE_TYPE);
1295369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    String key = parser.getAttributeValue(null, ATTRIBUTE_KEY);
1296369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    parser.next();
1297369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    String value = parser.getText();
1298369c8740adecbb47a17171f861322a76588a6319Tyler Gunn
1299369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    if (bundle == null) {
1300369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        bundle = new Bundle();
1301369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    }
1302369c8740adecbb47a17171f861322a76588a6319Tyler Gunn
1303369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    // Do not write null values to the bundle.
1304369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    if (value == null) {
1305369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        continue;
1306369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    }
1307369c8740adecbb47a17171f861322a76588a6319Tyler Gunn
1308369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    if (VALUE_TYPE_STRING.equals(valueType)) {
1309369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        bundle.putString(key, value);
1310369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    } else if (VALUE_TYPE_INTEGER.equals(valueType)) {
1311369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        try {
1312369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                            int intValue = Integer.parseInt(value);
1313369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                            bundle.putInt(key, intValue);
1314369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        } catch (NumberFormatException nfe) {
1315369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                            Log.w(this, "Invalid integer PhoneAccount extra.");
1316369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        }
1317369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    } else if (VALUE_TYPE_BOOLEAN.equals(valueType)) {
1318369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        boolean boolValue = Boolean.parseBoolean(value);
1319369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        bundle.putBoolean(key, boolValue);
1320369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    } else {
1321369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        Log.w(this, "Invalid type " + valueType + " for PhoneAccount bundle.");
1322369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    }
1323369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                }
1324369c8740adecbb47a17171f861322a76588a6319Tyler Gunn            }
1325369c8740adecbb47a17171f861322a76588a6319Tyler Gunn            return bundle;
1326369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        }
1327369c8740adecbb47a17171f861322a76588a6319Tyler Gunn
13289c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon        protected Bitmap readBitmap(XmlPullParser parser) {
1329d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad            byte[] imageByteArray = Base64.decode(parser.getText(), 0);
1330d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad            return BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length);
1331d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad        }
13329c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon
13339c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon        protected Icon readIcon(XmlPullParser parser) throws IOException {
13349c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon            byte[] iconByteArray = Base64.decode(parser.getText(), 0);
13359c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon            ByteArrayInputStream stream = new ByteArrayInputStream(iconByteArray);
13369c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon            return Icon.createFromStream(stream);
13379c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon        }
1338176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon    }
1339104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
1340b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    @VisibleForTesting
1341b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    public static final XmlSerialization<State> sStateXml =
1342b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            new XmlSerialization<State>() {
1343b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        private static final String CLASS_STATE = "phone_account_registrar_state";
1344104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        private static final String DEFAULT_OUTGOING = "default_outgoing";
1345104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        private static final String ACCOUNTS = "accounts";
13468425357e131867f33587641f23a1d1a328acf139Tyler Gunn        private static final String VERSION = "version";
1347104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
1348104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        @Override
1349105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        public void writeToXml(State o, XmlSerializer serializer, Context context)
1350b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                throws IOException {
13512692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad            if (o != null) {
13522692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                serializer.startTag(null, CLASS_STATE);
13538425357e131867f33587641f23a1d1a328acf139Tyler Gunn                serializer.attribute(null, VERSION, Objects.toString(EXPECTED_STATE_VERSION));
1354b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
13554a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                serializer.startTag(null, DEFAULT_OUTGOING);
13564a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                for (DefaultPhoneAccountHandle defaultPhoneAccountHandle : o
13574a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        .defaultOutgoingAccountHandles.values()) {
13584a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                    sDefaultPhoneAcountHandleXml
13594a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            .writeToXml(defaultPhoneAccountHandle, serializer, context);
13602692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                }
13614a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                serializer.endTag(null, DEFAULT_OUTGOING);
1362b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
13632692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                serializer.startTag(null, ACCOUNTS);
13642692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                for (PhoneAccount m : o.accounts) {
1365105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                    sPhoneAccountXml.writeToXml(m, serializer, context);
13662692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                }
13672692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                serializer.endTag(null, ACCOUNTS);
1368b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
13692692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                serializer.endTag(null, CLASS_STATE);
13702692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad            }
1371104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        }
1372104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
1373104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        @Override
13748425357e131867f33587641f23a1d1a328acf139Tyler Gunn        public State readFromXml(XmlPullParser parser, int version, Context context)
1375b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                throws IOException, XmlPullParserException {
1376b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            if (parser.getName().equals(CLASS_STATE)) {
1377b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                State s = new State();
13788425357e131867f33587641f23a1d1a328acf139Tyler Gunn
13798425357e131867f33587641f23a1d1a328acf139Tyler Gunn                String rawVersion = parser.getAttributeValue(null, VERSION);
13804a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                s.versionNumber = TextUtils.isEmpty(rawVersion) ? 1 : Integer.parseInt(rawVersion);
13818425357e131867f33587641f23a1d1a328acf139Tyler Gunn
1382b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                int outerDepth = parser.getDepth();
1383b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                while (XmlUtils.nextElementWithin(parser, outerDepth)) {
1384b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    if (parser.getName().equals(DEFAULT_OUTGOING)) {
13854a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        if (s.versionNumber < 9) {
13860c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                            // Migrate old default phone account handle here by assuming the
13870c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                            // default phone account handle belongs to the primary user. Also,
13880c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                            // assume there are no groups.
13894a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            parser.nextTag();
13904a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            PhoneAccountHandle phoneAccountHandle = sPhoneAccountHandleXml
13914a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                    .readFromXml(parser, s.versionNumber, context);
13924a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            UserManager userManager = UserManager.get(context);
13934a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            UserInfo primaryUser = userManager.getPrimaryUser();
13944a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            if (primaryUser != null) {
13954a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                UserHandle userHandle = primaryUser.getUserHandle();
13964a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                DefaultPhoneAccountHandle defaultPhoneAccountHandle
13974a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                        = new DefaultPhoneAccountHandle(userHandle,
13980c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                                        phoneAccountHandle, "" /* groupId */);
13994a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                s.defaultOutgoingAccountHandles
14004a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                        .put(userHandle, defaultPhoneAccountHandle);
14014a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            }
14024a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        } else {
14034a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            int defaultAccountHandlesDepth = parser.getDepth();
14044a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            while (XmlUtils.nextElementWithin(parser, defaultAccountHandlesDepth)) {
14054a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                DefaultPhoneAccountHandle accountHandle
14064a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                        = sDefaultPhoneAcountHandleXml
14074a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                        .readFromXml(parser, s.versionNumber, context);
14084a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                if (accountHandle != null && s.accounts != null) {
14094a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                    s.defaultOutgoingAccountHandles
14104a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                            .put(accountHandle.userHandle, accountHandle);
14114a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                }
14124a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            }
14134a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        }
1414b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    } else if (parser.getName().equals(ACCOUNTS)) {
1415b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        int accountsDepth = parser.getDepth();
1416b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        while (XmlUtils.nextElementWithin(parser, accountsDepth)) {
14178425357e131867f33587641f23a1d1a328acf139Tyler Gunn                            PhoneAccount account = sPhoneAccountXml.readFromXml(parser,
14188425357e131867f33587641f23a1d1a328acf139Tyler Gunn                                    s.versionNumber, context);
14198425357e131867f33587641f23a1d1a328acf139Tyler Gunn
14208425357e131867f33587641f23a1d1a328acf139Tyler Gunn                            if (account != null && s.accounts != null) {
1421b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                                s.accounts.add(account);
1422b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                            }
1423b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        }
1424104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad                    }
1425104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad                }
1426b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                return s;
1427104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad            }
1428b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            return null;
1429104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        }
1430104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad    };
1431104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
1432b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    @VisibleForTesting
14334a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak    public static final XmlSerialization<DefaultPhoneAccountHandle> sDefaultPhoneAcountHandleXml  =
14344a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            new XmlSerialization<DefaultPhoneAccountHandle>() {
14354a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                private static final String CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE
14364a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        = "default_outgoing_phone_account_handle";
14374a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                private static final String USER_SERIAL_NUMBER = "user_serial_number";
14380c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                private static final String GROUP_ID = "group_id";
14394a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                private static final String ACCOUNT_HANDLE = "account_handle";
14404a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak
14414a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                @Override
14424a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                public void writeToXml(DefaultPhoneAccountHandle o, XmlSerializer serializer,
14434a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        Context context) throws IOException {
14444a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                    if (o != null) {
14454a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        final UserManager userManager = UserManager.get(context);
14464a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        final long serialNumber = userManager.getSerialNumberForUser(o.userHandle);
14474a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        if (serialNumber != -1) {
14484a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            serializer.startTag(null, CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE);
14494a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            writeLong(USER_SERIAL_NUMBER, serialNumber, serializer);
14500c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                            writeNonNullString(GROUP_ID, o.groupId, serializer);
14514a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            serializer.startTag(null, ACCOUNT_HANDLE);
14524a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            sPhoneAccountHandleXml.writeToXml(o.phoneAccountHandle, serializer,
14534a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                    context);
14544a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            serializer.endTag(null, ACCOUNT_HANDLE);
14554a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            serializer.endTag(null, CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE);
14564a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        }
14574a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                    }
14584a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                }
14594a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak
14604a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                @Override
14614a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                public DefaultPhoneAccountHandle readFromXml(XmlPullParser parser, int version,
14624a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        Context context)
14634a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        throws IOException, XmlPullParserException {
14644a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                    if (parser.getName().equals(CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE)) {
14654a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        int outerDepth = parser.getDepth();
14664a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        PhoneAccountHandle accountHandle = null;
14674a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        String userSerialNumberString = null;
14680c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                        String groupId = "";
14694a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        while (XmlUtils.nextElementWithin(parser, outerDepth)) {
14704a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            if (parser.getName().equals(ACCOUNT_HANDLE)) {
14714a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                parser.nextTag();
14724a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                accountHandle = sPhoneAccountHandleXml.readFromXml(parser, version,
14734a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                        context);
14744a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            } else if (parser.getName().equals(USER_SERIAL_NUMBER)) {
14754a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                parser.next();
14764a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                userSerialNumberString = parser.getText();
14770c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                            } else if (parser.getName().equals(GROUP_ID)) {
14780c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                                parser.next();
14790c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                                groupId = parser.getText();
14804a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            }
14814a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        }
14824a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        UserHandle userHandle = null;
14834a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        if (userSerialNumberString != null) {
14844a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            try {
14854a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                long serialNumber = Long.parseLong(userSerialNumberString);
14864a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                userHandle = UserManager.get(context)
14874a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                        .getUserForSerialNumber(serialNumber);
14884a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            } catch (NumberFormatException e) {
14894a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                Log.e(this, e,
14904a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                                        "Could not parse UserHandle " + userSerialNumberString);
14914a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                            }
14924a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        }
14930c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                        if (accountHandle != null && userHandle != null && groupId != null) {
14940c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                            return new DefaultPhoneAccountHandle(userHandle, accountHandle,
14950c87b3c31f4ce9e47a07e40012cf669a763a1575Brad Ebinger                                    groupId);
14964a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                        }
14974a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                    }
14984a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                    return null;
14994a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak                }
15004a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak            };
15014a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak
15024a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak
15034a3e2fd2b783c9f667a719237ef527ebe686fe32Tony Mak    @VisibleForTesting
1504b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    public static final XmlSerialization<PhoneAccount> sPhoneAccountXml =
1505b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            new XmlSerialization<PhoneAccount>() {
1506b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        private static final String CLASS_PHONE_ACCOUNT = "phone_account";
1507b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        private static final String ACCOUNT_HANDLE = "account_handle";
15087129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee        private static final String ADDRESS = "handle";
15097129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee        private static final String SUBSCRIPTION_ADDRESS = "subscription_number";
1510104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        private static final String CAPABILITIES = "capabilities";
151196a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom        private static final String SUPPORTED_AUDIO_ROUTES = "supported_audio_routes";
1512104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        private static final String ICON_RES_ID = "icon_res_id";
1513d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad        private static final String ICON_PACKAGE_NAME = "icon_package_name";
1514d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad        private static final String ICON_BITMAP = "icon_bitmap";
15157e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad        private static final String ICON_TINT = "icon_tint";
15167e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad        private static final String HIGHLIGHT_COLOR = "highlight_color";
1517104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        private static final String LABEL = "label";
1518104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        private static final String SHORT_DESCRIPTION = "short_description";
15198425357e131867f33587641f23a1d1a328acf139Tyler Gunn        private static final String SUPPORTED_URI_SCHEMES = "supported_uri_schemes";
15209c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon        private static final String ICON = "icon";
1521369c8740adecbb47a17171f861322a76588a6319Tyler Gunn        private static final String EXTRAS = "extras";
1522ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon        private static final String ENABLED = "enabled";
1523104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
1524104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        @Override
1525105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        public void writeToXml(PhoneAccount o, XmlSerializer serializer, Context context)
1526b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                throws IOException {
15272692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad            if (o != null) {
15282692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                serializer.startTag(null, CLASS_PHONE_ACCOUNT);
1529b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
15302692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                if (o.getAccountHandle() != null) {
15312692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                    serializer.startTag(null, ACCOUNT_HANDLE);
1532105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                    sPhoneAccountHandleXml.writeToXml(o.getAccountHandle(), serializer, context);
15332692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                    serializer.endTag(null, ACCOUNT_HANDLE);
15342692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                }
1535b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
1536d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                writeTextIfNonNull(ADDRESS, o.getAddress(), serializer);
1537d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                writeTextIfNonNull(SUBSCRIPTION_ADDRESS, o.getSubscriptionAddress(), serializer);
1538d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                writeTextIfNonNull(CAPABILITIES, Integer.toString(o.getCapabilities()), serializer);
15399c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                writeIconIfNonNull(ICON, o.getIcon(), serializer);
15407e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                writeTextIfNonNull(HIGHLIGHT_COLOR,
15417e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                        Integer.toString(o.getHighlightColor()), serializer);
1542d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                writeTextIfNonNull(LABEL, o.getLabel(), serializer);
1543d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                writeTextIfNonNull(SHORT_DESCRIPTION, o.getShortDescription(), serializer);
15448425357e131867f33587641f23a1d1a328acf139Tyler Gunn                writeStringList(SUPPORTED_URI_SCHEMES, o.getSupportedUriSchemes(), serializer);
1545369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                writeBundle(EXTRAS, o.getExtras(), serializer);
1546ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon                writeTextIfNonNull(ENABLED, o.isEnabled() ? "true" : "false" , serializer);
154796a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom                writeTextIfNonNull(SUPPORTED_AUDIO_ROUTES, Integer.toString(
154896a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom                        o.getSupportedAudioRoutes()), serializer);
1549b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
15502692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                serializer.endTag(null, CLASS_PHONE_ACCOUNT);
15512692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad            }
1552104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        }
1553104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
15548425357e131867f33587641f23a1d1a328acf139Tyler Gunn        public PhoneAccount readFromXml(XmlPullParser parser, int version, Context context)
1555b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                throws IOException, XmlPullParserException {
1556b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            if (parser.getName().equals(CLASS_PHONE_ACCOUNT)) {
1557b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                int outerDepth = parser.getDepth();
1558b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                PhoneAccountHandle accountHandle = null;
15597129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                Uri address = null;
15607129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                Uri subscriptionAddress = null;
1561b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                int capabilities = 0;
156296a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom                int supportedAudioRoutes = 0;
15637e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                int iconResId = PhoneAccount.NO_RESOURCE_ID;
1564d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                String iconPackageName = null;
15657e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                Bitmap iconBitmap = null;
156607bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad                int iconTint = PhoneAccount.NO_ICON_TINT;
156707bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad                int highlightColor = PhoneAccount.NO_HIGHLIGHT_COLOR;
1568b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                String label = null;
1569b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                String shortDescription = null;
15708425357e131867f33587641f23a1d1a328acf139Tyler Gunn                List<String> supportedUriSchemes = null;
15719c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                Icon icon = null;
1572ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon                boolean enabled = false;
1573369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                Bundle extras = null;
1574b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
1575b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                while (XmlUtils.nextElementWithin(parser, outerDepth)) {
1576b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    if (parser.getName().equals(ACCOUNT_HANDLE)) {
1577b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        parser.nextTag();
15788425357e131867f33587641f23a1d1a328acf139Tyler Gunn                        accountHandle = sPhoneAccountHandleXml.readFromXml(parser, version,
15798425357e131867f33587641f23a1d1a328acf139Tyler Gunn                                context);
15807129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                    } else if (parser.getName().equals(ADDRESS)) {
1581b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        parser.next();
15827129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                        address = Uri.parse(parser.getText());
15837129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                    } else if (parser.getName().equals(SUBSCRIPTION_ADDRESS)) {
1584b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        parser.next();
15857129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                        String nextText = parser.getText();
15867129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                        subscriptionAddress = nextText == null ? null : Uri.parse(nextText);
1587b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    } else if (parser.getName().equals(CAPABILITIES)) {
1588b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        parser.next();
1589b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        capabilities = Integer.parseInt(parser.getText());
1590b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    } else if (parser.getName().equals(ICON_RES_ID)) {
1591b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        parser.next();
1592b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        iconResId = Integer.parseInt(parser.getText());
1593d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                    } else if (parser.getName().equals(ICON_PACKAGE_NAME)) {
1594d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                        parser.next();
1595d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                        iconPackageName = parser.getText();
1596d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                    } else if (parser.getName().equals(ICON_BITMAP)) {
1597d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                        parser.next();
15987e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                        iconBitmap = readBitmap(parser);
15997e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                    } else if (parser.getName().equals(ICON_TINT)) {
16007e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                        parser.next();
16017e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                        iconTint = Integer.parseInt(parser.getText());
16027e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                    } else if (parser.getName().equals(HIGHLIGHT_COLOR)) {
160306ce062a2ceb7ca73560edd6b2f85d0f16a17667Nancy Chen                        parser.next();
16047e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                        highlightColor = Integer.parseInt(parser.getText());
1605b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    } else if (parser.getName().equals(LABEL)) {
1606b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        parser.next();
1607b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        label = parser.getText();
1608b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    } else if (parser.getName().equals(SHORT_DESCRIPTION)) {
1609b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        parser.next();
1610b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        shortDescription = parser.getText();
16118425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    } else if (parser.getName().equals(SUPPORTED_URI_SCHEMES)) {
16128425357e131867f33587641f23a1d1a328acf139Tyler Gunn                        supportedUriSchemes = readStringList(parser);
16139c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                    } else if (parser.getName().equals(ICON)) {
16149c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                        parser.next();
16159c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                        icon = readIcon(parser);
1616ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon                    } else if (parser.getName().equals(ENABLED)) {
1617ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon                        parser.next();
1618ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon                        enabled = "true".equalsIgnoreCase(parser.getText());
1619369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                    } else if (parser.getName().equals(EXTRAS)) {
1620369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        extras = readBundle(parser);
162196a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom                    } else if (parser.getName().equals(SUPPORTED_AUDIO_ROUTES)) {
162296a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom                        parser.next();
162396a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom                        supportedAudioRoutes = Integer.parseInt(parser.getText());
1624b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    }
1625b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                }
16268425357e131867f33587641f23a1d1a328acf139Tyler Gunn
1627a9eebe4bd03a916655fd5b0d4f4fb9e8fdbc0ce8Santos Cordon                ComponentName pstnComponentName = new ComponentName("com.android.phone",
1628a9eebe4bd03a916655fd5b0d4f4fb9e8fdbc0ce8Santos Cordon                        "com.android.services.telephony.TelephonyConnectionService");
1629a82aed819d3a86b748d9e403fb288967a10dcdf2Santos Cordon                ComponentName sipComponentName = new ComponentName("com.android.phone",
1630a82aed819d3a86b748d9e403fb288967a10dcdf2Santos Cordon                        "com.android.services.telephony.sip.SipConnectionService");
1631a82aed819d3a86b748d9e403fb288967a10dcdf2Santos Cordon
16328425357e131867f33587641f23a1d1a328acf139Tyler Gunn                // Upgrade older phone accounts to specify the supported URI schemes.
16338425357e131867f33587641f23a1d1a328acf139Tyler Gunn                if (version < 2) {
16348425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    supportedUriSchemes = new ArrayList<>();
16358425357e131867f33587641f23a1d1a328acf139Tyler Gunn
16368425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    // Handle the SIP connection service.
16378425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    // Check the system settings to see if it also should handle "tel" calls.
16388425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    if (accountHandle.getComponentName().equals(sipComponentName)) {
16398425357e131867f33587641f23a1d1a328acf139Tyler Gunn                        boolean useSipForPstn = useSipForPstnCalls(context);
16408425357e131867f33587641f23a1d1a328acf139Tyler Gunn                        supportedUriSchemes.add(PhoneAccount.SCHEME_SIP);
16418425357e131867f33587641f23a1d1a328acf139Tyler Gunn                        if (useSipForPstn) {
16428425357e131867f33587641f23a1d1a328acf139Tyler Gunn                            supportedUriSchemes.add(PhoneAccount.SCHEME_TEL);
16438425357e131867f33587641f23a1d1a328acf139Tyler Gunn                        }
16448425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    } else {
16458425357e131867f33587641f23a1d1a328acf139Tyler Gunn                        supportedUriSchemes.add(PhoneAccount.SCHEME_TEL);
16468425357e131867f33587641f23a1d1a328acf139Tyler Gunn                        supportedUriSchemes.add(PhoneAccount.SCHEME_VOICEMAIL);
16478425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    }
16488425357e131867f33587641f23a1d1a328acf139Tyler Gunn                }
16498425357e131867f33587641f23a1d1a328acf139Tyler Gunn
16507e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                // Upgrade older phone accounts with explicit package name
16517e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                if (version < 5) {
16527e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                    if (iconBitmap == null) {
16537e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                        iconPackageName = accountHandle.getComponentName().getPackageName();
16547e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                    }
16557e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                }
16567e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad
1657a82aed819d3a86b748d9e403fb288967a10dcdf2Santos Cordon                if (version < 6) {
1658a82aed819d3a86b748d9e403fb288967a10dcdf2Santos Cordon                    // Always enable all SIP accounts on upgrade to version 6
1659a82aed819d3a86b748d9e403fb288967a10dcdf2Santos Cordon                    if (accountHandle.getComponentName().equals(sipComponentName)) {
1660a82aed819d3a86b748d9e403fb288967a10dcdf2Santos Cordon                        enabled = true;
1661a82aed819d3a86b748d9e403fb288967a10dcdf2Santos Cordon                    }
1662a82aed819d3a86b748d9e403fb288967a10dcdf2Santos Cordon                }
1663a9eebe4bd03a916655fd5b0d4f4fb9e8fdbc0ce8Santos Cordon                if (version < 7) {
1664a9eebe4bd03a916655fd5b0d4f4fb9e8fdbc0ce8Santos Cordon                    // Always enabled all PSTN acocunts on upgrade to version 7
1665a9eebe4bd03a916655fd5b0d4f4fb9e8fdbc0ce8Santos Cordon                    if (accountHandle.getComponentName().equals(pstnComponentName)) {
1666a9eebe4bd03a916655fd5b0d4f4fb9e8fdbc0ce8Santos Cordon                        enabled = true;
1667a9eebe4bd03a916655fd5b0d4f4fb9e8fdbc0ce8Santos Cordon                    }
1668a9eebe4bd03a916655fd5b0d4f4fb9e8fdbc0ce8Santos Cordon                }
16696f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                if (version < 8) {
16706f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                    // Migrate the SIP account handle ids to use SIP username instead of SIP URI.
16716f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                    if (accountHandle.getComponentName().equals(sipComponentName)) {
16726f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                        Uri accountUri = Uri.parse(accountHandle.getId());
16736f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                        if (accountUri.getScheme() != null &&
16746f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                            accountUri.getScheme().equals(PhoneAccount.SCHEME_SIP)) {
16756f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                            accountHandle = new PhoneAccountHandle(accountHandle.getComponentName(),
16766f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                                    accountUri.getSchemeSpecificPart(),
16776f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                                    accountHandle.getUserHandle());
16786f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                        }
16796f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                    }
16806f752c88d583f3f8f149919aefdb667e3176fef8Roshan Pius                }
1681a82aed819d3a86b748d9e403fb288967a10dcdf2Santos Cordon
168296a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom                if (version < 9) {
168396a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom                    // Set supported audio routes to all by default
168496a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom                    supportedAudioRoutes = CallAudioState.ROUTE_ALL;
168596a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom                }
168696a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom
16877e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                PhoneAccount.Builder builder = PhoneAccount.builder(accountHandle, label)
16887129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                        .setAddress(address)
16897129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                        .setSubscriptionAddress(subscriptionAddress)
16907129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                        .setCapabilities(capabilities)
169196a0be67619944378d95cdedc64b004aadb341e2Christine Hallstrom                        .setSupportedAudioRoutes(supportedAudioRoutes)
16927129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                        .setShortDescription(shortDescription)
16937129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee                        .setSupportedUriSchemes(supportedUriSchemes)
1694ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon                        .setHighlightColor(highlightColor)
1695369c8740adecbb47a17171f861322a76588a6319Tyler Gunn                        .setExtras(extras)
1696ea5cb93d81099f17654e0fdf9b8eda3bfa89f081Santos Cordon                        .setIsEnabled(enabled);
16977e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad
16989c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                if (icon != null) {
16999c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                    builder.setIcon(icon);
17009c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                } else if (iconBitmap != null) {
17019c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                    builder.setIcon(Icon.createWithBitmap(iconBitmap));
17029c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                } else if (!TextUtils.isEmpty(iconPackageName)) {
17039c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                    builder.setIcon(Icon.createWithResource(iconPackageName, iconResId));
17049c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon                    // TODO: Need to set tint.
17057e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad                }
17067e2c7f34dde14afd18c13d39777331ec2ef3a46aIhab Awad
17070a4b95fc7731943fdd1a9b295daae45eb46b28d0Ihab Awad                return builder.build();
1708b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            }
1709b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            return null;
1710104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        }
17118425357e131867f33587641f23a1d1a328acf139Tyler Gunn
17128425357e131867f33587641f23a1d1a328acf139Tyler Gunn        /**
17139c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon         * Determines if the SIP call settings specify to use SIP for all calls, including PSTN
17149c30c280f0007eb32d3ae9a7cad8ceb68120ca41Santos Cordon         * calls.
17158425357e131867f33587641f23a1d1a328acf139Tyler Gunn         *
17168425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * @param context The context.
17178425357e131867f33587641f23a1d1a328acf139Tyler Gunn         * @return {@code True} if SIP should be used for all calls.
17188425357e131867f33587641f23a1d1a328acf139Tyler Gunn         */
17198425357e131867f33587641f23a1d1a328acf139Tyler Gunn        private boolean useSipForPstnCalls(Context context) {
17208425357e131867f33587641f23a1d1a328acf139Tyler Gunn            String option = Settings.System.getString(context.getContentResolver(),
17218425357e131867f33587641f23a1d1a328acf139Tyler Gunn                    Settings.System.SIP_CALL_OPTIONS);
17228425357e131867f33587641f23a1d1a328acf139Tyler Gunn            option = (option != null) ? option : Settings.System.SIP_ADDRESS_ONLY;
17238425357e131867f33587641f23a1d1a328acf139Tyler Gunn            return option.equals(Settings.System.SIP_ALWAYS);
17248425357e131867f33587641f23a1d1a328acf139Tyler Gunn        }
1725104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad    };
1726104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
1727b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    @VisibleForTesting
1728b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    public static final XmlSerialization<PhoneAccountHandle> sPhoneAccountHandleXml =
1729b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            new XmlSerialization<PhoneAccountHandle>() {
1730b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        private static final String CLASS_PHONE_ACCOUNT_HANDLE = "phone_account_handle";
1731104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        private static final String COMPONENT_NAME = "component_name";
1732104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        private static final String ID = "id";
1733105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        private static final String USER_SERIAL_NUMBER = "user_serial_number";
1734104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
1735104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        @Override
1736105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton        public void writeToXml(PhoneAccountHandle o, XmlSerializer serializer, Context context)
1737b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                throws IOException {
17382692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad            if (o != null) {
17392692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                serializer.startTag(null, CLASS_PHONE_ACCOUNT_HANDLE);
1740b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
17412692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                if (o.getComponentName() != null) {
1742d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                    writeTextIfNonNull(
17432692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                            COMPONENT_NAME, o.getComponentName().flattenToString(), serializer);
17442692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                }
1745b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
1746d9f5438b2b4595a784947b92a49406ee99de2589Ihab Awad                writeTextIfNonNull(ID, o.getId(), serializer);
1747b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
1748105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                if (o.getUserHandle() != null && context != null) {
1749105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                    UserManager userManager = UserManager.get(context);
1750105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                    writeLong(USER_SERIAL_NUMBER,
1751105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                            userManager.getSerialNumberForUser(o.getUserHandle()), serializer);
1752105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                }
1753105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
17542692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                serializer.endTag(null, CLASS_PHONE_ACCOUNT_HANDLE);
17552692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad            }
1756104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        }
1757104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad
1758104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        @Override
17598425357e131867f33587641f23a1d1a328acf139Tyler Gunn        public PhoneAccountHandle readFromXml(XmlPullParser parser, int version, Context context)
1760b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                throws IOException, XmlPullParserException {
1761b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            if (parser.getName().equals(CLASS_PHONE_ACCOUNT_HANDLE)) {
1762b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                String componentNameString = null;
1763b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                String idString = null;
1764105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                String userSerialNumberString = null;
1765b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                int outerDepth = parser.getDepth();
1766105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
1767105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                UserManager userManager = UserManager.get(context);
1768105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton
1769b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                while (XmlUtils.nextElementWithin(parser, outerDepth)) {
1770b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    if (parser.getName().equals(COMPONENT_NAME)) {
1771b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        parser.next();
1772b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        componentNameString = parser.getText();
1773b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    } else if (parser.getName().equals(ID)) {
1774b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        parser.next();
1775b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        idString = parser.getText();
1776105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                    } else if (parser.getName().equals(USER_SERIAL_NUMBER)) {
1777105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                        parser.next();
1778105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                        userSerialNumberString = parser.getText();
1779b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    }
1780b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                }
17812692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad                if (componentNameString != null) {
1782105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                    UserHandle userHandle = null;
1783105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                    if (userSerialNumberString != null) {
1784105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                        try {
1785105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                            long serialNumber = Long.parseLong(userSerialNumberString);
1786105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                            userHandle = userManager.getUserForSerialNumber(serialNumber);
1787105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                        } catch (NumberFormatException e) {
1788105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                            Log.e(this, e, "Could not parse UserHandle " + userSerialNumberString);
1789105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                        }
1790105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                    }
1791b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    return new PhoneAccountHandle(
1792b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                            ComponentName.unflattenFromString(componentNameString),
1793105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                            idString,
1794105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton                            userHandle);
1795b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                }
1796b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            }
1797b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            return null;
1798104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad        }
1799104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad    };
1800176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon}
1801