CreateConnectionProcessor.java revision 664837f9a8a98f98876417a0bfff64834e8032fa
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 19664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport android.content.ComponentName; 20664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport android.net.Uri; 21664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport android.telephony.DisconnectCause; 22664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport android.telephony.PhoneNumberUtils; 23664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport android.telecomm.ConnectionRequest; 24664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 25664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.ArrayList; 26664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.Iterator; 27664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.List; 28664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalimport java.util.Map; 29664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 30664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal/** 31664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * This class creates connections to place new outgoing calls to attached to an existing incoming 32664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * call. In either case, this class cycles through a set of connection services until: 33664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * - a connection service returns a newly created connection in which case the call is displayed 34664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * to the user 35664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal * - a connection service cancels the process, in which case the call is aborted 36664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal */ 37664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalfinal class CreateConnectionProcessor { 38664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final Call mCall; 39664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final ConnectionServiceRepository mRepository; 40664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private List<ComponentName> mServiceComponentNames; 41664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private Iterator<ComponentName> mServiceComponentNameIterator; 42664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private CreateConnectionResponse mResponse; 43664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private int mLastErrorCode = DisconnectCause.ERROR_UNSPECIFIED; 44664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private String mLastErrorMsg; 45664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 46664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal CreateConnectionProcessor( 47664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Call call, ConnectionServiceRepository repository, CreateConnectionResponse response) { 48664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall = call; 49664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mRepository = repository; 50664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = response; 51664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 52664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 53664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal void process() { 54664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "process"); 55664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 56664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mServiceComponentNames = new ArrayList<>(); 57664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 58664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // TODO(sail): Remove once there's a way to pick the service. 59664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal ArrayList<ComponentName> priorityComponents = new ArrayList<>(); 60664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal priorityComponents.add(new ComponentName("com.android.phone", 61664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal "com.android.services.telephony.sip.SipConnectionService")); 62664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal priorityComponents.add(new ComponentName("com.google.android.talk", 63664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal "com.google.android.apps.babel.telephony.TeleConnectionService")); 64664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal priorityComponents.add(new ComponentName("com.android.telecomm.tests", 65664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal "com.android.telecomm.testapps.TestConnectionService")); 66664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 67664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal for (ConnectionServiceWrapper service : mRepository.lookupServices()) { 68664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal ComponentName serviceName = service.getComponentName(); 69664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (priorityComponents.contains(serviceName)) { 70664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.i(this, "Moving connection service %s to top of list", serviceName); 71664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mServiceComponentNames .add(0, serviceName); 72664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 73664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mServiceComponentNames.add(serviceName); 74664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 75664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 76664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 77664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal adjustComponentNamesForEmergency(); 78664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mServiceComponentNameIterator = mServiceComponentNames.iterator(); 79664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal attemptNextConnectionService(); 80664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 81664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 82664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal void abort() { 83664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "abort"); 84664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 85664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // Clear the response first to prevent attemptNextConnectionService from attempting any 86664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // more services. 87664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal CreateConnectionResponse response = mResponse; 88664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = null; 89664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 90664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal ConnectionServiceWrapper service = mCall.getConnectionService(); 91664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (service != null) { 92664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal service.abort(mCall); 93664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.clearConnectionService(); 94664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 95664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (response != null) { 96664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal response.handleCreateConnectionCancelled(); 97664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 98664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 99664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 100664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private void attemptNextConnectionService() { 101664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "attemptNextConnectionService"); 102664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 103664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse != null && mServiceComponentNameIterator.hasNext()) { 104664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal ComponentName component = mServiceComponentNameIterator.next(); 105664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal ConnectionServiceWrapper service = mRepository.getService(component); 106664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (service == null) { 107664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal attemptNextConnectionService(); 108664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 109664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.setConnectionService(service); 110664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.i(this, "Attempting to call from %s", service.getComponentName()); 111664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal service.createConnection(mCall, new Response(service)); 112664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 113664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 114664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Log.v(this, "attemptNextConnectionService, no more services, failing"); 115664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse != null) { 116664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse.handleCreateConnectionFailed(mLastErrorCode, mLastErrorMsg); 117664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = null; 118664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mCall.clearConnectionService(); 119664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 120664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 121664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 122664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 123664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // If we are possibly attempting to call a local emergency number, ensure that the 124664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal // plain PSTN connection service, if it exists, is attempted first. 125664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private void adjustComponentNamesForEmergency() { 126664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (shouldProcessAsEmergency(mCall.getHandle())) { 127664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal for (int i = 0; i < mServiceComponentNames.size(); i++) { 128664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (TelephonyUtil.isPstnComponentName(mServiceComponentNames.get(i))) { 129664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mServiceComponentNames.add(0, mServiceComponentNames.remove(i)); 130664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal return; 131664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 132664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 133664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 134664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 135664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 136664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private boolean shouldProcessAsEmergency(Uri handle) { 137664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal return handle != null && PhoneNumberUtils.isPotentialLocalEmergencyNumber( 138664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal TelecommApp.getInstance(), handle.getSchemeSpecificPart()); 139664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 140664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 141664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private class Response implements CreateConnectionResponse { 142664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal private final ConnectionServiceWrapper mService; 143664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 144664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal Response(ConnectionServiceWrapper service) { 145664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mService = service; 146664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 147664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 148664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal @Override 149664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal public void handleCreateConnectionSuccessful(ConnectionRequest request) { 150664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse == null) { 151664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mService.abort(mCall); 152664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } else { 153664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse.handleCreateConnectionSuccessful(request); 154664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse= null; 155664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 156664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 157664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 158664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal @Override 159664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal public void handleCreateConnectionFailed(int code, String msg) { 160664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mLastErrorCode = code; 161664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mLastErrorMsg = msg; 162664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal attemptNextConnectionService(); 163664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 164664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal 165664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal @Override 166664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal public void handleCreateConnectionCancelled() { 167664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal if (mResponse != null) { 168664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse.handleCreateConnectionCancelled(); 169664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal mResponse = null; 170664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 171664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 172664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal } 173664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal} 174