Replace CallServiceSelectors with Subscriptions (2/3)
Remove CallServiceSelectors and replace them with comprehensive
support for Subscriptions as the means of selecting ways of making
phone calls. After this change, a ConnectionService is not a
semantically meaningful "way of making a call" -- it's more like the
mechanism whereby the Android system communicates with a 3rd party
process to ask for phone services. We anticipate each process having
only one ConnectionService.
Change-Id: I11258709b014d2fd3eed98a521227c200027018f
diff --git a/src/com/android/telecomm/OutgoingCallProcessor.java b/src/com/android/telecomm/OutgoingCallProcessor.java
index 366307c..625366f 100644
--- a/src/com/android/telecomm/OutgoingCallProcessor.java
+++ b/src/com/android/telecomm/OutgoingCallProcessor.java
@@ -16,15 +16,15 @@
package com.android.telecomm;
-import android.content.ComponentName;
+import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.telecomm.CallServiceDescriptor;
import android.telephony.DisconnectCause;
+import android.telephony.PhoneNumberUtils;
import com.android.telecomm.BaseRepository.LookupCallback;
import com.google.android.collect.Sets;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import java.util.ArrayList;
@@ -70,8 +70,6 @@
private final CallServiceRepository mCallServiceRepository;
- private final CallServiceSelectorRepository mSelectorRepository;
-
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -93,13 +91,6 @@
*/
private Iterator<CallServiceDescriptor> mCallServiceDescriptorIterator;
- /**
- * The list of currently-available call-service selector implementations.
- */
- private Collection<CallServiceSelectorWrapper> mSelectors;
-
- private Iterator<CallServiceSelectorWrapper> mSelectorIterator;
-
private AsyncResultCallback<Boolean> mResultCallback;
private boolean mIsAborted = false;
@@ -109,21 +100,17 @@
private String mLastErrorMsg = null;
/**
- * Persists the specified parameters and iterates through the prioritized list of selectors
- * passing to each selector (read-only versions of) the call object and all available call-
- * service descriptors. Stops once a matching selector is found. Calls with no matching
- * selectors will eventually be killed by the cleanup/monitor switchboard handler, which will
- * in turn call the abort method of this processor via {@link OutgoingCallsManager}.
+ * Persists the specified parameters and iterates through the prioritized list of call
+ * services. Stops once a matching call service is found. Calls with no matching
+ * call service will eventually be killed by the cleanup/monitor switchboard handler.
*
* @param call The call to place.
* @param callServiceRepository
- * @param selectorRepository
* @param resultCallback The callback on which to return the result.
*/
OutgoingCallProcessor(
Call call,
CallServiceRepository callServiceRepository,
- CallServiceSelectorRepository selectorRepository,
AsyncResultCallback<Boolean> resultCallback) {
ThreadUtil.checkOnMainThread();
@@ -131,7 +118,6 @@
mCall = call;
mResultCallback = resultCallback;
mCallServiceRepository = callServiceRepository;
- mSelectorRepository = selectorRepository;
}
/**
@@ -150,20 +136,6 @@
setCallServices(services);
}
});
-
- if (mCall.getCallServiceSelector() == null) {
- // Lookup selectors
- mSelectorRepository.lookupServices(
- new LookupCallback<CallServiceSelectorWrapper>() {
- @Override
- public void onComplete(
- Collection<CallServiceSelectorWrapper> selectors) {
- setSelectors(selectors);
- }
- });
- } else {
- setSelectors(ImmutableList.of(mCall.getCallServiceSelector()));
- }
}
}
@@ -235,23 +207,6 @@
}
/**
- * Persists the ordered-list of call-service descriptor as selected by the current selector and
- * starts iterating through the corresponding call services continuing the attempt to place the
- * call.
- *
- * @param descriptors The (ordered) list of call-service descriptor.
- */
- void processSelectedCallServices(List<CallServiceDescriptor> descriptors) {
- Log.v(this, "processSelectedCallServices");
- if (descriptors == null || descriptors.isEmpty()) {
- attemptNextSelector();
- } else if (mCallServiceDescriptorIterator == null) {
- mCallServiceDescriptorIterator = descriptors.iterator();
- attemptNextCallService();
- }
- }
-
- /**
* Sets the call services to attempt for this outgoing call.
*
* @param callServices The call services.
@@ -267,96 +222,15 @@
mCallServicesById.put(descriptor.getCallServiceId(), callService);
}
- onLookupComplete();
- }
+ adjustCallServiceDescriptorsForEmergency();
- /**
- * Sets the selectors to attemnpt for this outgoing call.
- *
- * @param selectors The call-service selectors.
- */
- private void setSelectors(Collection<CallServiceSelectorWrapper> selectors) {
- mSelectors = adjustForEmergencyCalls(selectors);
- onLookupComplete();
- }
-
- private void onLookupComplete() {
- if (!mIsAborted && mSelectors != null && mCallServiceDescriptors != null) {
- if (mSelectorIterator == null) {
- mSelectorIterator = mSelectors.iterator();
- attemptNextSelector();
- }
- }
- }
-
- /**
- * Updates the specified collection of selectors to accomodate for emergency calls and any
- * preferred selectors specified in the call object.
- *
- * @param selectors The selectors found through the selector repository.
- */
- private Collection<CallServiceSelectorWrapper> adjustForEmergencyCalls(
- Collection<CallServiceSelectorWrapper> selectors) {
- boolean useEmergencySelector =
- EmergencyCallServiceSelector.shouldUseSelector(mCall.getHandle());
- Log.d(this, "processNewOutgoingCall, isEmergency=%b", useEmergencySelector);
-
- if (useEmergencySelector) {
- // This is potentially an emergency call so add the emergency selector before the
- // other selectors.
- ImmutableList.Builder<CallServiceSelectorWrapper> selectorsBuilder =
- ImmutableList.builder();
-
- ComponentName componentName = new ComponentName(
- TelecommApp.getInstance(), EmergencyCallServiceSelector.class);
- CallServiceSelectorWrapper emergencySelector =
- new CallServiceSelectorWrapper(
- componentName.flattenToShortString(),
- componentName,
- CallsManager.getInstance());
-
- selectorsBuilder.add(emergencySelector);
- selectorsBuilder.addAll(selectors);
- selectors = selectorsBuilder.build();
- }
-
- return selectors;
- }
-
- /**
- * Attempts to place the call using the next selector, no-op if no other selectors
- * are available.
- */
- private void attemptNextSelector() {
- Log.v(this, "attemptNextSelector, mIsAborted: %b", mIsAborted);
- if (mIsAborted) {
- return;
- }
-
- if (mSelectorIterator.hasNext()) {
- CallServiceSelectorWrapper selector = mSelectorIterator.next();
- mCall.setCallServiceSelector(selector);
- selector.select(mCall, mCallServiceDescriptors,
- new AsyncResultCallback<List<CallServiceDescriptor>>() {
- @Override
- public void onResult(
- List<CallServiceDescriptor> descriptors,
- int errorCode, String errorMsg) {
- processSelectedCallServices(descriptors);
- }
- });
- } else {
- Log.v(this, "attemptNextSelector, no more selectors, failing");
- mCall.clearCallServiceSelector();
- sendResult(false, mLastErrorCode, mLastErrorMsg);
- }
+ mCallServiceDescriptorIterator = mCallServiceDescriptors.iterator();
+ attemptNextCallService();
}
/**
* Attempts to place the call using the call service specified by the next call-service
- * descriptor of mCallServiceDescriptorIterator. If there are no more call services to
- * attempt, the process continues to the next call-service selector via
- * {@link #attemptNextSelector}.
+ * descriptor of mCallServiceDescriptorIterator.
*/
private void attemptNextCallService() {
Log.v(this, "attemptNextCallService, mIsAborted: %b", mIsAborted);
@@ -397,9 +271,10 @@
});
}
} else {
+ Log.v(this, "attemptNextCallService, no more service descriptors, failing");
mCallServiceDescriptorIterator = null;
mCall.clearCallService();
- attemptNextSelector();
+ sendResult(false, mLastErrorCode, mLastErrorMsg);
}
}
@@ -413,4 +288,22 @@
Log.wtf(this, "Attempting to return outgoing result twice for call %s", mCall);
}
}
+
+ // If we are possibly attempting to call a local emergency number, ensure that the
+ // plain PSTN call service, if it exists, is attempted first.
+ private void adjustCallServiceDescriptorsForEmergency() {
+ if (shouldProcessAsEmergency(mCall.getHandle())) {
+ for (int i = 0; i < mCallServiceDescriptors.size(); i++) {
+ if (TelephonyUtil.isPstnCallService(mCallServiceDescriptors.get(i))) {
+ mCallServiceDescriptors.add(0, mCallServiceDescriptors.remove(i));
+ return;
+ }
+ }
+ }
+ }
+
+ private boolean shouldProcessAsEmergency(Uri handle) {
+ return PhoneNumberUtils.isPotentialLocalEmergencyNumber(
+ TelecommApp.getInstance(), handle.getSchemeSpecificPart());
+ }
}