PhoneAccountRegistrar.java revision 1c5926fc5f3c828c5b16c25a5154e5a0306ea3e7
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; 20af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport android.content.Intent; 21af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport android.content.pm.PackageManager; 22af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport android.content.pm.ResolveInfo; 23cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunnimport android.content.pm.ServiceInfo; 2491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunnimport android.os.Environment; 2591d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunnimport android.os.UserHandle; 268425357e131867f33587641f23a1d1a328acf139Tyler Gunnimport android.provider.Settings; 277cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.ConnectionService; 287cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccount; 297cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccountHandle; 307cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.TelecomManager; 31176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordonimport android.content.ComponentName; 32176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordonimport android.content.Context; 33176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordonimport android.net.Uri; 34af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport android.text.TextUtils; 35b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport android.util.AtomicFile; 36b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport android.util.Xml; 37b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 3891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn// TODO: Needed for move to system service: import com.android.internal.R; 390e1dc5a99042dd05b94b16a41461a3632a3fe5eeSailesh Nepalimport com.android.internal.annotations.VisibleForTesting; 400e1dc5a99042dd05b94b16a41461a3632a3fe5eeSailesh Nepalimport com.android.internal.util.FastXmlSerializer; 410e1dc5a99042dd05b94b16a41461a3632a3fe5eeSailesh Nepalimport com.android.internal.util.XmlUtils; 420e1dc5a99042dd05b94b16a41461a3632a3fe5eeSailesh Nepal 43af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport org.xmlpull.v1.XmlPullParser; 44af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport org.xmlpull.v1.XmlPullParserException; 45af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charltonimport org.xmlpull.v1.XmlSerializer; 46af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton 47b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.BufferedInputStream; 48b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.BufferedOutputStream; 49b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.File; 50b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.FileNotFoundException; 51b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.FileOutputStream; 52b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.IOException; 53b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.io.InputStream; 548425357e131867f33587641f23a1d1a328acf139Tyler Gunnimport java.lang.Integer; 55cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunnimport java.lang.SecurityException; 56d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunnimport java.lang.String; 57176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordonimport java.util.ArrayList; 58afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordonimport java.util.Collections; 59d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunnimport java.util.Iterator; 60176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordonimport java.util.List; 61176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordonimport java.util.Objects; 62b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.util.concurrent.CopyOnWriteArrayList; 63176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 64176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon/** 6589176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton * Handles writing and reading PhoneAccountHandle registration entries. This is a simple verbatim 667cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn * delegate for all the account handling methods on {@link android.telecom.TelecomManager} as implemented in 677cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn * {@link TelecomServiceImpl}, with the notable exception that {@link TelecomServiceImpl} is 68104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad * responsible for security checking to make sure that the caller has proper authority over 6989176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton * the {@code ComponentName}s they are declaring in their {@code PhoneAccountHandle}s. 70176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon */ 71b78b27693afbe9736f0a54ec473328955251f885Ihab Awadpublic final class PhoneAccountRegistrar { 72176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 735e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee public static final PhoneAccountHandle NO_ACCOUNT_SELECTED = 745e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee new PhoneAccountHandle(new ComponentName("null", "null"), "NO_ACCOUNT_SELECTED"); 755e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee 76b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public abstract static class Listener { 77b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public void onAccountsChanged(PhoneAccountRegistrar registrar) {} 78b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public void onDefaultOutgoingChanged(PhoneAccountRegistrar registrar) {} 79b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public void onSimCallManagerChanged(PhoneAccountRegistrar registrar) {} 80b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 81b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 82b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private static final String FILE_NAME = "phone-account-registrar-state.xml"; 838425357e131867f33587641f23a1d1a328acf139Tyler Gunn @VisibleForTesting 848e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn public static final int EXPECTED_STATE_VERSION = 3; 858425357e131867f33587641f23a1d1a328acf139Tyler Gunn 868425357e131867f33587641f23a1d1a328acf139Tyler Gunn /** Keep in sync with the same in SipSettings.java */ 878425357e131867f33587641f23a1d1a328acf139Tyler Gunn private static final String SIP_SHARED_PREFERENCES = "SIP_PREFERENCES"; 88b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 89b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private final List<Listener> mListeners = new CopyOnWriteArrayList<>(); 90b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private final AtomicFile mAtomicFile; 91afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon private final Context mContext; 92b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private State mState; 93176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 942692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad public PhoneAccountRegistrar(Context context) { 95b78b27693afbe9736f0a54ec473328955251f885Ihab Awad this(context, FILE_NAME); 96b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 97b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 98b78b27693afbe9736f0a54ec473328955251f885Ihab Awad @VisibleForTesting 99b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public PhoneAccountRegistrar(Context context, String fileName) { 10091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn // TODO: This file path is subject to change -- it is storing the phone account registry 10191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn // state file in the path /data/system/users/0/, which is likely not correct in a 10291d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn // multi-user setting. 10391d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn /** UNCOMMENT_FOR_MOVE_TO_SYSTEM_SERVICE 10491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn String filePath = Environment.getUserSystemDirectory(UserHandle.myUserId()). 10591d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn getAbsolutePath(); 10691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn mAtomicFile = new AtomicFile(new File(filePath, fileName)); 10791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn UNCOMMENT_FOR_MOVE_TO_SYSTEM_SERVICE */ 108b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mAtomicFile = new AtomicFile(new File(context.getFilesDir(), fileName)); 10991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn 110b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mState = new State(); 111afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon mContext = context; 112b78b27693afbe9736f0a54ec473328955251f885Ihab Awad read(); 113104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 114176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 1158425357e131867f33587641f23a1d1a328acf139Tyler Gunn /** 1168425357e131867f33587641f23a1d1a328acf139Tyler Gunn * Retrieves the default outgoing phone account supporting the specified uriScheme. 1178425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @param uriScheme The URI scheme for the outgoing call. 1188425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @return The {@link PhoneAccountHandle} to use. 1198425357e131867f33587641f23a1d1a328acf139Tyler Gunn */ 1208425357e131867f33587641f23a1d1a328acf139Tyler Gunn public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) { 1215e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee final PhoneAccountHandle userSelected = getUserSelectedOutgoingPhoneAccount(); 1228425357e131867f33587641f23a1d1a328acf139Tyler Gunn 1235e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee if (userSelected != null) { 1248425357e131867f33587641f23a1d1a328acf139Tyler Gunn // If there is a default PhoneAccount, ensure it supports calls to handles with the 1258425357e131867f33587641f23a1d1a328acf139Tyler Gunn // specified uriScheme. 1268425357e131867f33587641f23a1d1a328acf139Tyler Gunn final PhoneAccount userSelectedAccount = getPhoneAccount(userSelected); 1278425357e131867f33587641f23a1d1a328acf139Tyler Gunn if (userSelectedAccount.supportsUriScheme(uriScheme)) { 1288425357e131867f33587641f23a1d1a328acf139Tyler Gunn return userSelected; 1298425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 130293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 131293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 132309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen List<PhoneAccountHandle> outgoing = getCallCapablePhoneAccounts(uriScheme); 1336fb37c87836b5245046bd3b14320823ab839a10cIhab Awad switch (outgoing.size()) { 134293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad case 0: 135293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // There are no accounts, so there can be no default 136293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad return null; 137293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad case 1: 138293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // There is only one account, which is by definition the default 1396fb37c87836b5245046bd3b14320823ab839a10cIhab Awad return outgoing.get(0); 140293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad default: 141293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // There are multiple accounts with no selected default 142293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad return null; 143f2a8491d71915c621518ac8a40bed3c2a35272a9Ihab Awad } 144104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 145104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 1465e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() { 1475e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee if (mState.defaultOutgoing != null) { 1485e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee // Return the registered outgoing default iff it still exists (we keep a sticky 1495e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee // default to survive account deletion and re-addition) 1505e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee for (int i = 0; i < mState.accounts.size(); i++) { 1515e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee if (mState.accounts.get(i).getAccountHandle().equals(mState.defaultOutgoing)) { 1525e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee return mState.defaultOutgoing; 1535e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee } 1545e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee } 1555e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee // At this point, there was a registered default but it has been deleted; proceed 1565e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee // as though there were no default 1575e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee } 1585e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee return null; 1595e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee } 1605e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee 161a51a386c818d3e4116b38b68daf588e2ab5e0499Andrew Lee public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) { 16289176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton if (accountHandle == null) { 163104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad // Asking to clear the default outgoing is a valid request 164293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mState.defaultOutgoing = null; 165104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } else { 166104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad boolean found = false; 167293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad for (PhoneAccount m : mState.accounts) { 16894d01629010a61f6112713f22330d5fd4baae851Evan Charlton if (Objects.equals(accountHandle, m.getAccountHandle())) { 169104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad found = true; 170104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad break; 171104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 172104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 173104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 174104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad if (!found) { 175b78b27693afbe9736f0a54ec473328955251f885Ihab Awad Log.w(this, "Trying to set nonexistent default outgoing %s", 176b78b27693afbe9736f0a54ec473328955251f885Ihab Awad accountHandle); 177b78b27693afbe9736f0a54ec473328955251f885Ihab Awad return; 178b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 179b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 1808e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn if (!getPhoneAccount(accountHandle).hasCapabilities( 1818e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn PhoneAccount.CAPABILITY_CALL_PROVIDER)) { 182b78b27693afbe9736f0a54ec473328955251f885Ihab Awad Log.w(this, "Trying to set non-call-provider default outgoing %s", 18389176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton accountHandle); 184104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad return; 185104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 186104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 187293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mState.defaultOutgoing = accountHandle; 188293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 189293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 190293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad write(); 191b78b27693afbe9736f0a54ec473328955251f885Ihab Awad fireDefaultOutgoingChanged(); 192293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 193293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 194293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public void setSimCallManager(PhoneAccountHandle callManager) { 195293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad if (callManager != null) { 196293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad PhoneAccount callManagerAccount = getPhoneAccount(callManager); 197293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad if (callManagerAccount == null) { 198293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad Log.d(this, "setSimCallManager: Nonexistent call manager: %s", callManager); 199293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad return; 2008e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn } else if (!callManagerAccount.hasCapabilities( 2018e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn PhoneAccount.CAPABILITY_CONNECTION_MANAGER)) { 202293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad Log.d(this, "setSimCallManager: Not a call manager: %s", callManagerAccount); 203293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad return; 204293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 2055e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee } else { 2065e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee callManager = NO_ACCOUNT_SELECTED; 207293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 208293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mState.simCallManager = callManager; 2095e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee 210293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad write(); 211b78b27693afbe9736f0a54ec473328955251f885Ihab Awad fireSimCallManagerChanged(); 212293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 213293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 214293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public PhoneAccountHandle getSimCallManager() { 215b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (mState.simCallManager != null) { 2165e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee if (NO_ACCOUNT_SELECTED.equals(mState.simCallManager)) { 2175e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee return null; 2185e8836a73b8db1529308867d5a41145cb16cbfb0Yorke Lee } 219b78b27693afbe9736f0a54ec473328955251f885Ihab Awad // Return the registered sim call manager iff it still exists (we keep a sticky 220b78b27693afbe9736f0a54ec473328955251f885Ihab Awad // setting to survive account deletion and re-addition) 221b78b27693afbe9736f0a54ec473328955251f885Ihab Awad for (int i = 0; i < mState.accounts.size(); i++) { 222b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (mState.accounts.get(i).getAccountHandle().equals(mState.simCallManager)) { 223b78b27693afbe9736f0a54ec473328955251f885Ihab Awad return mState.simCallManager; 224b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 225b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 226b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 227af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton 228af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton // See if the OEM has specified a default one. 229af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton String defaultConnectionMgr = 230afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon mContext.getResources().getString(R.string.default_connection_manager_component); 231af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton if (!TextUtils.isEmpty(defaultConnectionMgr)) { 232afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon PackageManager pm = mContext.getPackageManager(); 233af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton 234af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton ComponentName componentName = ComponentName.unflattenFromString(defaultConnectionMgr); 235af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton Intent intent = new Intent(ConnectionService.SERVICE_INTERFACE); 236af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton intent.setComponent(componentName); 237af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton 238af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton // Make sure that the component can be resolved. 239af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton List<ResolveInfo> resolveInfos = pm.queryIntentServices(intent, 0); 240af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton if (!resolveInfos.isEmpty()) { 241af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton // See if there is registered PhoneAccount by this component. 242af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton List<PhoneAccountHandle> handles = getAllPhoneAccountHandles(); 243af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton for (PhoneAccountHandle handle : handles) { 244af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton if (componentName.equals(handle.getComponentName())) { 245af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton return handle; 246af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton } 247af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton } 248af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton Log.d(this, "%s does not have a PhoneAccount; not using as default", componentName); 249af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton } else { 250af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton Log.d(this, "%s could not be resolved; not using as default", componentName); 251af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton } 252af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton } else { 253af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton Log.v(this, "No default connection manager specified"); 254af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton } 255af51ceb458f94b9a179145f222ae4ea84951e8beEvan Charlton 256b78b27693afbe9736f0a54ec473328955251f885Ihab Awad return null; 257293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 258293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 2598e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn /** 2608e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * Retrieves a list of all {@link PhoneAccountHandle}s registered. 2618e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * 2628e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * @return The list of {@link PhoneAccountHandle}s. 2638e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn */ 264293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public List<PhoneAccountHandle> getAllPhoneAccountHandles() { 265293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad List<PhoneAccountHandle> accountHandles = new ArrayList<>(); 266293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad for (PhoneAccount m : mState.accounts) { 267293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad accountHandles.add(m.getAccountHandle()); 268176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 269293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad return accountHandles; 270293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 271104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 272293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public List<PhoneAccount> getAllPhoneAccounts() { 273293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad return new ArrayList<>(mState.accounts); 274176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 275176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 2768e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn /** 277309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen * Determines the number of all {@link PhoneAccount}s. 2788e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * 279309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen * @return The total number {@link PhoneAccount}s. 2808e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn */ 2818e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn public int getAllPhoneAccountsCount() { 2828e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn return mState.accounts.size(); 2838e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn } 2848e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn 2858e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn /** 286309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen * Retrieves a list of all call provider phone accounts. 2878e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * 2888e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * @return The phone account handles. 2898e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn */ 290309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen public List<PhoneAccountHandle> getCallCapablePhoneAccounts() { 291afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CALL_PROVIDER); 292afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon } 293afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon 2948e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn /** 295309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen * Retrieves a list of all phone account call provider phone accounts supporting the 2968e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * specified URI scheme. 2978e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * 2988e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * @param uriScheme The URI scheme. 2998e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * @return The phone account handles. 3008e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn */ 301309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen public List<PhoneAccountHandle> getCallCapablePhoneAccounts(String uriScheme) { 302309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CALL_PROVIDER, uriScheme); 3038425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 3048425357e131867f33587641f23a1d1a328acf139Tyler Gunn 3058e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn /** 3061c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen * Retrieves a list of all phone accounts registered by a specified package. 3071c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen * 3081c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen * @param packageName The name of the package that registered the phone accounts. 3091c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen * @return The phone account handles. 3101c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen */ 3111c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen public List<PhoneAccountHandle> getPhoneAccountsForPackage(String packageName) { 3121c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen List<PhoneAccountHandle> accountHandles = new ArrayList<>(); 3131c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen for (PhoneAccount m : mState.accounts) { 3141c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen if (Objects.equals( 3151c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen packageName, 3161c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen m.getAccountHandle().getComponentName().getPackageName())) { 3171c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen accountHandles.add(m.getAccountHandle()); 3181c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen } 3191c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen } 3201c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen return accountHandles; 3211c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen } 3221c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen 3231c5926fc5f3c828c5b16c25a5154e5a0306ea3e7Nancy Chen /** 324309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen * Retrieves a list of all phone account handles with the connection manager capability. 3258e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * 3268e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * @return The phone account handles. 3278e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn */ 3288e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn public List<PhoneAccountHandle> getConnectionManagerPhoneAccounts() { 329e3d8245f09c9d5333ebc7e2d82e684ecfeb6040eSantos Cordon return getPhoneAccountHandles(PhoneAccount.CAPABILITY_CONNECTION_MANAGER, 330309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen null /* supportedUriScheme */); 331176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 332176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 333293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public PhoneAccount getPhoneAccount(PhoneAccountHandle handle) { 334293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad for (PhoneAccount m : mState.accounts) { 335293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad if (Objects.equals(handle, m.getAccountHandle())) { 336104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad return m; 337104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 338104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 339104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad return null; 340104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 341176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 342104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad // TODO: Should we implement an artificial limit for # of accounts associated with a single 343104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad // ComponentName? 344293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public void registerPhoneAccount(PhoneAccount account) { 345cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn // Enforce the requirement that a connection service for a phone account has the correct 346cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn // permission. 347cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn if (!phoneAccountHasPermission(account.getAccountHandle())) { 348cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn Log.w(this, "Phone account %s does not have BIND_CONNECTION_SERVICE permission.", 349cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn account.getAccountHandle()); 350cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn throw new SecurityException( 351cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn "PhoneAccount connection service requires BIND_CONNECTION_SERVICE permission."); 352cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn } 353cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn 3548e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn addOrReplacePhoneAccount(account); 3558e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn } 3568e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn 3578e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn /** 3588e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * Adds a {@code PhoneAccount}, replacing an existing one if found. 3598e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * 3608e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn * @param account The {@code PhoneAccount} to add or replace. 3618e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn */ 3628e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn private void addOrReplacePhoneAccount(PhoneAccount account) { 363293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mState.accounts.add(account); 364176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon // Search for duplicates and remove any that are found. 365293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad for (int i = 0; i < mState.accounts.size() - 1; i++) { 366293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad if (Objects.equals( 367293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad account.getAccountHandle(), mState.accounts.get(i).getAccountHandle())) { 368176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon // replace existing entry. 369293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mState.accounts.remove(i); 370176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon break; 371176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 372176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 373176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 374293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad write(); 375b78b27693afbe9736f0a54ec473328955251f885Ihab Awad fireAccountsChanged(); 376176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 377176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 378293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) { 379293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad for (int i = 0; i < mState.accounts.size(); i++) { 380293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad if (Objects.equals(accountHandle, mState.accounts.get(i).getAccountHandle())) { 381293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mState.accounts.remove(i); 382104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad break; 383176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 384176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 385176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 386293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad write(); 387b78b27693afbe9736f0a54ec473328955251f885Ihab Awad fireAccountsChanged(); 388176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 389176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 390d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn /** 391d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn * Un-registers all phone accounts associated with a specified package. 392d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn * 393d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn * @param packageName The package for which phone accounts will be removed. 394d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn */ 395104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad public void clearAccounts(String packageName) { 396d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn boolean accountsRemoved = false; 397d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn Iterator<PhoneAccount> it = mState.accounts.iterator(); 398d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn while (it.hasNext()) { 399d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn PhoneAccount phoneAccount = it.next(); 400104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad if (Objects.equals( 401104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad packageName, 402d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn phoneAccount.getAccountHandle().getComponentName().getPackageName())) { 403d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn Log.i(this, "Removing phone account " + phoneAccount.getLabel()); 404d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn it.remove(); 405d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn accountsRemoved = true; 406176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 407176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 408176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 409d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn if (accountsRemoved) { 410d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn write(); 411d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn fireAccountsChanged(); 412d900ce6021fe457c97f1e8d82374bf30b08f2ee5Tyler Gunn } 413b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 414b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 415b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public void addListener(Listener l) { 416b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mListeners.add(l); 417b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 418b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 419b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public void removeListener(Listener l) { 420a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner if (l != null) { 421a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner mListeners.remove(l); 422a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner } 423b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 424b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 425b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private void fireAccountsChanged() { 426b78b27693afbe9736f0a54ec473328955251f885Ihab Awad for (Listener l : mListeners) { 427b78b27693afbe9736f0a54ec473328955251f885Ihab Awad l.onAccountsChanged(this); 428b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 429b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 430b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 431b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private void fireDefaultOutgoingChanged() { 432b78b27693afbe9736f0a54ec473328955251f885Ihab Awad for (Listener l : mListeners) { 433b78b27693afbe9736f0a54ec473328955251f885Ihab Awad l.onDefaultOutgoingChanged(this); 434b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 435b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 436b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 437b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private void fireSimCallManagerChanged() { 438b78b27693afbe9736f0a54ec473328955251f885Ihab Awad for (Listener l : mListeners) { 439b78b27693afbe9736f0a54ec473328955251f885Ihab Awad l.onSimCallManagerChanged(this); 440b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 441293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 442293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 443cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn /** 444cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn * Determines if the connection service specified by a {@link PhoneAccountHandle} has the 445cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn * {@link Manifest.permission#BIND_CONNECTION_SERVICE} permission. 446cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn * 447cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn * @param phoneAccountHandle The phone account to check. 448cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn * @return {@code True} if the phone account has permission. 449cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn */ 450cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn public boolean phoneAccountHasPermission(PhoneAccountHandle phoneAccountHandle) { 45191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn PackageManager packageManager = mContext.getPackageManager(); 452cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn try { 453cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn ServiceInfo serviceInfo = packageManager.getServiceInfo( 454cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn phoneAccountHandle.getComponentName(), 0); 455cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn 456cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn return serviceInfo.permission != null && 457cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn serviceInfo.permission.equals(Manifest.permission.BIND_CONNECTION_SERVICE); 458cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn } catch (PackageManager.NameNotFoundException e) { 459cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn Log.w(this, "Name not found %s", e); 460cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn return false; 461cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn } 462cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn } 463cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn 464293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad //////////////////////////////////////////////////////////////////////////////////////////////// 465293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 466afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon /** 467afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon * Returns a list of phone account handles with the specified flag. 4688425357e131867f33587641f23a1d1a328acf139Tyler Gunn * 4698425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @param flags Flags which the {@code PhoneAccount} must have. 470afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon */ 471afe59e5194e394922819eacc1b2ee12754479bf4Santos Cordon private List<PhoneAccountHandle> getPhoneAccountHandles(int flags) { 472309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen return getPhoneAccountHandles(flags, null); 4738425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 4748425357e131867f33587641f23a1d1a328acf139Tyler Gunn 4758425357e131867f33587641f23a1d1a328acf139Tyler Gunn /** 4768425357e131867f33587641f23a1d1a328acf139Tyler Gunn * Returns a list of phone account handles with the specified flag, supporting the specified 477309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen * URI scheme. 4788425357e131867f33587641f23a1d1a328acf139Tyler Gunn * 4798425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @param flags Flags which the {@code PhoneAccount} must have. 4808425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @param uriScheme URI schemes the PhoneAccount must handle. {@code Null} bypasses the 4818425357e131867f33587641f23a1d1a328acf139Tyler Gunn * URI scheme check. 4828425357e131867f33587641f23a1d1a328acf139Tyler Gunn */ 483309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen private List<PhoneAccountHandle> getPhoneAccountHandles(int flags, String uriScheme) { 48494d01629010a61f6112713f22330d5fd4baae851Evan Charlton List<PhoneAccountHandle> accountHandles = new ArrayList<>(); 485293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad for (PhoneAccount m : mState.accounts) { 486309198ec4d8b2738cf955316ea7a2f9418929fd1Nancy Chen if (m.hasCapabilities(flags) && (uriScheme == null || m.supportsUriScheme(uriScheme))) { 487f2a8491d71915c621518ac8a40bed3c2a35272a9Ihab Awad accountHandles.add(m.getAccountHandle()); 488f2a8491d71915c621518ac8a40bed3c2a35272a9Ihab Awad } 489104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 49094d01629010a61f6112713f22330d5fd4baae851Evan Charlton return accountHandles; 491104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 492176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 493293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad /** 494293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad * The state of this {@code PhoneAccountRegistrar}. 495293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad */ 496b78b27693afbe9736f0a54ec473328955251f885Ihab Awad @VisibleForTesting 497b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public static class State { 498293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad /** 499293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad * The account selected by the user to be employed by default for making outgoing calls. 500293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad * If the user has not made such a selection, then this is null. 501293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad */ 502293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public PhoneAccountHandle defaultOutgoing = null; 503293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 504293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad /** 505b78b27693afbe9736f0a54ec473328955251f885Ihab Awad * A {@code PhoneAccount} having {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} which 506293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad * manages and optimizes a user's PSTN SIM connections. 507293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad */ 508293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public PhoneAccountHandle simCallManager; 509293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 510293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad /** 5117cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn * The complete list of {@code PhoneAccount}s known to the Telecom subsystem. 512293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad */ 513293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public final List<PhoneAccount> accounts = new ArrayList<>(); 5148425357e131867f33587641f23a1d1a328acf139Tyler Gunn 5158425357e131867f33587641f23a1d1a328acf139Tyler Gunn /** 5168425357e131867f33587641f23a1d1a328acf139Tyler Gunn * The version number of the State data. 5178425357e131867f33587641f23a1d1a328acf139Tyler Gunn */ 5188425357e131867f33587641f23a1d1a328acf139Tyler Gunn public int versionNumber; 519293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 520293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 521293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad //////////////////////////////////////////////////////////////////////////////////////////////// 522293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // 523293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // State management 524293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // 525293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 526293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private void write() { 527b78b27693afbe9736f0a54ec473328955251f885Ihab Awad final FileOutputStream os; 528104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad try { 529b78b27693afbe9736f0a54ec473328955251f885Ihab Awad os = mAtomicFile.startWrite(); 530b78b27693afbe9736f0a54ec473328955251f885Ihab Awad boolean success = false; 531b78b27693afbe9736f0a54ec473328955251f885Ihab Awad try { 532b78b27693afbe9736f0a54ec473328955251f885Ihab Awad XmlSerializer serializer = new FastXmlSerializer(); 533b78b27693afbe9736f0a54ec473328955251f885Ihab Awad serializer.setOutput(new BufferedOutputStream(os), "utf-8"); 534b78b27693afbe9736f0a54ec473328955251f885Ihab Awad writeToXml(mState, serializer); 535b78b27693afbe9736f0a54ec473328955251f885Ihab Awad serializer.flush(); 536b78b27693afbe9736f0a54ec473328955251f885Ihab Awad success = true; 537b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } finally { 538b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (success) { 539b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mAtomicFile.finishWrite(os); 540b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } else { 541b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mAtomicFile.failWrite(os); 542b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 543b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 544b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } catch (IOException e) { 545b78b27693afbe9736f0a54ec473328955251f885Ihab Awad Log.e(this, e, "Writing state to XML file"); 546176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 547104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 548176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 549b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private void read() { 550b78b27693afbe9736f0a54ec473328955251f885Ihab Awad final InputStream is; 551104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad try { 552b78b27693afbe9736f0a54ec473328955251f885Ihab Awad is = mAtomicFile.openRead(); 553b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } catch (FileNotFoundException ex) { 554b78b27693afbe9736f0a54ec473328955251f885Ihab Awad return; 555104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 556176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 5578425357e131867f33587641f23a1d1a328acf139Tyler Gunn boolean versionChanged = false; 5588425357e131867f33587641f23a1d1a328acf139Tyler Gunn 559b78b27693afbe9736f0a54ec473328955251f885Ihab Awad XmlPullParser parser; 560b78b27693afbe9736f0a54ec473328955251f885Ihab Awad try { 561b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser = Xml.newPullParser(); 562b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.setInput(new BufferedInputStream(is), null); 563b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.nextTag(); 5648425357e131867f33587641f23a1d1a328acf139Tyler Gunn mState = readFromXml(parser, mContext); 5658425357e131867f33587641f23a1d1a328acf139Tyler Gunn versionChanged = mState.versionNumber < EXPECTED_STATE_VERSION; 5668425357e131867f33587641f23a1d1a328acf139Tyler Gunn 567b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } catch (IOException | XmlPullParserException e) { 568b78b27693afbe9736f0a54ec473328955251f885Ihab Awad Log.e(this, e, "Reading state from XML file"); 569b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mState = new State(); 570b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } finally { 571b78b27693afbe9736f0a54ec473328955251f885Ihab Awad try { 572b78b27693afbe9736f0a54ec473328955251f885Ihab Awad is.close(); 573b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } catch (IOException e) { 574b78b27693afbe9736f0a54ec473328955251f885Ihab Awad Log.e(this, e, "Closing InputStream"); 575b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 576b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 5778425357e131867f33587641f23a1d1a328acf139Tyler Gunn 5788425357e131867f33587641f23a1d1a328acf139Tyler Gunn // If an upgrade occurred, write out the changed data. 5798425357e131867f33587641f23a1d1a328acf139Tyler Gunn if (versionChanged) { 5808425357e131867f33587641f23a1d1a328acf139Tyler Gunn write(); 5818425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 582176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 583176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 584b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private static void writeToXml(State state, XmlSerializer serializer) 585b78b27693afbe9736f0a54ec473328955251f885Ihab Awad throws IOException { 586b78b27693afbe9736f0a54ec473328955251f885Ihab Awad sStateXml.writeToXml(state, serializer); 587176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 588176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 5898425357e131867f33587641f23a1d1a328acf139Tyler Gunn private static State readFromXml(XmlPullParser parser, Context context) 590b78b27693afbe9736f0a54ec473328955251f885Ihab Awad throws IOException, XmlPullParserException { 5918425357e131867f33587641f23a1d1a328acf139Tyler Gunn State s = sStateXml.readFromXml(parser, 0, context); 592b78b27693afbe9736f0a54ec473328955251f885Ihab Awad return s != null ? s : new State(); 593176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 594176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon 595293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad //////////////////////////////////////////////////////////////////////////////////////////////// 596104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad // 597b78b27693afbe9736f0a54ec473328955251f885Ihab Awad // XML serialization 598104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad // 599104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 600b78b27693afbe9736f0a54ec473328955251f885Ihab Awad @VisibleForTesting 6012692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad public abstract static class XmlSerialization<T> { 6028425357e131867f33587641f23a1d1a328acf139Tyler Gunn private static final String LENGTH_ATTRIBUTE = "length"; 6038425357e131867f33587641f23a1d1a328acf139Tyler Gunn private static final String VALUE_TAG = "value"; 6048425357e131867f33587641f23a1d1a328acf139Tyler Gunn 605b78b27693afbe9736f0a54ec473328955251f885Ihab Awad /** 606b78b27693afbe9736f0a54ec473328955251f885Ihab Awad * Write the supplied object to XML 607b78b27693afbe9736f0a54ec473328955251f885Ihab Awad */ 6082692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad public abstract void writeToXml(T o, XmlSerializer serializer) 6092692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad throws IOException; 610b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 611b78b27693afbe9736f0a54ec473328955251f885Ihab Awad /** 612b78b27693afbe9736f0a54ec473328955251f885Ihab Awad * Read from the supplied XML into a new object, returning null in case of an 613b78b27693afbe9736f0a54ec473328955251f885Ihab Awad * unrecoverable schema mismatch or other data error. 'parser' must be already 614b78b27693afbe9736f0a54ec473328955251f885Ihab Awad * positioned at the first tag that is expected to have been emitted by this 615b78b27693afbe9736f0a54ec473328955251f885Ihab Awad * object's writeToXml(). This object tries to fail early without modifying 616b78b27693afbe9736f0a54ec473328955251f885Ihab Awad * 'parser' if it does not recognize the data it sees. 617b78b27693afbe9736f0a54ec473328955251f885Ihab Awad */ 6188425357e131867f33587641f23a1d1a328acf139Tyler Gunn public abstract T readFromXml(XmlPullParser parser, int version, Context context) 6192692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad throws IOException, XmlPullParserException; 6202692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad 6212692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad protected void writeTextSafely(String tagName, Object value, XmlSerializer serializer) 6222692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad throws IOException { 6232692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad if (value != null) { 6242692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.startTag(null, tagName); 6252692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.text(Objects.toString(value)); 6262692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.endTag(null, tagName); 6272692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad } 6282692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad } 6298425357e131867f33587641f23a1d1a328acf139Tyler Gunn 6308425357e131867f33587641f23a1d1a328acf139Tyler Gunn /** 6318425357e131867f33587641f23a1d1a328acf139Tyler Gunn * Serializes a string array. 6328425357e131867f33587641f23a1d1a328acf139Tyler Gunn * 6338425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @param tagName The tag name for the string array. 6348425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @param values The string values to serialize. 6358425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @param serializer The serializer. 6368425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @throws IOException 6378425357e131867f33587641f23a1d1a328acf139Tyler Gunn */ 6388425357e131867f33587641f23a1d1a328acf139Tyler Gunn protected void writeStringList(String tagName, List<String> values, 6398425357e131867f33587641f23a1d1a328acf139Tyler Gunn XmlSerializer serializer) 6408425357e131867f33587641f23a1d1a328acf139Tyler Gunn throws IOException { 6418425357e131867f33587641f23a1d1a328acf139Tyler Gunn 6428425357e131867f33587641f23a1d1a328acf139Tyler Gunn serializer.startTag(null, tagName); 6438425357e131867f33587641f23a1d1a328acf139Tyler Gunn if (values != null) { 6448425357e131867f33587641f23a1d1a328acf139Tyler Gunn serializer.attribute(null, LENGTH_ATTRIBUTE, Objects.toString(values.size())); 6458425357e131867f33587641f23a1d1a328acf139Tyler Gunn for (String toSerialize : values) { 6468425357e131867f33587641f23a1d1a328acf139Tyler Gunn serializer.startTag(null, VALUE_TAG); 6478425357e131867f33587641f23a1d1a328acf139Tyler Gunn if (toSerialize != null ){ 6488425357e131867f33587641f23a1d1a328acf139Tyler Gunn serializer.text(toSerialize); 6498425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 6508425357e131867f33587641f23a1d1a328acf139Tyler Gunn serializer.endTag(null, VALUE_TAG); 6518425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 6528425357e131867f33587641f23a1d1a328acf139Tyler Gunn } else { 6538425357e131867f33587641f23a1d1a328acf139Tyler Gunn serializer.attribute(null, LENGTH_ATTRIBUTE, "0"); 6548425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 6558425357e131867f33587641f23a1d1a328acf139Tyler Gunn serializer.endTag(null, tagName); 6568425357e131867f33587641f23a1d1a328acf139Tyler Gunn 6578425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 6588425357e131867f33587641f23a1d1a328acf139Tyler Gunn 6598425357e131867f33587641f23a1d1a328acf139Tyler Gunn /** 6608425357e131867f33587641f23a1d1a328acf139Tyler Gunn * Reads a string array from the XML parser. 6618425357e131867f33587641f23a1d1a328acf139Tyler Gunn * 6628425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @param parser The XML parser. 6638425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @return String array containing the parsed values. 6648425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @throws IOException Exception related to IO. 6658425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @throws XmlPullParserException Exception related to parsing. 6668425357e131867f33587641f23a1d1a328acf139Tyler Gunn */ 6678425357e131867f33587641f23a1d1a328acf139Tyler Gunn protected List<String> readStringList(XmlPullParser parser) 6688425357e131867f33587641f23a1d1a328acf139Tyler Gunn throws IOException, XmlPullParserException { 6698425357e131867f33587641f23a1d1a328acf139Tyler Gunn 6708425357e131867f33587641f23a1d1a328acf139Tyler Gunn int length = Integer.parseInt(parser.getAttributeValue(null, LENGTH_ATTRIBUTE)); 6718425357e131867f33587641f23a1d1a328acf139Tyler Gunn List<String> arrayEntries = new ArrayList<String>(length); 6728425357e131867f33587641f23a1d1a328acf139Tyler Gunn String value = null; 6738425357e131867f33587641f23a1d1a328acf139Tyler Gunn 6748425357e131867f33587641f23a1d1a328acf139Tyler Gunn if (length == 0) { 6758425357e131867f33587641f23a1d1a328acf139Tyler Gunn return arrayEntries; 6768425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 6778425357e131867f33587641f23a1d1a328acf139Tyler Gunn 6788425357e131867f33587641f23a1d1a328acf139Tyler Gunn int outerDepth = parser.getDepth(); 6798425357e131867f33587641f23a1d1a328acf139Tyler Gunn while (XmlUtils.nextElementWithin(parser, outerDepth)) { 6808425357e131867f33587641f23a1d1a328acf139Tyler Gunn if (parser.getName().equals(VALUE_TAG)) { 6818e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn parser.next(); 6828425357e131867f33587641f23a1d1a328acf139Tyler Gunn value = parser.getText(); 6838425357e131867f33587641f23a1d1a328acf139Tyler Gunn arrayEntries.add(value); 6848425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 6858425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 6868425357e131867f33587641f23a1d1a328acf139Tyler Gunn 6878425357e131867f33587641f23a1d1a328acf139Tyler Gunn return arrayEntries; 6888425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 689176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon } 690104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 691b78b27693afbe9736f0a54ec473328955251f885Ihab Awad @VisibleForTesting 692b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public static final XmlSerialization<State> sStateXml = 693b78b27693afbe9736f0a54ec473328955251f885Ihab Awad new XmlSerialization<State>() { 694b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private static final String CLASS_STATE = "phone_account_registrar_state"; 695104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad private static final String DEFAULT_OUTGOING = "default_outgoing"; 696293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private static final String SIM_CALL_MANAGER = "sim_call_manager"; 697104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad private static final String ACCOUNTS = "accounts"; 6988425357e131867f33587641f23a1d1a328acf139Tyler Gunn private static final String VERSION = "version"; 699104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 700104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad @Override 701b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public void writeToXml(State o, XmlSerializer serializer) 702b78b27693afbe9736f0a54ec473328955251f885Ihab Awad throws IOException { 7032692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad if (o != null) { 7042692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.startTag(null, CLASS_STATE); 7058425357e131867f33587641f23a1d1a328acf139Tyler Gunn serializer.attribute(null, VERSION, Objects.toString(EXPECTED_STATE_VERSION)); 706b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 7072692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad if (o.defaultOutgoing != null) { 7082692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.startTag(null, DEFAULT_OUTGOING); 7092692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad sPhoneAccountHandleXml.writeToXml(o.defaultOutgoing, serializer); 7102692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.endTag(null, DEFAULT_OUTGOING); 7112692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad } 712b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 7132692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad if (o.simCallManager != null) { 7142692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.startTag(null, SIM_CALL_MANAGER); 7152692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad sPhoneAccountHandleXml.writeToXml(o.simCallManager, serializer); 7162692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.endTag(null, SIM_CALL_MANAGER); 7172692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad } 718b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 7192692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.startTag(null, ACCOUNTS); 7202692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad for (PhoneAccount m : o.accounts) { 7212692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad sPhoneAccountXml.writeToXml(m, serializer); 7222692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad } 7232692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.endTag(null, ACCOUNTS); 724b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 7252692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.endTag(null, CLASS_STATE); 7262692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad } 727104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 728104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 729104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad @Override 7308425357e131867f33587641f23a1d1a328acf139Tyler Gunn public State readFromXml(XmlPullParser parser, int version, Context context) 731b78b27693afbe9736f0a54ec473328955251f885Ihab Awad throws IOException, XmlPullParserException { 732b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (parser.getName().equals(CLASS_STATE)) { 733b78b27693afbe9736f0a54ec473328955251f885Ihab Awad State s = new State(); 7348425357e131867f33587641f23a1d1a328acf139Tyler Gunn 7358425357e131867f33587641f23a1d1a328acf139Tyler Gunn String rawVersion = parser.getAttributeValue(null, VERSION); 7368425357e131867f33587641f23a1d1a328acf139Tyler Gunn s.versionNumber = TextUtils.isEmpty(rawVersion) ? 1 : 7378425357e131867f33587641f23a1d1a328acf139Tyler Gunn Integer.parseInt(rawVersion); 7388425357e131867f33587641f23a1d1a328acf139Tyler Gunn 739b78b27693afbe9736f0a54ec473328955251f885Ihab Awad int outerDepth = parser.getDepth(); 740b78b27693afbe9736f0a54ec473328955251f885Ihab Awad while (XmlUtils.nextElementWithin(parser, outerDepth)) { 741b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (parser.getName().equals(DEFAULT_OUTGOING)) { 742b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.nextTag(); 7438425357e131867f33587641f23a1d1a328acf139Tyler Gunn s.defaultOutgoing = sPhoneAccountHandleXml.readFromXml(parser, 7448425357e131867f33587641f23a1d1a328acf139Tyler Gunn s.versionNumber, context); 745b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } else if (parser.getName().equals(SIM_CALL_MANAGER)) { 746b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.nextTag(); 7478425357e131867f33587641f23a1d1a328acf139Tyler Gunn s.simCallManager = sPhoneAccountHandleXml.readFromXml(parser, 7488425357e131867f33587641f23a1d1a328acf139Tyler Gunn s.versionNumber, context); 749b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } else if (parser.getName().equals(ACCOUNTS)) { 750b78b27693afbe9736f0a54ec473328955251f885Ihab Awad int accountsDepth = parser.getDepth(); 751b78b27693afbe9736f0a54ec473328955251f885Ihab Awad while (XmlUtils.nextElementWithin(parser, accountsDepth)) { 7528425357e131867f33587641f23a1d1a328acf139Tyler Gunn PhoneAccount account = sPhoneAccountXml.readFromXml(parser, 7538425357e131867f33587641f23a1d1a328acf139Tyler Gunn s.versionNumber, context); 7548425357e131867f33587641f23a1d1a328acf139Tyler Gunn 7558425357e131867f33587641f23a1d1a328acf139Tyler Gunn if (account != null && s.accounts != null) { 756b78b27693afbe9736f0a54ec473328955251f885Ihab Awad s.accounts.add(account); 757b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 758b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 759104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 760104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 761b78b27693afbe9736f0a54ec473328955251f885Ihab Awad return s; 762104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 763b78b27693afbe9736f0a54ec473328955251f885Ihab Awad return null; 764104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 765104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad }; 766104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 767b78b27693afbe9736f0a54ec473328955251f885Ihab Awad @VisibleForTesting 768b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public static final XmlSerialization<PhoneAccount> sPhoneAccountXml = 769b78b27693afbe9736f0a54ec473328955251f885Ihab Awad new XmlSerialization<PhoneAccount>() { 770b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private static final String CLASS_PHONE_ACCOUNT = "phone_account"; 771b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private static final String ACCOUNT_HANDLE = "account_handle"; 7727129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee private static final String ADDRESS = "handle"; 7737129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee private static final String SUBSCRIPTION_ADDRESS = "subscription_number"; 774104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad private static final String CAPABILITIES = "capabilities"; 775104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad private static final String ICON_RES_ID = "icon_res_id"; 776104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad private static final String LABEL = "label"; 777104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad private static final String SHORT_DESCRIPTION = "short_description"; 7788425357e131867f33587641f23a1d1a328acf139Tyler Gunn private static final String SUPPORTED_URI_SCHEMES = "supported_uri_schemes"; 7798e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn private static final String TRUE = "true"; 7808e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn private static final String FALSE = "false"; 781104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 782104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad @Override 783b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public void writeToXml(PhoneAccount o, XmlSerializer serializer) 784b78b27693afbe9736f0a54ec473328955251f885Ihab Awad throws IOException { 7852692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad if (o != null) { 7862692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.startTag(null, CLASS_PHONE_ACCOUNT); 787b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 7882692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad if (o.getAccountHandle() != null) { 7892692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.startTag(null, ACCOUNT_HANDLE); 7902692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad sPhoneAccountHandleXml.writeToXml(o.getAccountHandle(), serializer); 7912692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.endTag(null, ACCOUNT_HANDLE); 7922692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad } 793b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 7947129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee writeTextSafely(ADDRESS, o.getAddress(), serializer); 7957129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee writeTextSafely(SUBSCRIPTION_ADDRESS, o.getSubscriptionAddress(), serializer); 7962692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad writeTextSafely(CAPABILITIES, Integer.toString(o.getCapabilities()), serializer); 7972692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad writeTextSafely(ICON_RES_ID, Integer.toString(o.getIconResId()), serializer); 7982692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad writeTextSafely(LABEL, o.getLabel(), serializer); 7992692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad writeTextSafely(SHORT_DESCRIPTION, o.getShortDescription(), serializer); 8008425357e131867f33587641f23a1d1a328acf139Tyler Gunn writeStringList(SUPPORTED_URI_SCHEMES, o.getSupportedUriSchemes(), serializer); 801b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 8022692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.endTag(null, CLASS_PHONE_ACCOUNT); 8032692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad } 804104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 805104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 8068425357e131867f33587641f23a1d1a328acf139Tyler Gunn public PhoneAccount readFromXml(XmlPullParser parser, int version, Context context) 807b78b27693afbe9736f0a54ec473328955251f885Ihab Awad throws IOException, XmlPullParserException { 808b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (parser.getName().equals(CLASS_PHONE_ACCOUNT)) { 809b78b27693afbe9736f0a54ec473328955251f885Ihab Awad int outerDepth = parser.getDepth(); 810b78b27693afbe9736f0a54ec473328955251f885Ihab Awad PhoneAccountHandle accountHandle = null; 8117129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee Uri address = null; 8127129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee Uri subscriptionAddress = null; 813b78b27693afbe9736f0a54ec473328955251f885Ihab Awad int capabilities = 0; 814b78b27693afbe9736f0a54ec473328955251f885Ihab Awad int iconResId = 0; 815b78b27693afbe9736f0a54ec473328955251f885Ihab Awad String label = null; 816b78b27693afbe9736f0a54ec473328955251f885Ihab Awad String shortDescription = null; 8178425357e131867f33587641f23a1d1a328acf139Tyler Gunn List<String> supportedUriSchemes = null; 818b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 819b78b27693afbe9736f0a54ec473328955251f885Ihab Awad while (XmlUtils.nextElementWithin(parser, outerDepth)) { 820b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (parser.getName().equals(ACCOUNT_HANDLE)) { 821b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.nextTag(); 8228425357e131867f33587641f23a1d1a328acf139Tyler Gunn accountHandle = sPhoneAccountHandleXml.readFromXml(parser, version, 8238425357e131867f33587641f23a1d1a328acf139Tyler Gunn context); 8247129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee } else if (parser.getName().equals(ADDRESS)) { 825b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.next(); 8267129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee address = Uri.parse(parser.getText()); 8277129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee } else if (parser.getName().equals(SUBSCRIPTION_ADDRESS)) { 828b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.next(); 8297129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee String nextText = parser.getText(); 8307129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee subscriptionAddress = nextText == null ? null : Uri.parse(nextText); 831b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } else if (parser.getName().equals(CAPABILITIES)) { 832b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.next(); 833b78b27693afbe9736f0a54ec473328955251f885Ihab Awad capabilities = Integer.parseInt(parser.getText()); 834b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } else if (parser.getName().equals(ICON_RES_ID)) { 835b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.next(); 836b78b27693afbe9736f0a54ec473328955251f885Ihab Awad iconResId = Integer.parseInt(parser.getText()); 837b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } else if (parser.getName().equals(LABEL)) { 838b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.next(); 839b78b27693afbe9736f0a54ec473328955251f885Ihab Awad label = parser.getText(); 840b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } else if (parser.getName().equals(SHORT_DESCRIPTION)) { 841b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.next(); 842b78b27693afbe9736f0a54ec473328955251f885Ihab Awad shortDescription = parser.getText(); 8438425357e131867f33587641f23a1d1a328acf139Tyler Gunn } else if (parser.getName().equals(SUPPORTED_URI_SCHEMES)) { 8448425357e131867f33587641f23a1d1a328acf139Tyler Gunn supportedUriSchemes = readStringList(parser); 845b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 846b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 8478425357e131867f33587641f23a1d1a328acf139Tyler Gunn 8488425357e131867f33587641f23a1d1a328acf139Tyler Gunn // Upgrade older phone accounts to specify the supported URI schemes. 8498425357e131867f33587641f23a1d1a328acf139Tyler Gunn if (version < 2) { 8508425357e131867f33587641f23a1d1a328acf139Tyler Gunn ComponentName sipComponentName = new ComponentName("com.android.phone", 8518425357e131867f33587641f23a1d1a328acf139Tyler Gunn "com.android.services.telephony.sip.SipConnectionService"); 8528425357e131867f33587641f23a1d1a328acf139Tyler Gunn 8538425357e131867f33587641f23a1d1a328acf139Tyler Gunn supportedUriSchemes = new ArrayList<>(); 8548425357e131867f33587641f23a1d1a328acf139Tyler Gunn 8558425357e131867f33587641f23a1d1a328acf139Tyler Gunn // Handle the SIP connection service. 8568425357e131867f33587641f23a1d1a328acf139Tyler Gunn // Check the system settings to see if it also should handle "tel" calls. 8578425357e131867f33587641f23a1d1a328acf139Tyler Gunn if (accountHandle.getComponentName().equals(sipComponentName)) { 8588425357e131867f33587641f23a1d1a328acf139Tyler Gunn boolean useSipForPstn = useSipForPstnCalls(context); 8598425357e131867f33587641f23a1d1a328acf139Tyler Gunn supportedUriSchemes.add(PhoneAccount.SCHEME_SIP); 8608425357e131867f33587641f23a1d1a328acf139Tyler Gunn if (useSipForPstn) { 8618425357e131867f33587641f23a1d1a328acf139Tyler Gunn supportedUriSchemes.add(PhoneAccount.SCHEME_TEL); 8628425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 8638425357e131867f33587641f23a1d1a328acf139Tyler Gunn } else { 8648425357e131867f33587641f23a1d1a328acf139Tyler Gunn supportedUriSchemes.add(PhoneAccount.SCHEME_TEL); 8658425357e131867f33587641f23a1d1a328acf139Tyler Gunn supportedUriSchemes.add(PhoneAccount.SCHEME_VOICEMAIL); 8668425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 8678425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 8688425357e131867f33587641f23a1d1a328acf139Tyler Gunn 8697129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee return PhoneAccount.builder(accountHandle, label) 8707129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee .setAddress(address) 8717129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee .setSubscriptionAddress(subscriptionAddress) 8727129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee .setCapabilities(capabilities) 8737129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee .setIconResId(iconResId) 8747129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee .setShortDescription(shortDescription) 8757129f1c47945f9aca51858c04daef58ada6bcc39Andrew Lee .setSupportedUriSchemes(supportedUriSchemes) 8766fb37c87836b5245046bd3b14320823ab839a10cIhab Awad .build(); 877b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 878b78b27693afbe9736f0a54ec473328955251f885Ihab Awad return null; 879104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 8808425357e131867f33587641f23a1d1a328acf139Tyler Gunn 8818425357e131867f33587641f23a1d1a328acf139Tyler Gunn /** 8828425357e131867f33587641f23a1d1a328acf139Tyler Gunn * Determines if the SIP call settings specify to use SIP for all calls, including PSTN calls. 8838425357e131867f33587641f23a1d1a328acf139Tyler Gunn * 8848425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @param context The context. 8858425357e131867f33587641f23a1d1a328acf139Tyler Gunn * @return {@code True} if SIP should be used for all calls. 8868425357e131867f33587641f23a1d1a328acf139Tyler Gunn */ 8878425357e131867f33587641f23a1d1a328acf139Tyler Gunn private boolean useSipForPstnCalls(Context context) { 8888425357e131867f33587641f23a1d1a328acf139Tyler Gunn String option = Settings.System.getString(context.getContentResolver(), 8898425357e131867f33587641f23a1d1a328acf139Tyler Gunn Settings.System.SIP_CALL_OPTIONS); 8908425357e131867f33587641f23a1d1a328acf139Tyler Gunn option = (option != null) ? option : Settings.System.SIP_ADDRESS_ONLY; 8918425357e131867f33587641f23a1d1a328acf139Tyler Gunn return option.equals(Settings.System.SIP_ALWAYS); 8928425357e131867f33587641f23a1d1a328acf139Tyler Gunn } 893104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad }; 894104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 895b78b27693afbe9736f0a54ec473328955251f885Ihab Awad @VisibleForTesting 896b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public static final XmlSerialization<PhoneAccountHandle> sPhoneAccountHandleXml = 897b78b27693afbe9736f0a54ec473328955251f885Ihab Awad new XmlSerialization<PhoneAccountHandle>() { 898b78b27693afbe9736f0a54ec473328955251f885Ihab Awad private static final String CLASS_PHONE_ACCOUNT_HANDLE = "phone_account_handle"; 899104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad private static final String COMPONENT_NAME = "component_name"; 900104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad private static final String ID = "id"; 901104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 902104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad @Override 903b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public void writeToXml(PhoneAccountHandle o, XmlSerializer serializer) 904b78b27693afbe9736f0a54ec473328955251f885Ihab Awad throws IOException { 9052692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad if (o != null) { 9062692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.startTag(null, CLASS_PHONE_ACCOUNT_HANDLE); 907b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 9082692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad if (o.getComponentName() != null) { 9092692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad writeTextSafely( 9102692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad COMPONENT_NAME, o.getComponentName().flattenToString(), serializer); 9112692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad } 912b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 9132692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad writeTextSafely(ID, o.getId(), serializer); 914b78b27693afbe9736f0a54ec473328955251f885Ihab Awad 9152692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad serializer.endTag(null, CLASS_PHONE_ACCOUNT_HANDLE); 9162692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad } 917104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 918104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad 919104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad @Override 9208425357e131867f33587641f23a1d1a328acf139Tyler Gunn public PhoneAccountHandle readFromXml(XmlPullParser parser, int version, Context context) 921b78b27693afbe9736f0a54ec473328955251f885Ihab Awad throws IOException, XmlPullParserException { 922b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (parser.getName().equals(CLASS_PHONE_ACCOUNT_HANDLE)) { 923b78b27693afbe9736f0a54ec473328955251f885Ihab Awad String componentNameString = null; 924b78b27693afbe9736f0a54ec473328955251f885Ihab Awad String idString = null; 925b78b27693afbe9736f0a54ec473328955251f885Ihab Awad int outerDepth = parser.getDepth(); 926b78b27693afbe9736f0a54ec473328955251f885Ihab Awad while (XmlUtils.nextElementWithin(parser, outerDepth)) { 927b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (parser.getName().equals(COMPONENT_NAME)) { 928b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.next(); 929b78b27693afbe9736f0a54ec473328955251f885Ihab Awad componentNameString = parser.getText(); 930b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } else if (parser.getName().equals(ID)) { 931b78b27693afbe9736f0a54ec473328955251f885Ihab Awad parser.next(); 932b78b27693afbe9736f0a54ec473328955251f885Ihab Awad idString = parser.getText(); 933b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 934b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 9352692322d55952a807c4fdad7048ca4b4051bf516Ihab Awad if (componentNameString != null) { 936b78b27693afbe9736f0a54ec473328955251f885Ihab Awad return new PhoneAccountHandle( 937b78b27693afbe9736f0a54ec473328955251f885Ihab Awad ComponentName.unflattenFromString(componentNameString), 938b78b27693afbe9736f0a54ec473328955251f885Ihab Awad idString); 939b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 940b78b27693afbe9736f0a54ec473328955251f885Ihab Awad } 941b78b27693afbe9736f0a54ec473328955251f885Ihab Awad return null; 942104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad } 943104f80654d9a0df493f1cf4b9f07b0c2d5d4436eIhab Awad }; 944176ae28ea91519a0b8d513abf3885535c7420d95Santos Cordon} 945