CreateConnectionProcessor.java revision 69eb0f582babcedc1dc5e6613a27867be6e8d0e0
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 1969eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awadimport android.telecomm.PhoneAccount; 20664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport android.telephony.DisconnectCause; 21664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport android.telecomm.ConnectionRequest; 22664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 23664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.ArrayList; 24664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.Iterator; 25664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.List; 26664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 27664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal/** 28664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * This class creates connections to place new outgoing calls to attached to an existing incoming 29664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * call. In either case, this class cycles through a set of connection services until: 30664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * - a connection service returns a newly created connection in which case the call is displayed 31664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * to the user 32664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * - a connection service cancels the process, in which case the call is aborted 33664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal */ 34664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalfinal class CreateConnectionProcessor { 35664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final Call mCall; 36664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final ConnectionServiceRepository mRepository; 3769eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad private List<PhoneAccount> mPhoneAccounts; 3869eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad private Iterator<PhoneAccount> mPhoneAccountIterator; 39664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private CreateConnectionResponse mResponse; 40664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private int mLastErrorCode = DisconnectCause.ERROR_UNSPECIFIED; 41664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private String mLastErrorMsg; 42664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 43664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal CreateConnectionProcessor( 44664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Call call, ConnectionServiceRepository repository, CreateConnectionResponse response) { 45664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall = call; 46664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mRepository = repository; 47664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = response; 48664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 49664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 50664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal void process() { 51664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "process"); 5269eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad mPhoneAccounts = new ArrayList<>(); 5369eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad if (mCall.getPhoneAccount() != null) { 5469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad mPhoneAccounts.add(mCall.getPhoneAccount()); 55664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 5669eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad adjustPhoneAccountsForEmergency(); 5769eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad mPhoneAccountIterator = mPhoneAccounts.iterator(); 5869eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad attemptNextPhoneAccount(); 59664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 60664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 61664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal void abort() { 62664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "abort"); 63664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 64664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // Clear the response first to prevent attemptNextConnectionService from attempting any 65664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // more services. 66664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal CreateConnectionResponse response = mResponse; 67664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = null; 68664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 69664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal ConnectionServiceWrapper service = mCall.getConnectionService(); 70664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (service != null) { 71664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal service.abort(mCall); 72664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.clearConnectionService(); 73664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 74664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (response != null) { 75664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal response.handleCreateConnectionCancelled(); 76664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 77664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 78664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 7969eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad private void attemptNextPhoneAccount() { 8069eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.v(this, "attemptNextPhoneAccount"); 81664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 8269eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad if (mResponse != null && mPhoneAccountIterator.hasNext()) { 8369eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad PhoneAccount account = mPhoneAccountIterator.next(); 8469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.i(this, "Trying account %s", account); 8569eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad ConnectionServiceWrapper service = mRepository.getService(account.getComponentName()); 86664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (service == null) { 8769eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.i(this, "Found no connection service for account %s", account); 8869eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad attemptNextPhoneAccount(); 89664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 9069eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad mCall.setPhoneAccount(account); 91664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.setConnectionService(service); 92664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.i(this, "Attempting to call from %s", service.getComponentName()); 93664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal service.createConnection(mCall, new Response(service)); 94664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 95664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 9669eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.v(this, "attemptNextPhoneAccount, no more accounts, failing"); 97664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse != null) { 98664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse.handleCreateConnectionFailed(mLastErrorCode, mLastErrorMsg); 99664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = null; 100664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.clearConnectionService(); 101664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 102664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 103664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 104664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 105664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // If we are possibly attempting to call a local emergency number, ensure that the 10669eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad // plain PSTN connection services are listed, and nothing else. 10769eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad private void adjustPhoneAccountsForEmergency() { 10869eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad if (TelephonyUtil.shouldProcessAsEmergency(TelecommApp.getInstance(), mCall.getHandle())) { 10969eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.i(this, "Emergency number detected"); 11069eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad mPhoneAccounts.clear(); 11169eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad List<PhoneAccount> allAccounts = TelecommApp.getInstance().getPhoneAccountRegistrar() 11269eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad .getEnabledPhoneAccounts(); 11369eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad for (int i = 0; i < allAccounts.size(); i++) { 11469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad if (TelephonyUtil.isPstnComponentName(allAccounts.get(i).getComponentName())) { 11569eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.i(this, "Will try PSTN account %s for emergency", allAccounts.get(i)); 11669eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad mPhoneAccounts.add(allAccounts.get(i)); 117664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 118664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 119664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 120664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 121664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 122664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private class Response implements CreateConnectionResponse { 123664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final ConnectionServiceWrapper mService; 124664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 125664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Response(ConnectionServiceWrapper service) { 126664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mService = service; 127664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 128664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 129664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal @Override 130664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal public void handleCreateConnectionSuccessful(ConnectionRequest request) { 131664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse == null) { 132664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mService.abort(mCall); 133664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 134664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse.handleCreateConnectionSuccessful(request); 135664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse= null; 136664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 137664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 138664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 139664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal @Override 140664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal public void handleCreateConnectionFailed(int code, String msg) { 141664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mLastErrorCode = code; 142664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mLastErrorMsg = msg; 14369eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad Log.d(CreateConnectionProcessor.this, "Connection failed: %d (%s)", code, msg); 14469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad attemptNextPhoneAccount(); 145664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 146664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 147664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal @Override 148664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal public void handleCreateConnectionCancelled() { 149664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse != null) { 150664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse.handleCreateConnectionCancelled(); 151664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = null; 152664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 153664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 154664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 155664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal} 156