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