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; 21a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Log; 227cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.ParcelableConnection; 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 28f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebingerimport com.android.internal.annotations.VisibleForTesting; 29f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger 30664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.ArrayList; 31646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepalimport java.util.Collection; 32646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepalimport java.util.HashSet; 33664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.Iterator; 34664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.List; 35293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awadimport java.util.Objects; 36664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 37664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal/** 389250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee * This class creates connections to place new outgoing calls or to attach to an existing incoming 39664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * call. In either case, this class cycles through a set of connection services until: 40664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * - a connection service returns a newly created connection in which case the call is displayed 41664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * to the user 42664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * - a connection service cancels the process, in which case the call is aborted 43664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal */ 44f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger@VisibleForTesting 45f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebingerpublic class CreateConnectionProcessor implements CreateConnectionResponse { 46293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 47293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // Describes information required to attempt to make a phone call 48293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private static class CallAttemptRecord { 49293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // The PhoneAccount describing the target connection service which we will 50293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // contact in order to process an attempt 51b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public final PhoneAccountHandle connectionManagerPhoneAccount; 52293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // The PhoneAccount which we will tell the target connection service to use 53293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // for attempting to make the actual phone call 54b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public final PhoneAccountHandle targetPhoneAccount; 55293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 56293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public CallAttemptRecord( 57b78b27693afbe9736f0a54ec473328955251f885Ihab Awad PhoneAccountHandle connectionManagerPhoneAccount, 58b78b27693afbe9736f0a54ec473328955251f885Ihab Awad PhoneAccountHandle targetPhoneAccount) { 59b78b27693afbe9736f0a54ec473328955251f885Ihab Awad this.connectionManagerPhoneAccount = connectionManagerPhoneAccount; 60b78b27693afbe9736f0a54ec473328955251f885Ihab Awad this.targetPhoneAccount = targetPhoneAccount; 61293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 62293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 63293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad @Override 64293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public String toString() { 65293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad return "CallAttemptRecord(" 66b78b27693afbe9736f0a54ec473328955251f885Ihab Awad + Objects.toString(connectionManagerPhoneAccount) + "," 67b78b27693afbe9736f0a54ec473328955251f885Ihab Awad + Objects.toString(targetPhoneAccount) + ")"; 68293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 696e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn 706e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn /** 716e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn * Determines if this instance of {@code CallAttemptRecord} has the same underlying 726e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn * {@code PhoneAccountHandle}s as another instance. 736e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn * 746e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn * @param obj The other instance to compare against. 756e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn * @return {@code True} if the {@code CallAttemptRecord}s are equal. 766e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn */ 776e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn @Override 786e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn public boolean equals(Object obj) { 796e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn if (obj instanceof CallAttemptRecord) { 806e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn CallAttemptRecord other = (CallAttemptRecord) obj; 816e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn return Objects.equals(connectionManagerPhoneAccount, 826e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn other.connectionManagerPhoneAccount) && 836e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn Objects.equals(targetPhoneAccount, other.targetPhoneAccount); 846e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn } 856e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn return false; 866e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn } 87293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 88293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 89664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final Call mCall; 90664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final ConnectionServiceRepository mRepository; 91293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private List<CallAttemptRecord> mAttemptRecords; 92293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private Iterator<CallAttemptRecord> mAttemptRecordIterator; 93f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger private CreateConnectionResponse mCallResponse; 94701dc006ac11625b55d872f1639107b028933895Andrew Lee private DisconnectCause mLastErrorDisconnectCause; 9591d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn private final PhoneAccountRegistrar mPhoneAccountRegistrar; 9691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn private final Context mContext; 97646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal private CreateConnectionTimeout mTimeout; 98f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger private ConnectionServiceWrapper mService; 996e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger private int mConnectionAttempt; 100664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 101f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger @VisibleForTesting 102f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger public CreateConnectionProcessor( 10391d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn Call call, ConnectionServiceRepository repository, CreateConnectionResponse response, 10491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn PhoneAccountRegistrar phoneAccountRegistrar, Context context) { 1058de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad Log.v(this, "CreateConnectionProcessor created for Call = %s", call); 106664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall = call; 107664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mRepository = repository; 108f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mCallResponse = response; 10991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn mPhoneAccountRegistrar = phoneAccountRegistrar; 11091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn mContext = context; 1116e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger mConnectionAttempt = 0; 112664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 113664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 114752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal boolean isProcessingComplete() { 115f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger return mCallResponse == null; 116752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal } 117752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal 118646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal boolean isCallTimedOut() { 119646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal return mTimeout != null && mTimeout.isCallTimedOut(); 120646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal } 121646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal 1226e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger public int getConnectionAttempt() { 1236e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger return mConnectionAttempt; 1246e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger } 1256e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger 126f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger @VisibleForTesting 127f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger public void process() { 128664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "process"); 129646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal clearTimeout(); 130293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecords = new ArrayList<>(); 131b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (mCall.getTargetPhoneAccount() != null) { 1327957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal mAttemptRecords.add(new CallAttemptRecord( 1337957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount())); 134664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 135a90ba73e6ca2e7e3ef88e41477bf595e03f9359fTyler Gunn if (!mCall.isSelfManaged()) { 136a90ba73e6ca2e7e3ef88e41477bf595e03f9359fTyler Gunn adjustAttemptsForConnectionManager(); 137a90ba73e6ca2e7e3ef88e41477bf595e03f9359fTyler Gunn adjustAttemptsForEmergency(mCall.getTargetPhoneAccount()); 138a90ba73e6ca2e7e3ef88e41477bf595e03f9359fTyler Gunn } 139293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecordIterator = mAttemptRecords.iterator(); 14069eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad attemptNextPhoneAccount(); 141664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 142664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 143752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal boolean hasMorePhoneAccounts() { 144752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal return mAttemptRecordIterator.hasNext(); 145752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal } 146752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal 147752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal void continueProcessingIfPossible(CreateConnectionResponse response, 148752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal DisconnectCause disconnectCause) { 149752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal Log.v(this, "continueProcessingIfPossible"); 150f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mCallResponse = response; 151752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal mLastErrorDisconnectCause = disconnectCause; 152752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal attemptNextPhoneAccount(); 153752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal } 154752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal 155664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal void abort() { 156664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "abort"); 157664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 158664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // Clear the response first to prevent attemptNextConnectionService from attempting any 159664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // more services. 160f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger CreateConnectionResponse response = mCallResponse; 161f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mCallResponse = null; 162646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal clearTimeout(); 163664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 164664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal ConnectionServiceWrapper service = mCall.getConnectionService(); 165664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (service != null) { 166664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal service.abort(mCall); 167664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.clearConnectionService(); 168664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 169664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (response != null) { 170701dc006ac11625b55d872f1639107b028933895Andrew Lee response.handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.LOCAL)); 171664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 172664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 173664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 17469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad private void attemptNextPhoneAccount() { 17569eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.v(this, "attemptNextPhoneAccount"); 176cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn CallAttemptRecord attempt = null; 177cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn if (mAttemptRecordIterator.hasNext()) { 178cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn attempt = mAttemptRecordIterator.next(); 179664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 1806a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon if (!mPhoneAccountRegistrar.phoneAccountRequiresBindPermission( 18191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn attempt.connectionManagerPhoneAccount)) { 182cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn Log.w(this, 1837bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee "Connection mgr does not have BIND_TELECOM_CONNECTION_SERVICE for " 1847bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee + "attempt: %s", attempt); 185cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn attemptNextPhoneAccount(); 186cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn return; 187cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn } 188cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn 189cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn // If the target PhoneAccount differs from the ConnectionManager phone acount, ensure it 1907bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee // also requires the BIND_TELECOM_CONNECTION_SERVICE permission. 191cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn if (!attempt.connectionManagerPhoneAccount.equals(attempt.targetPhoneAccount) && 1926a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon !mPhoneAccountRegistrar.phoneAccountRequiresBindPermission( 1936a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon attempt.targetPhoneAccount)) { 194cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn Log.w(this, 1957bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee "Target PhoneAccount does not have BIND_TELECOM_CONNECTION_SERVICE for " 1967bb8ce9b4e7ffa5e603d8bd8780f55a1c2ced071Yorke Lee + "attempt: %s", attempt); 197cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn attemptNextPhoneAccount(); 198cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn return; 199cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn } 200cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn } 201cb59b679e98d346c9725697ce08b05dd4c2f0a69Tyler Gunn 202f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger if (mCallResponse != null && attempt != null) { 203293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad Log.i(this, "Trying attempt %s", attempt); 204105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount; 205f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mService = mRepository.getService(phoneAccount.getComponentName(), 206f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger phoneAccount.getUserHandle()); 207f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger if (mService == null) { 208293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad Log.i(this, "Found no connection service for attempt %s", attempt); 20969eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad attemptNextPhoneAccount(); 210664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 2116e8f3d70ac7397afb4cb5ab276d1cd385c92dd21Brad Ebinger mConnectionAttempt++; 212b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount); 213b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mCall.setTargetPhoneAccount(attempt.targetPhoneAccount); 214f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mCall.setConnectionService(mService); 215f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger setTimeoutIfNeeded(mService, attempt); 216606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng if (mCall.isIncoming()) { 217606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng mService.createConnection(mCall, CreateConnectionProcessor.this); 218606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng } else { 219606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng // Start to create the connection for outgoing call after the ConnectionService 220606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng // of the call has gained the focus. 221606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng mCall.getConnectionServiceFocusManager().requestFocus( 222606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng mCall, 223606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng new CallsManager.RequestCallback(new CallsManager.PendingAction() { 224606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng @Override 225606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng public void performAction() { 226606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng Log.d(this, "perform create connection"); 227606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng mService.createConnection( 228606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng mCall, 229606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng CreateConnectionProcessor.this); 230606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng } 231606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng })); 232646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal 233606ff7f93c1b95fda48a89876000cb4f63b6e47bPengquan Meng } 234664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 235664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 23669eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.v(this, "attemptNextPhoneAccount, no more accounts, failing"); 237f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger DisconnectCause disconnectCause = mLastErrorDisconnectCause != null ? 238f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mLastErrorDisconnectCause : new DisconnectCause(DisconnectCause.ERROR); 239f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger notifyCallConnectionFailure(disconnectCause); 240664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 241664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 242664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 243646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal private void setTimeoutIfNeeded(ConnectionServiceWrapper service, CallAttemptRecord attempt) { 244646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal clearTimeout(); 245646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal 246646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal CreateConnectionTimeout timeout = new CreateConnectionTimeout( 247646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal mContext, mPhoneAccountRegistrar, service, mCall); 248646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal if (timeout.isTimeoutNeededForCall(getConnectionServices(mAttemptRecords), 249646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal attempt.connectionManagerPhoneAccount)) { 250646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal mTimeout = timeout; 251646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal timeout.registerTimeout(); 252646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal } 253646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal } 254646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal 255646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal private void clearTimeout() { 256646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal if (mTimeout != null) { 257646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal mTimeout.unregisterTimeout(); 258646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal mTimeout = null; 259646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal } 260646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal } 261646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal 2627957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal private boolean shouldSetConnectionManager() { 2637957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (mAttemptRecords.size() == 0) { 2647957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return false; 265293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 2667957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 2677957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (mAttemptRecords.size() > 1) { 2687957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal Log.d(this, "shouldSetConnectionManager, error, mAttemptRecords should not have more " 2697957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal + "than 1 record"); 2707957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return false; 2717957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } 2727957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 273240656f19c078b4f703d0502ce29114de0d45a50Tony Mak PhoneAccountHandle connectionManager = 274240656f19c078b4f703d0502ce29114de0d45a50Tony Mak mPhoneAccountRegistrar.getSimCallManagerFromCall(mCall); 2757957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (connectionManager == null) { 2767957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return false; 2777957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } 2787957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 2797957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal PhoneAccountHandle targetPhoneAccountHandle = mAttemptRecords.get(0).targetPhoneAccount; 2807957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (Objects.equals(connectionManager, targetPhoneAccountHandle)) { 2817957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return false; 2827957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } 2837957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 2847957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal // Connection managers are only allowed to manage SIM subscriptions. 2856a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon // TODO: Should this really be checking the "calling user" test for phone account? 286240656f19c078b4f703d0502ce29114de0d45a50Tony Mak PhoneAccount targetPhoneAccount = mPhoneAccountRegistrar 287240656f19c078b4f703d0502ce29114de0d45a50Tony Mak .getPhoneAccountUnchecked(targetPhoneAccountHandle); 28891fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal if (targetPhoneAccount == null) { 28991fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal Log.d(this, "shouldSetConnectionManager, phone account not found"); 29091fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal return false; 29191fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal } 2927957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal boolean isSimSubscription = (targetPhoneAccount.getCapabilities() & 2937957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0; 2947957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (!isSimSubscription) { 2957957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return false; 2967957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } 2977957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 2987957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal return true; 2997957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } 3007957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal 3017957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal // If there exists a registered connection manager then use it. 3027957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal private void adjustAttemptsForConnectionManager() { 3037957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal if (shouldSetConnectionManager()) { 3047957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal CallAttemptRecord record = new CallAttemptRecord( 305240656f19c078b4f703d0502ce29114de0d45a50Tony Mak mPhoneAccountRegistrar.getSimCallManagerFromCall(mCall), 3067957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal mAttemptRecords.get(0).targetPhoneAccount); 30710a5831cf61b3ab3b126329044ea05dc3181fa63mike dooley Log.v(this, "setConnectionManager, changing %s -> %s", mAttemptRecords.get(0), record); 308f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mAttemptRecords.add(0, record); 3097957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal } else { 3107957f9ca486703ba1c2d5f63a8537d65ac3f1f94Sailesh Nepal Log.v(this, "setConnectionManager, not changing"); 311293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 312293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 313293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 314664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // If we are possibly attempting to call a local emergency number, ensure that the 31569eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad // plain PSTN connection services are listed, and nothing else. 316e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger private void adjustAttemptsForEmergency(PhoneAccountHandle preferredPAH) { 3176ffe531cc43849b5ca22a23647f5e729fae01c25Tyler Gunn if (mCall.isEmergencyCall()) { 31869eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.i(this, "Emergency number detected"); 319293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecords.clear(); 320240656f19c078b4f703d0502ce29114de0d45a50Tony Mak // Phone accounts in profile do not handle emergency call, use phone accounts in 321240656f19c078b4f703d0502ce29114de0d45a50Tony Mak // current user. 322240656f19c078b4f703d0502ce29114de0d45a50Tony Mak List<PhoneAccount> allAccounts = mPhoneAccountRegistrar 323240656f19c078b4f703d0502ce29114de0d45a50Tony Mak .getAllPhoneAccountsOfCurrentUser(); 324c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee 325c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee if (allAccounts.isEmpty()) { 326c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee // If the list of phone accounts is empty at this point, it means Telephony hasn't 327c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee // registered any phone accounts yet. Add a fallback emergency phone account so 328c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee // that emergency calls can still go through. We create a new ArrayLists here just 329c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee // in case the implementation of PhoneAccountRegistrar ever returns an unmodifiable 330c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee // list. 331c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee allAccounts = new ArrayList<PhoneAccount>(); 332c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee allAccounts.add(TelephonyUtil.getDefaultEmergencyPhoneAccount()); 333c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee } 334c127211ffd269bffc8a393a3c5ebfe7bdd99896bYorke Lee 335e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger // First, possibly add the SIM phone account that the user prefers 336e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger PhoneAccount preferredPA = mPhoneAccountRegistrar.getPhoneAccountUnchecked( 337e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger preferredPAH); 338e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger if (preferredPA != null && 339e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger preferredPA.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS) && 340e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger preferredPA.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) { 341e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger Log.i(this, "Will try PSTN account %s for emergency", 342e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger preferredPA.getAccountHandle()); 343e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger mAttemptRecords.add(new CallAttemptRecord(preferredPAH, preferredPAH)); 344e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger } 345e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger 346e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger // Next, add all SIM phone accounts which can place emergency calls. 347e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger TelephonyUtil.sortSimPhoneAccounts(mContext, allAccounts); 348a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala 349a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala // If preferredPA already has an emergency PhoneAccount, do not add others since the 350a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala // emergency call be redialed in Telephony. 351a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala if (mAttemptRecords.isEmpty()) { 352a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala for (PhoneAccount phoneAccount : allAccounts) { 353a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS) 354a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala && phoneAccount.hasCapabilities( 355a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) { 356a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala PhoneAccountHandle phoneAccountHandle = phoneAccount.getAccountHandle(); 357e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger Log.i(this, "Will try PSTN account %s for emergency", phoneAccountHandle); 358e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger mAttemptRecords.add(new CallAttemptRecord(phoneAccountHandle, 359e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger phoneAccountHandle)); 360a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala // Add only one emergency SIM PhoneAccount to the attempt list. 361a67450da020aa313d0c7c503e73e71d843f36729Srikanth Chintala break; 362e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger } 363664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 364664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 3656e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn 3668e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn // Next, add the connection manager account as a backup if it can place emergency calls. 367240656f19c078b4f703d0502ce29114de0d45a50Tony Mak PhoneAccountHandle callManagerHandle = 368240656f19c078b4f703d0502ce29114de0d45a50Tony Mak mPhoneAccountRegistrar.getSimCallManagerOfCurrentUser(); 369f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger if (callManagerHandle != null) { 370f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // TODO: Should this really be checking the "calling user" test for phone account? 37191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn PhoneAccount callManager = mPhoneAccountRegistrar 372240656f19c078b4f703d0502ce29114de0d45a50Tony Mak .getPhoneAccountUnchecked(callManagerHandle); 37391fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal if (callManager != null && callManager.hasCapabilities( 37491fc8099a0690a3367eb206788c9c25ceff31875Sailesh Nepal PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS)) { 3758e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn CallAttemptRecord callAttemptRecord = new CallAttemptRecord(callManagerHandle, 376240656f19c078b4f703d0502ce29114de0d45a50Tony Mak mPhoneAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 37762630f727fa055e5d79c8194ed5db697104f116cHall Liu mCall.getHandle() == null 37862630f727fa055e5d79c8194ed5db697104f116cHall Liu ? null : mCall.getHandle().getScheme())); 3798e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn if (!mAttemptRecords.contains(callAttemptRecord)) { 3808e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn Log.i(this, "Will try Connection Manager account %s for emergency", 3818e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn callManager); 3828e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn mAttemptRecords.add(callAttemptRecord); 3838e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn } 3848e0fef4e1fd09116e4df4ba2ecc18f06cebe71c2Tyler Gunn } 3856e6f6d1f7b7e5b5b506c198e6719c9c68e205042Tyler Gunn } 386664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 387664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 388664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 389646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal /** Returns all connection services used by the call attempt records. */ 390646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal private static Collection<PhoneAccountHandle> getConnectionServices( 391646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal List<CallAttemptRecord> records) { 392646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal HashSet<PhoneAccountHandle> result = new HashSet<>(); 393646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal for (CallAttemptRecord record : records) { 394646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal result.add(record.connectionManagerPhoneAccount); 395646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal } 396646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal return result; 397646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal } 398646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal 399664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 400f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger private void notifyCallConnectionFailure(DisconnectCause errorDisconnectCause) { 401f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger if (mCallResponse != null) { 402f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger clearTimeout(); 403f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mCallResponse.handleCreateConnectionFailure(errorDisconnectCause); 404f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mCallResponse = null; 405f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mCall.clearConnectionService(); 406664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 407f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger } 408664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 409f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger @Override 410f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger public void handleCreateConnectionSuccess( 411f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger CallIdMapper idMapper, 412f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger ParcelableConnection connection) { 413f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger if (mCallResponse == null) { 414f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // Nobody is listening for this connection attempt any longer; ask the responsible 415f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // ConnectionService to tear down any resources associated with the call 416f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mService.abort(mCall); 417f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger } else { 418f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // Success -- share the good news and remember that we are no longer interested 419f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // in hearing about any more attempts 420f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mCallResponse.handleCreateConnectionSuccess(idMapper, connection); 421f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mCallResponse = null; 422f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // If there's a timeout running then don't clear it. The timeout can be triggered 423f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // after the call has successfully been created but before it has become active. 424664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 425f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger } 426664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 427f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger private boolean shouldFailCallIfConnectionManagerFails(DisconnectCause cause) { 428f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // Connection Manager does not exist or does not match registered Connection Manager 429f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // Since Connection manager is a proxy for SIM, fall back to SIM 430f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger PhoneAccountHandle handle = mCall.getConnectionManagerPhoneAccount(); 431f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger if (handle == null || !handle.equals(mPhoneAccountRegistrar.getSimCallManagerFromCall( 432f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger mCall))) { 433f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger return false; 434f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger } 435bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal 436f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // The Call's Connection Service does not exist 437f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger ConnectionServiceWrapper connectionManager = mCall.getConnectionService(); 438f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger if (connectionManager == null) { 439f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger return true; 440f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger } 441bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal 442f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // In this case, fall back to a sim because connection manager declined 443f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger if (cause.getCode() == DisconnectCause.CONNECTION_MANAGER_NOT_SUPPORTED) { 444f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger Log.d(CreateConnectionProcessor.this, "Connection manager declined to handle the " 445f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger + "call, falling back to not using a connection manager"); 446f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger return false; 447f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger } 448bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal 449f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger if (!connectionManager.isServiceValid("createConnection")) { 450f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger Log.d(CreateConnectionProcessor.this, "Connection manager unbound while trying " 451f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger + "create a connection, falling back to not using a connection manager"); 452bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal return false; 453bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal } 454bafadce53332c7e0f7be0482cf04333c72487a70Sailesh Nepal 455f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // Do not fall back from connection manager and simply fail call if the failure reason is 456f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // other 457f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger Log.d(CreateConnectionProcessor.this, "Connection Manager denied call with the following " + 458f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger "error: " + cause.getReason() + ". Not falling back to SIM."); 459f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger return true; 460f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger } 461f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger 462f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger @Override 463f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger public void handleCreateConnectionFailure(DisconnectCause errorDisconnectCause) { 464f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger // Failure of some sort; record the reasons for failure and try again if possible 465f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger Log.d(CreateConnectionProcessor.this, "Connection failed: (%s)", errorDisconnectCause); 466e6c481acfcad381e3973e3250a366e1893259b84Brad Ebinger if (shouldFailCallIfConnectionManagerFails(errorDisconnectCause)) { 467f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger notifyCallConnectionFailure(errorDisconnectCause); 468f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger return; 469664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 4708ff99f3751fcdd662932317ca45f886f6883e196Santos Cordon mLastErrorDisconnectCause = errorDisconnectCause; 471f19000764f6b93dfa15561342cbdd9c1aa1d3e22Brad Ebinger attemptNextPhoneAccount(); 472664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 473664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal} 474