CreateConnectionProcessor.java revision b78b27693afbe9736f0a54ec473328955251f885
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 17664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalpackage com.android.telecomm; 18664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 1972890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordonimport android.telecomm.ConnectionRequest; 2072890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordonimport android.telecomm.ParcelableConnection; 2189176375c8d97db25588f720952a4fadbce2f9a3Evan Charltonimport android.telecomm.PhoneAccountHandle; 22664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport android.telephony.DisconnectCause; 23664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 24664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.ArrayList; 25664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.Iterator; 26664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.List; 27293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awadimport java.util.Objects; 28664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 29664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal/** 30664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * This class creates connections to place new outgoing calls to attached to an existing incoming 31664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * call. In either case, this class cycles through a set of connection services until: 32664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * - a connection service returns a newly created connection in which case the call is displayed 33664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * to the user 34664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * - a connection service cancels the process, in which case the call is aborted 35664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal */ 36664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalfinal class CreateConnectionProcessor { 37293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 38293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // Describes information required to attempt to make a phone call 39293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private static class CallAttemptRecord { 40293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // The PhoneAccount describing the target connection service which we will 41293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // contact in order to process an attempt 42b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public final PhoneAccountHandle connectionManagerPhoneAccount; 43293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // The PhoneAccount which we will tell the target connection service to use 44293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // for attempting to make the actual phone call 45b78b27693afbe9736f0a54ec473328955251f885Ihab Awad public final PhoneAccountHandle targetPhoneAccount; 46293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 47293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public CallAttemptRecord( 48b78b27693afbe9736f0a54ec473328955251f885Ihab Awad PhoneAccountHandle connectionManagerPhoneAccount, 49b78b27693afbe9736f0a54ec473328955251f885Ihab Awad PhoneAccountHandle targetPhoneAccount) { 50b78b27693afbe9736f0a54ec473328955251f885Ihab Awad this.connectionManagerPhoneAccount = connectionManagerPhoneAccount; 51b78b27693afbe9736f0a54ec473328955251f885Ihab Awad this.targetPhoneAccount = targetPhoneAccount; 52293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 53293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 54293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad @Override 55293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad public String toString() { 56293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad return "CallAttemptRecord(" 57b78b27693afbe9736f0a54ec473328955251f885Ihab Awad + Objects.toString(connectionManagerPhoneAccount) + "," 58b78b27693afbe9736f0a54ec473328955251f885Ihab Awad + Objects.toString(targetPhoneAccount) + ")"; 59293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 60293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 61293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 62664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final Call mCall; 63664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final ConnectionServiceRepository mRepository; 64293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private List<CallAttemptRecord> mAttemptRecords; 65293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private Iterator<CallAttemptRecord> mAttemptRecordIterator; 66664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private CreateConnectionResponse mResponse; 67fd6ca447a45c47aeb3956964103770475c655a26Santos Cordon private int mLastErrorCode = DisconnectCause.OUTGOING_FAILURE; 68664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private String mLastErrorMsg; 69664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 70664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal CreateConnectionProcessor( 71664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Call call, ConnectionServiceRepository repository, CreateConnectionResponse response) { 72664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall = call; 73664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mRepository = repository; 74664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = response; 75664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 76664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 77664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal void process() { 78664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "process"); 79293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecords = new ArrayList<>(); 80b78b27693afbe9736f0a54ec473328955251f885Ihab Awad if (mCall.getTargetPhoneAccount() != null) { 81293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecords.add( 82b78b27693afbe9736f0a54ec473328955251f885Ihab Awad new CallAttemptRecord(mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount())); 83664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 84293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad adjustAttemptsForWifi(); 85293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad adjustAttemptsForEmergency(); 86293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecordIterator = mAttemptRecords.iterator(); 8769eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad attemptNextPhoneAccount(); 88664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 89664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 90664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal void abort() { 91664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "abort"); 92664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 93664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // Clear the response first to prevent attemptNextConnectionService from attempting any 94664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // more services. 95664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal CreateConnectionResponse response = mResponse; 96664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = null; 97664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 98664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal ConnectionServiceWrapper service = mCall.getConnectionService(); 99664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (service != null) { 100664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal service.abort(mCall); 101664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.clearConnectionService(); 102664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 103664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (response != null) { 104664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal response.handleCreateConnectionCancelled(); 105664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 106664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 107664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 10869eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad private void attemptNextPhoneAccount() { 10969eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.v(this, "attemptNextPhoneAccount"); 110664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 111293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad if (mResponse != null && mAttemptRecordIterator.hasNext()) { 112293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad CallAttemptRecord attempt = mAttemptRecordIterator.next(); 113293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad Log.i(this, "Trying attempt %s", attempt); 11494d01629010a61f6112713f22330d5fd4baae851Evan Charlton ConnectionServiceWrapper service = 115b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mRepository.getService( 116b78b27693afbe9736f0a54ec473328955251f885Ihab Awad attempt.connectionManagerPhoneAccount.getComponentName()); 117664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (service == null) { 118293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad Log.i(this, "Found no connection service for attempt %s", attempt); 11969eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad attemptNextPhoneAccount(); 120664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 121b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount); 122b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mCall.setTargetPhoneAccount(attempt.targetPhoneAccount); 123664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.setConnectionService(service); 124664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.i(this, "Attempting to call from %s", service.getComponentName()); 125664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal service.createConnection(mCall, new Response(service)); 126664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 127664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 12869eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.v(this, "attemptNextPhoneAccount, no more accounts, failing"); 129664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse != null) { 130664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse.handleCreateConnectionFailed(mLastErrorCode, mLastErrorMsg); 131664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = null; 132664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.clearConnectionService(); 133664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 134664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 135664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 136664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 137293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad // If there exists a registered Wi-Fi calling service, use it. 138293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private void adjustAttemptsForWifi() { 139293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad switch (mAttemptRecords.size()) { 140293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad case 0: 141293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad return; 142293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad case 1: 143293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad break; 144293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad default: 145293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad Log.d(this, "Unexpectedly have > 1 attempt: %s", mAttemptRecords); 146293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad return; 147293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 148293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad PhoneAccountHandle simCallManager = 149293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad TelecommApp.getInstance().getPhoneAccountRegistrar().getSimCallManager(); 150293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad if (simCallManager != null && 151b78b27693afbe9736f0a54ec473328955251f885Ihab Awad !Objects.equals(simCallManager, mAttemptRecords.get(0).targetPhoneAccount)) { 152293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecords.set( 153293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 0, 154293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad new CallAttemptRecord( 155293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad simCallManager, 156b78b27693afbe9736f0a54ec473328955251f885Ihab Awad mAttemptRecords.get(0).targetPhoneAccount)); 157293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 158293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad } 159293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad 160664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // If we are possibly attempting to call a local emergency number, ensure that the 16169eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad // plain PSTN connection services are listed, and nothing else. 162293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad private void adjustAttemptsForEmergency() { 16369eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad if (TelephonyUtil.shouldProcessAsEmergency(TelecommApp.getInstance(), mCall.getHandle())) { 16469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.i(this, "Emergency number detected"); 165293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecords.clear(); 16694d01629010a61f6112713f22330d5fd4baae851Evan Charlton List<PhoneAccountHandle> allAccountHandles = TelecommApp.getInstance() 16794d01629010a61f6112713f22330d5fd4baae851Evan Charlton .getPhoneAccountRegistrar().getEnabledPhoneAccounts(); 16894d01629010a61f6112713f22330d5fd4baae851Evan Charlton for (int i = 0; i < allAccountHandles.size(); i++) { 16994d01629010a61f6112713f22330d5fd4baae851Evan Charlton if (TelephonyUtil.isPstnComponentName( 17094d01629010a61f6112713f22330d5fd4baae851Evan Charlton allAccountHandles.get(i).getComponentName())) { 17194d01629010a61f6112713f22330d5fd4baae851Evan Charlton Log.i(this, "Will try PSTN account %s for emergency", allAccountHandles.get(i)); 172293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad mAttemptRecords.add( 173293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad new CallAttemptRecord( 174293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad allAccountHandles.get(i), 175293edf245f3e37691073c8bf4a1fc271ecbc5370Ihab Awad allAccountHandles.get(i))); 176664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 177664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 178664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 179664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 180664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 181664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private class Response implements CreateConnectionResponse { 182664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final ConnectionServiceWrapper mService; 183664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 184664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Response(ConnectionServiceWrapper service) { 185664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mService = service; 186664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 187664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 188664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal @Override 18972890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon public void handleCreateConnectionSuccessful( 19072890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon ConnectionRequest request, ParcelableConnection connection) { 191664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse == null) { 192664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mService.abort(mCall); 193664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 19472890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon mResponse.handleCreateConnectionSuccessful(request, connection); 19572890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon mResponse = null; 196664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 197664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 198664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 199664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal @Override 200664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal public void handleCreateConnectionFailed(int code, String msg) { 201664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mLastErrorCode = code; 202664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mLastErrorMsg = msg; 20369eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.d(CreateConnectionProcessor.this, "Connection failed: %d (%s)", code, msg); 20469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad attemptNextPhoneAccount(); 205664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 206664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 207664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal @Override 208664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal public void handleCreateConnectionCancelled() { 209664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse != null) { 210664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse.handleCreateConnectionCancelled(); 211664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = null; 212664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 213664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 214664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 215664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal} 216