CreateConnectionProcessor.java revision c127211ffd269bffc8a393a3c5ebfe7bdd99896b
1664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal/* 2664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * Copyright 2014, The Android Open Source Project 3664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * 4664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * Licensed under the Apache License, Version 2.0 (the "License"); 5664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * you may not use this file except in compliance with the License. 6664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * You may obtain a copy of the License at 7664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * 8664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * http://www.apache.org/licenses/LICENSE-2.0 9664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * 10664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * Unless required by applicable law or agreed to in writing, software 11664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * distributed under the License is distributed on an "AS IS" BASIS, 12664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * See the License for the specific language governing permissions and 14664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * limitations under the License. 15664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal */ 16664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom; 18664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 1991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunnimport android.content.Context; 20701dc006ac11625b55d872f1639107b028933895Andrew Leeimport android.telecom.DisconnectCause; 217cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.ParcelableConnection; 2291d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunnimport android.telecom.Phone; 237cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccount; 247cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccountHandle; 25664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 2691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn// TODO: Needed for move to system service: import com.android.internal.R; 2791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn 28664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.ArrayList; 29664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.Iterator; 30664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.List; 31293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awadimport java.util.Objects; 32664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 33664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal/** 349250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee * This class creates connections to place new outgoing calls or to attach to an existing incoming 35664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * call. In either case, this class cycles through a set of connection services until: 36664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * - a connection service returns a newly created connection in which case the call is displayed 37664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * to the user 38664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * - a connection service cancels the process, in which case the call is aborted 39664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal */ 40664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalfinal class CreateConnectionProcessor { 41293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 42293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // Describes information required to attempt to make a phone call 43293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private static class CallAttemptRecord { 44293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // The PhoneAccount describing the target connection service which we will 45293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // contact in order to process an attempt 46b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public final PhoneAccountHandle connectionManagerPhoneAccount; 47293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // The PhoneAccount which we will tell the target connection service to use 48293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // for attempting to make the actual phone call 49b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public final PhoneAccountHandle targetPhoneAccount; 50293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 51293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public CallAttemptRecord( 52b78b27693afbe9736f0a54ec473328955251f885Ihab Awad PhoneAccountHandle connectionManagerPhoneAccount, 53b78b27693afbe9736f0a54ec473328955251f885Ihab Awad PhoneAccountHandle targetPhoneAccount) { 54b78b27693afbe9736f0a54ec473328955251f885Ihab Awad this.connectionManagerPhoneAccount = connectionManagerPhoneAccount; 55b78b27693afbe9736f0a54ec473328955251f885Ihab Awad this.targetPhoneAccount = targetPhoneAccount; 56293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 57293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 58293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad @Override 59293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public String toString() { 60293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad return "CallAttemptRecord(" 61b78b27693afbe9736f0a54ec473328955251f885Ihab Awad + Objects.toString(connectionManagerPhoneAccount) + "," 62b78b27693afbe9736f0a54ec473328955251f885Ihab Awad + Objects.toString(targetPhoneAccount) + ")"; 63293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 646e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn 656e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn /** 666e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn * Determines if this instance of {@code CallAttemptRecord} has the same underlying 676e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn * {@code PhoneAccountHandle}s as another instance. 686e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn * 696e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn * @param obj The other instance to compare against. 706e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn * @return {@code True} if the {@code CallAttemptRecord}s are equal. 716e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn */ 726e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn @Override 736e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn public boolean equals(Object obj) { 746e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn if (obj instanceof CallAttemptRecord) { 756e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn CallAttemptRecord other = (CallAttemptRecord) obj; 766e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn return Objects.equals(connectionManagerPhoneAccount, 776e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn other.connectionManagerPhoneAccount) && 786e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn Objects.equals(targetPhoneAccount, other.targetPhoneAccount); 796e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn } 806e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn return false; 816e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn } 82293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 83293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 84664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final Call mCall; 85664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final ConnectionServiceRepository mRepository; 86293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private List<CallAttemptRecord> mAttemptRecords; 87293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private Iterator<CallAttemptRecord> mAttemptRecordIterator; 88664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private CreateConnectionResponse mResponse; 89701dc006ac11625b55d872f1639107b028933895Andrew Lee private DisconnectCause mLastErrorDisconnectCause; 9091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn private final PhoneAccountRegistrar mPhoneAccountRegistrar; 9191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn private final Context mContext; 92664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 93664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal CreateConnectionProcessor( 9491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn Call call, ConnectionServiceRepository repository, CreateConnectionResponse response, 9591d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn PhoneAccountRegistrar phoneAccountRegistrar, Context context) { 96664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall = call; 97664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mRepository = repository; 98664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = response; 9991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn mPhoneAccountRegistrar = phoneAccountRegistrar; 10091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn mContext = context; 101664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 102664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 103664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal void process() { 104664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "process"); 105293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecords = new ArrayList<>(); 106b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (mCall.getTargetPhoneAccount() != null) { 1077957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal mAttemptRecords.add(new CallAttemptRecord( 1087957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount())); 109664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 1107957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal adjustAttemptsForConnectionManager(); 111293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad adjustAttemptsForEmergency(); 112293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecordIterator = mAttemptRecords.iterator(); 11369eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad attemptNextPhoneAccount(); 114664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 115664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 116664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal void abort() { 117664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "abort"); 118664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 119664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // Clear the response first to prevent attemptNextConnectionService from attempting any 120664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // more services. 121664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal CreateConnectionResponse response = mResponse; 122664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = null; 123664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 124664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal ConnectionServiceWrapper service = mCall.getConnectionService(); 125664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (service != null) { 126664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal service.abort(mCall); 127664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.clearConnectionService(); 128664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 129664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (response != null) { 130701dc006ac11625b55d872f1639107b028933895Andrew Lee response.handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.LOCAL)); 131664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 132664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 133664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 13469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad private void attemptNextPhoneAccount() { 13569eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.v(this, "attemptNextPhoneAccount"); 136cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn CallAttemptRecord attempt = null; 137cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn if (mAttemptRecordIterator.hasNext()) { 138cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn attempt = mAttemptRecordIterator.next(); 139664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 14091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn if (!mPhoneAccountRegistrar.phoneAccountHasPermission( 14191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn attempt.connectionManagerPhoneAccount)) { 142cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn Log.w(this, 143cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn "Connection mgr does not have BIND_CONNECTION_SERVICE for attempt: %s", 144cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn attempt); 145cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn attemptNextPhoneAccount(); 146cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn return; 147cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn } 148cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn 149cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn // If the target PhoneAccount differs from the ConnectionManager phone acount, ensure it 150cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn // also has BIND_CONNECTION_SERVICE permission. 151cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn if (!attempt.connectionManagerPhoneAccount.equals(attempt.targetPhoneAccount) && 15291d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn !mPhoneAccountRegistrar.phoneAccountHasPermission(attempt.targetPhoneAccount)) { 153cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn Log.w(this, 154cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn "Target PhoneAccount does not have BIND_CONNECTION_SERVICE for attempt: %s", 155cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn attempt); 156cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn attemptNextPhoneAccount(); 157cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn return; 158cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn } 159cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn } 160cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn 161cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn if (mResponse != null && attempt != null) { 162293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad Log.i(this, "Trying attempt %s", attempt); 16394d01629010a61f6112713f22330d5fd4baae851Evan Charlton ConnectionServiceWrapper service = 164b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mRepository.getService( 165b78b27693afbe9736f0a54ec473328955251f885Ihab Awad attempt.connectionManagerPhoneAccount.getComponentName()); 166664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (service == null) { 167293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad Log.i(this, "Found no connection service for attempt %s", attempt); 16869eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad attemptNextPhoneAccount(); 169664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 170b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount); 171b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mCall.setTargetPhoneAccount(attempt.targetPhoneAccount); 172664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.setConnectionService(service); 173664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.i(this, "Attempting to call from %s", service.getComponentName()); 174664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal service.createConnection(mCall, new Response(service)); 175664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 176664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 17769eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.v(this, "attemptNextPhoneAccount, no more accounts, failing"); 178664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse != null) { 179f211ce79c1034315d454289ed233c11dd3aa4d0fJay Shrauner mResponse.handleCreateConnectionFailure(mLastErrorDisconnectCause != null ? 180f211ce79c1034315d454289ed233c11dd3aa4d0fJay Shrauner mLastErrorDisconnectCause : new DisconnectCause(DisconnectCause.ERROR)); 181664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = null; 182664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.clearConnectionService(); 183664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 184664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 185664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 186664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 1877957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal private boolean shouldSetConnectionManager() { 1887957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (mAttemptRecords.size() == 0) { 1897957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return false; 190293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 1917957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 1927957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (mAttemptRecords.size() > 1) { 1937957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal Log.d(this, "shouldSetConnectionManager, error, mAttemptRecords should not have more " 1947957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal + "than 1 record"); 1957957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return false; 1967957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } 1977957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 19891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn PhoneAccountHandle connectionManager = mPhoneAccountRegistrar.getSimCallManager(); 1997957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (connectionManager == null) { 2007957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return false; 2017957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } 2027957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 2037957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal PhoneAccountHandle targetPhoneAccountHandle = mAttemptRecords.get(0).targetPhoneAccount; 2047957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (Objects.equals(connectionManager, targetPhoneAccountHandle)) { 2057957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return false; 2067957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } 2077957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 2087957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal // Connection managers are only allowed to manage SIM subscriptions. 20991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn PhoneAccount targetPhoneAccount = mPhoneAccountRegistrar.getPhoneAccount( 21091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn targetPhoneAccountHandle); 2117957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal boolean isSimSubscription = (targetPhoneAccount.getCapabilities() & 2127957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0; 2137957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (!isSimSubscription) { 2147957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return false; 2157957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } 2167957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 2177957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return true; 2187957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } 2197957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 2207957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal // If there exists a registered connection manager then use it. 2217957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal private void adjustAttemptsForConnectionManager() { 2227957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (shouldSetConnectionManager()) { 2237957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal CallAttemptRecord record = new CallAttemptRecord( 22491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn mPhoneAccountRegistrar.getSimCallManager(), 2257957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal mAttemptRecords.get(0).targetPhoneAccount); 2267957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal Log.v(this, "setConnectionManager, changing %s -> %s", 2277957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal mAttemptRecords.get(0).targetPhoneAccount, record); 2287957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal mAttemptRecords.set(0, record); 2297957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } else { 2307957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal Log.v(this, "setConnectionManager, not changing"); 231293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 232293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 233293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 234664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // If we are possibly attempting to call a local emergency number, ensure that the 23569eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad // plain PSTN connection services are listed, and nothing else. 236293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private void adjustAttemptsForEmergency() { 23791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn if (TelephonyUtil.shouldProcessAsEmergency(mContext, mCall.getHandle())) { 23869eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.i(this, "Emergency number detected"); 239293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecords.clear(); 24091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn List<PhoneAccount> allAccounts = mPhoneAccountRegistrar.getAllPhoneAccounts(); 241c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee 242c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee if (allAccounts.isEmpty()) { 243c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee // If the list of phone accounts is empty at this point, it means Telephony hasn't 244c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee // registered any phone accounts yet. Add a fallback emergency phone account so 245c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee // that emergency calls can still go through. We create a new ArrayLists here just 246c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee // in case the implementation of PhoneAccountRegistrar ever returns an unmodifiable 247c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee // list. 248c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee allAccounts = new ArrayList<PhoneAccount>(); 249c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee allAccounts.add(TelephonyUtil.getDefaultEmergencyPhoneAccount()); 250c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee } 251c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee 252c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee 2538e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn // First, add SIM phone accounts which can place emergency calls. 2548e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn for (PhoneAccount phoneAccount : allAccounts) { 2558e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS) && 2568e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) { 2578e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn Log.i(this, "Will try PSTN account %s for emergency", 2588e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn phoneAccount.getAccountHandle()); 259293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecords.add( 260293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad new CallAttemptRecord( 2618e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn phoneAccount.getAccountHandle(), 2628e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn phoneAccount.getAccountHandle())); 263664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 264664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 2656e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn 2668e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn // Next, add the connection manager account as a backup if it can place emergency calls. 26791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn PhoneAccountHandle callManagerHandle = mPhoneAccountRegistrar.getSimCallManager(); 2688e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn if (callManagerHandle != null) { 26991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn PhoneAccount callManager = mPhoneAccountRegistrar 27091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn .getPhoneAccount(callManagerHandle); 2718e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn if (callManager.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)) { 2728e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn CallAttemptRecord callAttemptRecord = new CallAttemptRecord(callManagerHandle, 27391d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn mPhoneAccountRegistrar. 2748e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn getDefaultOutgoingPhoneAccount(mCall.getHandle().getScheme()) 2758e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn ); 2768e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn 2778e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn if (!mAttemptRecords.contains(callAttemptRecord)) { 2788e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn Log.i(this, "Will try Connection Manager account %s for emergency", 2798e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn callManager); 2808e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn mAttemptRecords.add(callAttemptRecord); 2818e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn } 2828e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn } 2836e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn } 284664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 285664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 286664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 287664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private class Response implements CreateConnectionResponse { 288664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final ConnectionServiceWrapper mService; 289664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 290664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Response(ConnectionServiceWrapper service) { 291664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mService = service; 292664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 293664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 294664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal @Override 2958000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad public void handleCreateConnectionSuccess( 2968000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad CallIdMapper idMapper, 2978000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad ParcelableConnection connection) { 298664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse == null) { 299fb5560d634aef745466e8869f8acf496447da17bIhab Awad // Nobody is listening for this connection attempt any longer; ask the responsible 300fb5560d634aef745466e8869f8acf496447da17bIhab Awad // ConnectionService to tear down any resources associated with the call 301664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mService.abort(mCall); 302664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 303fb5560d634aef745466e8869f8acf496447da17bIhab Awad // Success -- share the good news and remember that we are no longer interested 304fb5560d634aef745466e8869f8acf496447da17bIhab Awad // in hearing about any more attempts 3058000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad mResponse.handleCreateConnectionSuccess(idMapper, connection); 30672890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon mResponse = null; 307664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 308664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 309664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 310664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal @Override 311701dc006ac11625b55d872f1639107b028933895Andrew Lee public void handleCreateConnectionFailure(DisconnectCause errorDisconnectCause) { 312fb5560d634aef745466e8869f8acf496447da17bIhab Awad // Failure of some sort; record the reasons for failure and try again if possible 313701dc006ac11625b55d872f1639107b028933895Andrew Lee Log.d(CreateConnectionProcessor.this, "Connection failed: (%s)", errorDisconnectCause); 314701dc006ac11625b55d872f1639107b028933895Andrew Lee mLastErrorDisconnectCause = errorDisconnectCause; 31569eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad attemptNextPhoneAccount(); 316664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 317664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 318664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal} 319