Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2014, The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.telecomm; |
| 18 | |
Ihab Awad | 55a3428 | 2014-06-18 10:31:09 -0700 | [diff] [blame] | 19 | import android.net.Uri; |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 20 | import android.os.Handler; |
| 21 | import android.os.Message; |
Ben Gilad | c5b2269 | 2014-02-18 20:03:22 -0800 | [diff] [blame] | 22 | import android.telecomm.CallServiceDescriptor; |
Ihab Awad | 0fea3f2 | 2014-06-03 18:45:05 -0700 | [diff] [blame] | 23 | import android.telephony.DisconnectCause; |
Ihab Awad | 55a3428 | 2014-06-18 10:31:09 -0700 | [diff] [blame] | 24 | import android.telephony.PhoneNumberUtils; |
Sailesh Nepal | b6141ae | 2014-02-18 08:45:26 -0800 | [diff] [blame] | 25 | |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 26 | import com.android.telecomm.BaseRepository.LookupCallback; |
Ben Gilad | 6192561 | 2014-03-11 19:06:36 -0700 | [diff] [blame] | 27 | import com.google.android.collect.Sets; |
Santos Cordon | 766d04f | 2014-05-06 10:28:25 -0700 | [diff] [blame] | 28 | import com.google.common.collect.Maps; |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 29 | |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 30 | import java.util.ArrayList; |
Sailesh Nepal | 18386a8 | 2014-03-19 10:22:40 -0700 | [diff] [blame] | 31 | import java.util.Collection; |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 32 | import java.util.Iterator; |
| 33 | import java.util.List; |
| 34 | import java.util.Map; |
| 35 | import java.util.Set; |
| 36 | |
| 37 | /** |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 38 | * Utility class to place a call using the specified set of call-services. Each of the connection |
| 39 | * services is then attempted until either the outgoing call is placed, the attempted call is |
| 40 | * aborted, or the list is exhausted -- whichever occurs first. |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 41 | * |
Santos Cordon | 74d420b | 2014-05-07 14:38:47 -0700 | [diff] [blame] | 42 | * Except for the abort case, all other scenarios should terminate with the call notified |
Santos Cordon | 681663d | 2014-01-30 04:32:15 -0800 | [diff] [blame] | 43 | * of the result. |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 44 | */ |
| 45 | final class OutgoingCallProcessor { |
| 46 | |
| 47 | /** |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 48 | * The outgoing call this processor is tasked with placing. |
| 49 | */ |
| 50 | private final Call mCall; |
| 51 | |
| 52 | /** |
Sailesh Nepal | b6141ae | 2014-02-18 08:45:26 -0800 | [diff] [blame] | 53 | * The map of currently-available call-service implementations keyed by call-service ID. |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 54 | */ |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 55 | private final Map<String, ConnectionServiceWrapper> mConnectionServicesById = Maps.newHashMap(); |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 56 | |
| 57 | /** |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 58 | * The set of attempted connection services, used to ensure services are attempted at most once |
| 59 | * per outgoing-call attempt. |
Ben Gilad | 6192561 | 2014-03-11 19:06:36 -0700 | [diff] [blame] | 60 | */ |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 61 | private final Set<ConnectionServiceWrapper> mAttemptedConnectionServices = Sets.newHashSet(); |
Ben Gilad | 6192561 | 2014-03-11 19:06:36 -0700 | [diff] [blame] | 62 | |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 63 | private final CallServiceRepository mCallServiceRepository; |
Ben Gilad | 6192561 | 2014-03-11 19:06:36 -0700 | [diff] [blame] | 64 | |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 65 | /** |
| 66 | * The duplicate-free list of currently-available call-service descriptors. |
| 67 | */ |
| 68 | private List<CallServiceDescriptor> mCallServiceDescriptors; |
Sailesh Nepal | 18386a8 | 2014-03-19 10:22:40 -0700 | [diff] [blame] | 69 | |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 70 | /** |
Ben Gilad | c5b2269 | 2014-02-18 20:03:22 -0800 | [diff] [blame] | 71 | * The iterator over the currently-selected ordered list of call-service descriptors. |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 72 | */ |
Ben Gilad | c5b2269 | 2014-02-18 20:03:22 -0800 | [diff] [blame] | 73 | private Iterator<CallServiceDescriptor> mCallServiceDescriptorIterator; |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 74 | |
Sailesh Nepal | 5a73b03 | 2014-06-25 15:53:21 -0700 | [diff] [blame] | 75 | private OutgoingCallResponse mResultCallback; |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 76 | |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 77 | private boolean mIsAborted = false; |
| 78 | |
Ihab Awad | 0fea3f2 | 2014-06-03 18:45:05 -0700 | [diff] [blame] | 79 | private int mLastErrorCode = 0; |
| 80 | |
| 81 | private String mLastErrorMsg = null; |
| 82 | |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 83 | /** |
Ihab Awad | 55a3428 | 2014-06-18 10:31:09 -0700 | [diff] [blame] | 84 | * Persists the specified parameters and iterates through the prioritized list of call |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 85 | * services. Stops once a matching connection service is found. Calls with no matching |
| 86 | * connection service will eventually be killed by the cleanup/monitor switchboard handler. |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 87 | * |
| 88 | * @param call The call to place. |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 89 | * @param callServiceRepository |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 90 | * @param resultCallback The callback on which to return the result. |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 91 | */ |
| 92 | OutgoingCallProcessor( |
| 93 | Call call, |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 94 | CallServiceRepository callServiceRepository, |
Sailesh Nepal | 5a73b03 | 2014-06-25 15:53:21 -0700 | [diff] [blame] | 95 | OutgoingCallResponse resultCallback) { |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 96 | |
Ben Gilad | d88323b | 2014-01-29 19:03:19 -0800 | [diff] [blame] | 97 | ThreadUtil.checkOnMainThread(); |
| 98 | |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 99 | mCall = call; |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 100 | mResultCallback = resultCallback; |
| 101 | mCallServiceRepository = callServiceRepository; |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 102 | } |
| 103 | |
| 104 | /** |
| 105 | * Initiates the attempt to place the call. No-op beyond the first invocation. |
| 106 | */ |
| 107 | void process() { |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 108 | Log.v(this, "process, mIsAborted: %b", mIsAborted); |
Ben Gilad | 28e8ad6 | 2014-03-06 17:01:54 -0800 | [diff] [blame] | 109 | if (!mIsAborted) { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 110 | // Lookup connection services |
| 111 | mCallServiceRepository.lookupServices(new LookupCallback<ConnectionServiceWrapper>() { |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 112 | @Override |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 113 | public void onComplete(Collection<ConnectionServiceWrapper> services) { |
| 114 | setConnectionServices(services); |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 115 | } |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 116 | }); |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 117 | } |
Ben Gilad | 6192561 | 2014-03-11 19:06:36 -0700 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | /** |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 121 | * Aborts the attempt to place the relevant call. Intended to be invoked by |
Santos Cordon | 681663d | 2014-01-30 04:32:15 -0800 | [diff] [blame] | 122 | * switchboard through the outgoing-calls manager. |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 123 | */ |
| 124 | void abort() { |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 125 | Log.v(this, "abort"); |
Ben Gilad | 9c23411 | 2014-03-04 16:07:33 -0800 | [diff] [blame] | 126 | ThreadUtil.checkOnMainThread(); |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 127 | if (!mIsAborted && mResultCallback != null) { |
Ben Gilad | 9c23411 | 2014-03-04 16:07:33 -0800 | [diff] [blame] | 128 | mIsAborted = true; |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 129 | |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 130 | // On an abort, we need to check if we already told the connection service to place the |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 131 | // call. If so, we need to tell it to abort. |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 132 | // TODO(santoscordon): The conneciton service is saved with the call and so we have to |
| 133 | // query the call to get it, which is a bit backwards. Ideally, the connection service |
| 134 | // would be saved inside this class until the whole thing is complete and then set on |
| 135 | // the call. |
| 136 | ConnectionServiceWrapper service = mCall.getConnectionService(); |
| 137 | if (service != null) { |
| 138 | service.abort(mCall); |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 139 | } |
| 140 | |
Ihab Awad | 0fea3f2 | 2014-06-03 18:45:05 -0700 | [diff] [blame] | 141 | // We consider a deliberate abort to be a "normal" disconnect, not |
| 142 | // requiring special reporting. |
| 143 | sendResult(false, DisconnectCause.LOCAL, null); |
Ben Gilad | 9c23411 | 2014-03-04 16:07:33 -0800 | [diff] [blame] | 144 | } |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 145 | } |
| 146 | |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 147 | boolean isAborted() { |
| 148 | return mIsAborted; |
| 149 | } |
| 150 | |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 151 | /** |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 152 | * Completes the outgoing call sequence by setting the connection service on the call object. |
| 153 | * This is invoked when the connection service adapter receives positive confirmation that the |
| 154 | * connection service placed the call. |
Santos Cordon | 681663d | 2014-01-30 04:32:15 -0800 | [diff] [blame] | 155 | */ |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 156 | void handleSuccessfulCallAttempt(ConnectionServiceWrapper service) { |
Sailesh Nepal | 810735e | 2014-03-18 18:15:46 -0700 | [diff] [blame] | 157 | Log.v(this, "handleSuccessfulCallAttempt"); |
Ben Gilad | 8e55d1d | 2014-02-26 16:25:56 -0800 | [diff] [blame] | 158 | ThreadUtil.checkOnMainThread(); |
| 159 | |
| 160 | if (mIsAborted) { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 161 | service.abort(mCall); |
Ben Gilad | 8e55d1d | 2014-02-26 16:25:56 -0800 | [diff] [blame] | 162 | return; |
| 163 | } |
| 164 | |
Ihab Awad | 0fea3f2 | 2014-06-03 18:45:05 -0700 | [diff] [blame] | 165 | sendResult(true, DisconnectCause.NOT_DISCONNECTED, null); |
Santos Cordon | 681663d | 2014-01-30 04:32:15 -0800 | [diff] [blame] | 166 | } |
| 167 | |
| 168 | /** |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 169 | * Attempts the next connection service if the specified connection service is the one currently |
| 170 | * being attempted. |
Santos Cordon | 681663d | 2014-01-30 04:32:15 -0800 | [diff] [blame] | 171 | * |
Ihab Awad | 0fea3f2 | 2014-06-03 18:45:05 -0700 | [diff] [blame] | 172 | * @param errorCode The reason for the failure, one of {@link DisconnectCause}. |
| 173 | * @param errorMsg Optional text reason for the failure. |
Santos Cordon | 681663d | 2014-01-30 04:32:15 -0800 | [diff] [blame] | 174 | */ |
Ihab Awad | 0fea3f2 | 2014-06-03 18:45:05 -0700 | [diff] [blame] | 175 | void handleFailedCallAttempt(int errorCode, String errorMsg) { |
| 176 | Log.v(this, "handleFailedCallAttempt %s %s", DisconnectCause.toString(errorCode), errorMsg); |
| 177 | // Store latest error code and message. If this is our last available attempt at placing |
| 178 | // a call, these error details will be considered "the" cause of the failure. |
| 179 | mLastErrorCode = errorCode; |
| 180 | mLastErrorMsg = errorMsg; |
Ben Gilad | 28e8ad6 | 2014-03-06 17:01:54 -0800 | [diff] [blame] | 181 | if (!mIsAborted) { |
| 182 | ThreadUtil.checkOnMainThread(); |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 183 | attemptNextConnectionService(); |
Ben Gilad | 28e8ad6 | 2014-03-06 17:01:54 -0800 | [diff] [blame] | 184 | } |
Santos Cordon | 681663d | 2014-01-30 04:32:15 -0800 | [diff] [blame] | 185 | } |
| 186 | |
| 187 | /** |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 188 | * Sets the connection services to attempt for this outgoing call. |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 189 | * |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 190 | * @param services The connection services. |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 191 | */ |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 192 | private void setConnectionServices(Collection<ConnectionServiceWrapper> services) { |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 193 | mCallServiceDescriptors = new ArrayList<>(); |
| 194 | |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 195 | // Populate the list and map of call-service descriptors. |
| 196 | for (ConnectionServiceWrapper service : services) { |
| 197 | CallServiceDescriptor descriptor = service.getDescriptor(); |
Sailesh Nepal | a1b3bca | 2014-06-24 15:17:44 -0700 | [diff] [blame] | 198 | // TODO(sail): Remove once there's a way to pick the service. |
| 199 | if (descriptor.getServiceComponent().getPackageName().equals( |
| 200 | "com.google.android.talk")) { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 201 | Log.i(this, "Moving connection service %s to top of list", descriptor); |
Sailesh Nepal | a1b3bca | 2014-06-24 15:17:44 -0700 | [diff] [blame] | 202 | mCallServiceDescriptors.add(0, descriptor); |
| 203 | } else { |
| 204 | mCallServiceDescriptors.add(descriptor); |
| 205 | } |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 206 | mConnectionServicesById.put(descriptor.getConnectionServiceId(), service); |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 207 | } |
| 208 | |
Ihab Awad | 55a3428 | 2014-06-18 10:31:09 -0700 | [diff] [blame] | 209 | adjustCallServiceDescriptorsForEmergency(); |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 210 | |
Ihab Awad | 55a3428 | 2014-06-18 10:31:09 -0700 | [diff] [blame] | 211 | mCallServiceDescriptorIterator = mCallServiceDescriptors.iterator(); |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 212 | attemptNextConnectionService(); |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 213 | } |
| 214 | |
| 215 | /** |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 216 | * Attempts to place the call using the connection service specified by the next call-service |
Ihab Awad | 55a3428 | 2014-06-18 10:31:09 -0700 | [diff] [blame] | 217 | * descriptor of mCallServiceDescriptorIterator. |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 218 | */ |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 219 | private void attemptNextConnectionService() { |
| 220 | Log.v(this, "attemptNextConnectionService, mIsAborted: %b", mIsAborted); |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 221 | if (mIsAborted) { |
| 222 | return; |
| 223 | } |
| 224 | |
Evan Charlton | f02e988 | 2014-03-06 12:54:52 -0800 | [diff] [blame] | 225 | if (mCallServiceDescriptorIterator != null && mCallServiceDescriptorIterator.hasNext()) { |
Ben Gilad | c5b2269 | 2014-02-18 20:03:22 -0800 | [diff] [blame] | 226 | CallServiceDescriptor descriptor = mCallServiceDescriptorIterator.next(); |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 227 | final ConnectionServiceWrapper service = |
| 228 | mConnectionServicesById.get(descriptor.getConnectionServiceId()); |
Ben Gilad | 8e55d1d | 2014-02-26 16:25:56 -0800 | [diff] [blame] | 229 | |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 230 | if (service == null || mAttemptedConnectionServices.contains(service)) { |
| 231 | // The next connection service is either null or has already been attempted, fast |
| 232 | // forward to the next. |
| 233 | attemptNextConnectionService(); |
Santos Cordon | 681663d | 2014-01-30 04:32:15 -0800 | [diff] [blame] | 234 | } else { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 235 | mAttemptedConnectionServices.add(service); |
| 236 | mCall.setConnectionService(service); |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 237 | |
| 238 | // Increment the associated call count until we get a result. This prevents the call |
| 239 | // service from unbinding while we are using it. |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 240 | service.incrementAssociatedCallCount(); |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 241 | |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 242 | Log.i(this, "Attempting to call from %s", service.getDescriptor()); |
| 243 | service.call(mCall, new OutgoingCallResponse() { |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 244 | @Override |
Sailesh Nepal | 5a73b03 | 2014-06-25 15:53:21 -0700 | [diff] [blame] | 245 | public void onOutgoingCallSuccess() { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 246 | handleSuccessfulCallAttempt(service); |
| 247 | service.decrementAssociatedCallCount(); |
Sailesh Nepal | 5a73b03 | 2014-06-25 15:53:21 -0700 | [diff] [blame] | 248 | } |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 249 | |
Sailesh Nepal | 5a73b03 | 2014-06-25 15:53:21 -0700 | [diff] [blame] | 250 | @Override |
| 251 | public void onOutgoingCallFailure(int code, String msg) { |
| 252 | handleFailedCallAttempt(code, msg); |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 253 | service.decrementAssociatedCallCount(); |
Sailesh Nepal | 5a73b03 | 2014-06-25 15:53:21 -0700 | [diff] [blame] | 254 | } |
| 255 | |
| 256 | @Override |
| 257 | public void onOutgoingCallCancel() { |
| 258 | abort(); |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 259 | service.decrementAssociatedCallCount(); |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 260 | } |
| 261 | }); |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 262 | } |
| 263 | } else { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 264 | Log.v(this, "attemptNextConnectionService, no more service descriptors, failing"); |
Ben Gilad | c5b2269 | 2014-02-18 20:03:22 -0800 | [diff] [blame] | 265 | mCallServiceDescriptorIterator = null; |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 266 | mCall.clearConnectionService(); |
Ihab Awad | 55a3428 | 2014-06-18 10:31:09 -0700 | [diff] [blame] | 267 | sendResult(false, mLastErrorCode, mLastErrorMsg); |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 268 | } |
| 269 | } |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 270 | |
Ihab Awad | 0fea3f2 | 2014-06-03 18:45:05 -0700 | [diff] [blame] | 271 | private void sendResult(boolean wasCallPlaced, int errorCode, String errorMsg) { |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 272 | if (mResultCallback != null) { |
Sailesh Nepal | 5a73b03 | 2014-06-25 15:53:21 -0700 | [diff] [blame] | 273 | if (mIsAborted) { |
| 274 | mResultCallback.onOutgoingCallCancel(); |
| 275 | } else if (wasCallPlaced) { |
| 276 | mResultCallback.onOutgoingCallSuccess(); |
| 277 | } else { |
| 278 | mResultCallback.onOutgoingCallFailure(errorCode, errorMsg); |
| 279 | } |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 280 | mResultCallback = null; |
Santos Cordon | 682fe6b | 2014-05-20 08:56:39 -0700 | [diff] [blame] | 281 | } else { |
| 282 | Log.wtf(this, "Attempting to return outgoing result twice for call %s", mCall); |
| 283 | } |
| 284 | } |
Ihab Awad | 55a3428 | 2014-06-18 10:31:09 -0700 | [diff] [blame] | 285 | |
| 286 | // If we are possibly attempting to call a local emergency number, ensure that the |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 287 | // plain PSTN connection service, if it exists, is attempted first. |
Ihab Awad | 55a3428 | 2014-06-18 10:31:09 -0700 | [diff] [blame] | 288 | private void adjustCallServiceDescriptorsForEmergency() { |
Santos Cordon | 5924bea | 2014-06-18 06:39:51 -0700 | [diff] [blame] | 289 | for (int i = 0; i < mCallServiceDescriptors.size(); i++) { |
| 290 | if (shouldProcessAsEmergency(mCall.getHandle())) { |
Sailesh Nepal | c92c436 | 2014-07-04 18:33:21 -0700 | [diff] [blame] | 291 | if (TelephonyUtil.isPstnConnectionService(mCallServiceDescriptors.get(i))) { |
Ihab Awad | 55a3428 | 2014-06-18 10:31:09 -0700 | [diff] [blame] | 292 | mCallServiceDescriptors.add(0, mCallServiceDescriptors.remove(i)); |
| 293 | return; |
| 294 | } |
Santos Cordon | 5924bea | 2014-06-18 06:39:51 -0700 | [diff] [blame] | 295 | } else { |
| 296 | if (mCallServiceDescriptors.get(i).getServiceComponent().getPackageName().equals( |
| 297 | "com.android.telecomm.tests")) { |
| 298 | mCallServiceDescriptors.add(0, mCallServiceDescriptors.remove(i)); |
| 299 | } |
Ihab Awad | 55a3428 | 2014-06-18 10:31:09 -0700 | [diff] [blame] | 300 | } |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | private boolean shouldProcessAsEmergency(Uri handle) { |
| 305 | return PhoneNumberUtils.isPotentialLocalEmergencyNumber( |
| 306 | TelecommApp.getInstance(), handle.getSchemeSpecificPart()); |
| 307 | } |
Ben Gilad | 0bf5b91 | 2014-01-28 17:55:57 -0800 | [diff] [blame] | 308 | } |