Wiring up the Telecomm abort flow.
Change-Id: Ie9de03507fabe09c09347b37355c8fe5ce4492b0
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index 2babb4e..f40d4ea 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -169,14 +169,14 @@
}
/**
- * Aborts ongoing attempts to connect this call. No-op once the call is connected or has been
- * disconnected. See {@link #disconnect} for already-connected calls.
+ * Aborts ongoing attempts to connect this call. Only applicable to {@link CallState#NEW}
+ * outgoing calls. See {@link #disconnect} for already-connected calls.
*/
void abort() {
- if (mState == CallState.NEW ||
- mState == CallState.DIALING ||
- mState == CallState.RINGING) {
-
+ if (mState == CallState.NEW) {
+ if (mCallService != null) {
+ mCallService.abort(mId);
+ }
clearCallService();
clearCallServiceSelector();
mState = CallState.ABORTED;
diff --git a/src/com/android/telecomm/CallServiceAdapter.java b/src/com/android/telecomm/CallServiceAdapter.java
index f602d50..8daa16e 100644
--- a/src/com/android/telecomm/CallServiceAdapter.java
+++ b/src/com/android/telecomm/CallServiceAdapter.java
@@ -46,9 +46,16 @@
/** Used to run code (e.g. messages, Runnables) on the main (UI) thread. */
private final Handler mHandler = new Handler(Looper.getMainLooper());
- /** The set of pending incoming call IDs. Contains the call IDs for which we are expecting
- * details via {@link #handleIncomingCall}. If {@link #handleIncomingCall} is invoked for a call
- * ID that is not in this set, it will be ignored.
+ /**
+ * The set of pending outgoing call IDs. Any {@link #handleSuccessfulOutgoingCall} and
+ * {@link #handleFailedOutgoingCall} invocations with a call ID that is not in this set
+ * are ignored.
+ */
+ private final Set<String> mPendingOutgoingCallIds = Sets.newHashSet();
+
+ /**
+ * The set of pending incoming call IDs. Any {@link #handleIncomingCall} invocations with
+ * a call ID not in this set are ignored.
*/
private final Set<String> mPendingIncomingCallIds = Sets.newHashSet();
@@ -80,7 +87,7 @@
mIncomingCallsManager.handleSuccessfulIncomingCall(callInfo);
} else {
Log.wtf(CallServiceAdapter.this,
- "Received details for an unknown incoming call %s", callInfo);
+ "Unknown incoming call: %s", callInfo);
}
}
});
@@ -91,7 +98,13 @@
checkValidCallId(callId);
mHandler.post(new Runnable() {
@Override public void run() {
- mOutgoingCallsManager.handleSuccessfulCallAttempt(callId);
+ if (mPendingOutgoingCallIds.remove(callId)) {
+ mOutgoingCallsManager.handleSuccessfulCallAttempt(callId);
+ } else {
+ // TODO(gilad): Figure out how to wire up the callService.abort() call.
+ Log.wtf(CallServiceAdapter.this,
+ "Unknown outgoing call: %s", callId);
+ }
}
});
}
@@ -101,7 +114,12 @@
checkValidCallId(callId);
mHandler.post(new Runnable() {
@Override public void run() {
- mOutgoingCallsManager.handleFailedCallAttempt(callId, reason);
+ if (mPendingOutgoingCallIds.remove(callId)) {
+ mOutgoingCallsManager.handleFailedCallAttempt(callId, reason);
+ } else {
+ Log.wtf(CallServiceAdapter.this,
+ "Unknown outgoing call: %s", callId);
+ }
}
});
}
@@ -137,6 +155,8 @@
}
/** {@inheritDoc} */
+ // TODO(gilad): Ensure that any communication from the underlying ICallService
+ // implementation is expected (or otherwise suppressed at the adapter level).
@Override public void setDisconnected(final String callId) {
checkValidCallId(callId);
mHandler.post(new Runnable() {
@@ -147,6 +167,26 @@
}
/**
+ * Adds the specified call ID to the list of pending outgoing call IDs.
+ * TODO(gilad): Consider passing the call processor (instead of the ID) both here and in the
+ * remove case (same for incoming) such that the detour via the *CallsManager can be avoided.
+ *
+ * @param callId The ID of the call.
+ */
+ void addPendingOutgoingCallId(String callId) {
+ mPendingOutgoingCallIds.add(callId);
+ }
+
+ /**
+ * Removes the specified call ID from the list of pending outgoing call IDs.
+ *
+ * @param callId The ID of the call.
+ */
+ void removePendingOutgoingCallId(String callId) {
+ mPendingOutgoingCallIds.remove(callId);
+ }
+
+ /**
* Adds a call ID to the list of pending incoming call IDs. Only calls with call IDs in the
* list will be handled by {@link #handleIncomingCall}.
*
@@ -157,7 +197,7 @@
}
/**
- * Removed a call ID from the list of pending incoming call IDs.
+ * Removes the specified call ID from the list of pending incoming call IDs.
*
* @param callId The ID of the call.
*/
diff --git a/src/com/android/telecomm/CallServiceWrapper.java b/src/com/android/telecomm/CallServiceWrapper.java
index 94be7c8..15ec20d 100644
--- a/src/com/android/telecomm/CallServiceWrapper.java
+++ b/src/com/android/telecomm/CallServiceWrapper.java
@@ -24,6 +24,7 @@
import android.telecomm.CallServiceDescriptor;
import android.telecomm.ICallService;
import android.telecomm.ICallServiceAdapter;
+import android.telecomm.ICallServiceProvider;
/**
* Wrapper for {@link ICallService}s, handles binding to {@link ICallService} and keeps track of
@@ -92,11 +93,25 @@
/** See {@link ICallService#call}. */
public void call(CallInfo callInfo) {
+ String callId = callInfo.getId();
if (isServiceValid("call")) {
try {
mServiceInterface.call(callInfo);
+ mAdapter.addPendingOutgoingCallId(callId);
} catch (RemoteException e) {
- Log.e(this, e, "Failed to place call " + callInfo.getId() + ".");
+ Log.e(this, e, "Failed to place call " + callId + ".");
+ }
+ }
+ }
+
+ /** See {@link ICallService#abort}. */
+ public void abort(String callId) {
+ mAdapter.removePendingOutgoingCallId(callId);
+ if (isServiceValid("abort")) {
+ try {
+ mServiceInterface.abort(callId);
+ } catch (RemoteException e) {
+ Log.e(this, e, "Failed to abort call %s", callId);
}
}
}
diff --git a/src/com/android/telecomm/OutgoingCallProcessor.java b/src/com/android/telecomm/OutgoingCallProcessor.java
index 42a16c6..4d21280 100644
--- a/src/com/android/telecomm/OutgoingCallProcessor.java
+++ b/src/com/android/telecomm/OutgoingCallProcessor.java
@@ -68,7 +68,7 @@
private final Map<String, CallServiceWrapper> mCallServicesById = Maps.newHashMap();
/**
- * The set of currently-available call-service selector implementations.
+ * The list of currently-available call-service selector implementations.
*/
private final List<ICallServiceSelector> mSelectors;
@@ -111,9 +111,6 @@
ThreadUtil.checkOnMainThread();
- Preconditions.checkNotNull(callServices);
- Preconditions.checkNotNull(selectors);
-
mCall = call;
mSelectors = selectors;
mOutgoingCallsManager = outgoingCallsManager;
@@ -132,17 +129,14 @@
* Initiates the attempt to place the call. No-op beyond the first invocation.
*/
void process() {
- ThreadUtil.checkOnMainThread();
+ if (!mIsAborted) {
+ // Only process un-aborted calls.
+ ThreadUtil.checkOnMainThread();
- if (mSelectors.isEmpty() || mCallServiceDescriptors.isEmpty()) {
- // TODO(gilad): Consider adding a failure message/type to differentiate the various
- // cases, or potentially throw an exception in this case.
- // TODO(gilad): Perform this check all the way up in switchboard to short-circuit
- // the current detour.
- mOutgoingCallsManager.handleFailedOutgoingCall(mCall);
- } else if (mSelectorIterator == null) {
- mSelectorIterator = mSelectors.iterator();
- attemptNextSelector();
+ if (mSelectorIterator == null) {
+ mSelectorIterator = mSelectors.iterator();
+ attemptNextSelector();
+ }
}
}
@@ -154,9 +148,6 @@
ThreadUtil.checkOnMainThread();
if (!mIsAborted) {
mCall.abort();
-
- // TODO(gilad): Add logic to notify the relevant call service and/or selector.
-
mIsAborted = true;
}
}
@@ -185,11 +176,13 @@
* @param reason The call-service supplied reason for the failed call attempt.
*/
void handleFailedCallAttempt(String reason) {
- ThreadUtil.checkOnMainThread();
+ if (!mIsAborted) {
+ ThreadUtil.checkOnMainThread();
- mCall.clearCallService();
- mCall.clearCallServiceSelector();
- attemptNextCallService();
+ mCall.clearCallService();
+ mCall.clearCallServiceSelector();
+ attemptNextCallService();
+ }
}
/**