DO NOT MERGE. Implement connection error dialogs (2/4)
Implement reporting of connection errors from ConnectionServices through
Telecomm to the InCallUI.
Bug: 15195720
Bug: 15117141
Change-Id: Idbd822a4eed897676663da008071c6050cc79616
(cherry picked from commit a3cb9e34db5952f0852c1a3230870cc6e378f246)
diff --git a/src/com/android/telecomm/AsyncResultCallback.java b/src/com/android/telecomm/AsyncResultCallback.java
index d059c6c..b6e0de5 100644
--- a/src/com/android/telecomm/AsyncResultCallback.java
+++ b/src/com/android/telecomm/AsyncResultCallback.java
@@ -20,5 +20,5 @@
* Generic result interface for use with async method callback.
*/
interface AsyncResultCallback<T> {
- void onResult(T param1);
+ void onResult(T result, int errorCode, String errorMsg);
}
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index cd64ff8..a699f02 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -55,7 +55,7 @@
*/
interface Listener {
void onSuccessfulOutgoingCall(Call call);
- void onFailedOutgoingCall(Call call, boolean isAborted);
+ void onFailedOutgoingCall(Call call, boolean isAborted, int errorCode, String errorMsg);
void onSuccessfulIncomingCall(Call call, CallInfo callInfo);
void onFailedIncomingCall(Call call);
void onRequestingRingback(Call call, boolean requestingRingback);
@@ -500,11 +500,12 @@
Switchboard.getInstance().getSelectorRepository(),
new AsyncResultCallback<Boolean>() {
@Override
- public void onResult(Boolean wasCallPlaced) {
+ public void onResult(Boolean wasCallPlaced, int errorCode, String errorMsg) {
if (wasCallPlaced) {
handleSuccessfulOutgoing();
} else {
- handleFailedOutgoing(mOutgoingCallProcessor.isAborted());
+ handleFailedOutgoing(
+ mOutgoingCallProcessor.isAborted(), errorCode, errorMsg);
}
mOutgoingCallProcessor = null;
}
@@ -519,10 +520,10 @@
}
}
- void handleFailedOutgoing(boolean isAborted) {
+ void handleFailedOutgoing(boolean isAborted, int errorCode, String errorMsg) {
// TODO(santoscordon): Replace this with state transitions related to "connecting".
for (Listener l : mListeners) {
- l.onFailedOutgoingCall(this, isAborted);
+ l.onFailedOutgoingCall(this, isAborted, errorCode, errorMsg);
}
clearCallService();
diff --git a/src/com/android/telecomm/CallServiceSelectorWrapper.java b/src/com/android/telecomm/CallServiceSelectorWrapper.java
index 7cc01a2..6ee73d2 100644
--- a/src/com/android/telecomm/CallServiceSelectorWrapper.java
+++ b/src/com/android/telecomm/CallServiceSelectorWrapper.java
@@ -27,6 +27,7 @@
import android.telecomm.CallInfo;
import android.telecomm.CallServiceDescriptor;
import android.telecomm.TelecommConstants;
+import android.telephony.DisconnectCause;
import com.android.internal.os.SomeArgs;
import com.android.internal.telecomm.ICallServiceSelector;
@@ -61,7 +62,7 @@
(List<CallServiceDescriptor>) args.arg2;
mCallIdMapper.removeCall(callId);
- mPendingSelects.remove(callId).onResult(descriptors);
+ mPendingSelects.remove(callId).onResult(descriptors, 0, null);
} else {
Log.w(this, "setSelectedCallServices: unknown call: %s, id: %s",
callId, args.arg1);
@@ -189,13 +190,14 @@
mSelectorInterface.select(callInfo, descriptors);
} catch (RemoteException e) {
mCallIdMapper.removeCall(call);
- mPendingSelects.get(callId).onResult(null);
+ mPendingSelects.get(callId).onResult(
+ null, DisconnectCause.ERROR_UNSPECIFIED, e.toString());
}
}
@Override
public void onFailure() {
- resultCallback.onResult(null);
+ resultCallback.onResult(null, DisconnectCause.ERROR_UNSPECIFIED, null);
}
};
diff --git a/src/com/android/telecomm/CallServiceWrapper.java b/src/com/android/telecomm/CallServiceWrapper.java
index 41a80e5..d09c52a 100644
--- a/src/com/android/telecomm/CallServiceWrapper.java
+++ b/src/com/android/telecomm/CallServiceWrapper.java
@@ -25,7 +25,9 @@
import android.telecomm.CallInfo;
import android.telecomm.CallService;
import android.telecomm.CallServiceDescriptor;
+import android.telecomm.ConnectionRequest;
import android.telecomm.TelecommConstants;
+import android.telephony.DisconnectCause;
import com.android.internal.os.SomeArgs;
import com.android.internal.telecomm.ICallService;
@@ -35,6 +37,8 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
+import org.apache.http.conn.ClientConnectionRequest;
+
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -80,7 +84,7 @@
case MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL: {
String callId = (String) msg.obj;
if (mPendingOutgoingCalls.containsKey(callId)) {
- mPendingOutgoingCalls.remove(callId).onResult(true);
+ mPendingOutgoingCalls.remove(callId).onResult(true, 0, null);
} else {
Log.w(this, "handleSuccessfulOutgoingCall, unknown call: %s", callId);
}
@@ -90,11 +94,13 @@
SomeArgs args = (SomeArgs) msg.obj;
try {
String callId = (String) args.arg1;
- String reason = (String) args.arg2;
+ int statusCode = args.argi1;
+ String statusMsg = (String) args.arg2;
// TODO(santoscordon): Do something with 'reason' or get rid of it.
if (mPendingOutgoingCalls.containsKey(callId)) {
- mPendingOutgoingCalls.remove(callId).onResult(false);
+ mPendingOutgoingCalls.remove(callId).onResult(
+ false, statusCode, statusMsg);
mCallIdMapper.removeCall(callId);
} else {
Log.w(this, "handleFailedOutgoingCall, unknown call: %s", callId);
@@ -194,12 +200,16 @@
/** {@inheritDoc} */
@Override
- public void handleFailedOutgoingCall(String callId, String reason) {
- mCallIdMapper.checkValidCallId(callId);
- Log.d(this, "handleFailedOutgoingCall %s", callId);
+ public void handleFailedOutgoingCall(
+ ConnectionRequest request,
+ int errorCode,
+ String errorMsg) {
+ mCallIdMapper.checkValidCallId(request.getCallId());
+ Log.d(this, "handleFailedOutgoingCall %s", request.getCallId());
SomeArgs args = SomeArgs.obtain();
- args.arg1 = callId;
- args.arg2 = reason;
+ args.arg1 = request.getCallId();
+ args.argi1 = errorCode;
+ args.arg2 = errorMsg;
mHandler.obtainMessage(MSG_HANDLE_FAILED_OUTGOING_CALL, args).sendToTarget();
}
@@ -325,13 +335,14 @@
CallInfo callInfo = call.toCallInfo(callId);
mServiceInterface.call(callInfo);
} catch (RemoteException e) {
- mPendingOutgoingCalls.remove(callId).onResult(false);
+ mPendingOutgoingCalls.remove(callId).onResult(
+ false, DisconnectCause.ERROR_UNSPECIFIED, e.toString());
}
}
@Override
public void onFailure() {
- resultCallback.onResult(false);
+ resultCallback.onResult(false, DisconnectCause.ERROR_UNSPECIFIED, null);
}
};
@@ -487,7 +498,7 @@
AsyncResultCallback<Boolean> outgoingResultCallback =
mPendingOutgoingCalls.remove(mCallIdMapper.getCallId(call));
if (outgoingResultCallback != null) {
- outgoingResultCallback.onResult(false);
+ outgoingResultCallback.onResult(false, DisconnectCause.ERROR_UNSPECIFIED, null);
}
mCallIdMapper.removeCall(call);
@@ -516,7 +527,7 @@
private void handleCallServiceDeath() {
if (!mPendingOutgoingCalls.isEmpty()) {
for (AsyncResultCallback<Boolean> callback : mPendingOutgoingCalls.values()) {
- callback.onResult(false);
+ callback.onResult(false, DisconnectCause.ERROR_UNSPECIFIED, null);
}
mPendingOutgoingCalls.clear();
}
diff --git a/src/com/android/telecomm/CallsManager.java b/src/com/android/telecomm/CallsManager.java
index a2aa045..819ed34 100644
--- a/src/com/android/telecomm/CallsManager.java
+++ b/src/com/android/telecomm/CallsManager.java
@@ -140,14 +140,14 @@
}
@Override
- public void onFailedOutgoingCall(Call call, boolean isAborted) {
+ public void onFailedOutgoingCall(Call call, boolean isAborted, int errorCode, String errorMsg) {
Log.v(this, "onFailedOutgoingCall, call: %s, isAborted: %b", call, isAborted);
if (isAborted) {
setCallState(call, CallState.ABORTED);
removeCall(call);
} else {
// TODO: Replace disconnect cause with more specific disconnect causes.
- markCallAsDisconnected(call, DisconnectCause.ERROR_UNSPECIFIED, null);
+ markCallAsDisconnected(call, errorCode, errorMsg);
}
}
diff --git a/src/com/android/telecomm/InCallController.java b/src/com/android/telecomm/InCallController.java
index a8d54fa..1318825 100644
--- a/src/com/android/telecomm/InCallController.java
+++ b/src/com/android/telecomm/InCallController.java
@@ -257,8 +257,8 @@
if (state == CallState.DISCONNECTED && call.getHandoffCallServiceDescriptor() != null) {
state = CallState.ACTIVE;
}
- return new InCallCall(callId, state, call.getDisconnectCause(), capabilities,
- call.getConnectTimeMillis(), call.getHandle(), call.getGatewayInfo(), descriptor,
- call.getHandoffCallServiceDescriptor());
+ return new InCallCall(callId, state, call.getDisconnectCause(), call.getDisconnectMessage(),
+ capabilities, call.getConnectTimeMillis(), call.getHandle(), call.getGatewayInfo(),
+ descriptor, call.getHandoffCallServiceDescriptor());
}
}
diff --git a/src/com/android/telecomm/OutgoingCallProcessor.java b/src/com/android/telecomm/OutgoingCallProcessor.java
index 0f77567..366307c 100644
--- a/src/com/android/telecomm/OutgoingCallProcessor.java
+++ b/src/com/android/telecomm/OutgoingCallProcessor.java
@@ -20,6 +20,7 @@
import android.os.Handler;
import android.os.Message;
import android.telecomm.CallServiceDescriptor;
+import android.telephony.DisconnectCause;
import com.android.telecomm.BaseRepository.LookupCallback;
import com.google.android.collect.Sets;
@@ -103,6 +104,10 @@
private boolean mIsAborted = false;
+ private int mLastErrorCode = 0;
+
+ 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-
@@ -182,7 +187,9 @@
callService.abort(mCall);
}
- sendResult(false);
+ // We consider a deliberate abort to be a "normal" disconnect, not
+ // requiring special reporting.
+ sendResult(false, DisconnectCause.LOCAL, null);
}
}
@@ -205,17 +212,22 @@
return;
}
- sendResult(true);
+ sendResult(true, DisconnectCause.NOT_DISCONNECTED, null);
}
/**
* Attempts the next call service if the specified call service is the one currently being
* attempted.
*
- * @param reason The call-service supplied reason for the failed call attempt.
+ * @param errorCode The reason for the failure, one of {@link DisconnectCause}.
+ * @param errorMsg Optional text reason for the failure.
*/
- void handleFailedCallAttempt(String reason) {
- Log.v(this, "handleFailedCallAttempt");
+ void handleFailedCallAttempt(int errorCode, String errorMsg) {
+ Log.v(this, "handleFailedCallAttempt %s %s", DisconnectCause.toString(errorCode), errorMsg);
+ // Store latest error code and message. If this is our last available attempt at placing
+ // a call, these error details will be considered "the" cause of the failure.
+ mLastErrorCode = errorCode;
+ mLastErrorMsg = errorMsg;
if (!mIsAborted) {
ThreadUtil.checkOnMainThread();
attemptNextCallService();
@@ -327,14 +339,16 @@
selector.select(mCall, mCallServiceDescriptors,
new AsyncResultCallback<List<CallServiceDescriptor>>() {
@Override
- public void onResult(List<CallServiceDescriptor> descriptors) {
+ 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);
+ sendResult(false, mLastErrorCode, mLastErrorMsg);
}
}
@@ -369,11 +383,11 @@
callService.call(mCall, new AsyncResultCallback<Boolean>() {
@Override
- public void onResult(Boolean wasCallPlaced) {
+ public void onResult(Boolean wasCallPlaced, int errorCode, String errorMsg) {
if (wasCallPlaced) {
handleSuccessfulCallAttempt(callService);
} else {
- handleFailedCallAttempt("call failed.");
+ handleFailedCallAttempt(errorCode, errorMsg);
}
// If successful, the call should not have it's own association to keep
@@ -389,9 +403,9 @@
}
}
- private void sendResult(boolean wasCallPlaced) {
+ private void sendResult(boolean wasCallPlaced, int errorCode, String errorMsg) {
if (mResultCallback != null) {
- mResultCallback.onResult(wasCallPlaced);
+ mResultCallback.onResult(wasCallPlaced, errorCode, errorMsg);
mResultCallback = null;
mHandler.removeMessages(MSG_EXPIRE);