DO NOT MERGE. Implement connection error dialogs (3/4)
Implement reporting of connection errors from ConnectionServices through
Telecomm to the InCallUI.
Bug: 15195720
Bug: 15117141
Change-Id: Ia8cd6f2092661225c5cc65a60abba1c35e8fba65
diff --git a/src/com/android/services/telephony/PstnConnectionService.java b/src/com/android/services/telephony/PstnConnectionService.java
index cd3598e..8ac6ee9 100644
--- a/src/com/android/services/telephony/PstnConnectionService.java
+++ b/src/com/android/services/telephony/PstnConnectionService.java
@@ -18,6 +18,7 @@
import android.net.Uri;
+import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
import com.android.internal.telephony.Call;
@@ -52,7 +53,11 @@
if (!canCall(request.getHandle())) {
Log.d(this, "Cannot place the call with %s", this.getClass().getSimpleName());
- respondWithError(request, response, "Cannot place call.");
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.ERROR_UNSPECIFIED, // TODO: Code for "ConnSvc cannot call"
+ "Cannot place call.");
return;
}
@@ -71,7 +76,11 @@
if (isRadioReady) {
startCallWithPhone(phone, request, response);
} else {
- respondWithError(request, response, "Failed to turn on radio.");
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.POWER_OFF,
+ "Failed to turn on radio.");
}
}
}
@@ -103,6 +112,7 @@
respondWithError(
request,
response,
+ DisconnectCause.ERROR_UNSPECIFIED, // Internal error
"Cannot set incoming call ID, ringing connection already registered.");
} else {
// Address can be null for blocked calls.
@@ -117,7 +127,11 @@
try {
telephonyConnection = createTelephonyConnection(request, connection);
} catch (Exception e) {
- respondWithError(request, response, e.getMessage());
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.ERROR_UNSPECIFIED, // Internal error
+ e.getMessage());
return;
}
@@ -130,6 +144,7 @@
respondWithError(
request,
response,
+ DisconnectCause.INCOMING_MISSED, // Most likely cause
String.format("Found no ringing call, call state: %s", call.getState()));
}
super.onCreateIncomingConnection(request, response);
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 185fa57..c17b8f6 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -17,10 +17,13 @@
package com.android.services.telephony;
import android.net.Uri;
+import android.telephony.DisconnectCause;
+import android.telephony.ServiceState;
import android.text.TextUtils;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Phone;
+
import android.telecomm.Connection;
import android.telecomm.ConnectionRequest;
import android.telecomm.ConnectionService;
@@ -46,7 +49,11 @@
try {
respondWithResult(handle, response, canCall(handle) ? new Subscription() : null);
} catch (Exception e) {
- respondWithError(handle, response, "onFindSubscriptions error: " + e.toString());
+ respondWithError(
+ handle,
+ response,
+ DisconnectCause.ERROR_UNSPECIFIED, // Internal error
+ "onFindSubscriptions error: " + e.toString());
}
}
@@ -64,18 +71,34 @@
Log.d(this, "startCallWithPhone: %s.", request);
if (phone == null) {
- respondWithError(request, response, "Phone is null");
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.ERROR_UNSPECIFIED, // Generic internal error
+ "Phone is null");
return;
}
if (request.getHandle() == null) {
- respondWithError(request, response, "Handle is null");
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.NO_PHONE_NUMBER_SUPPLIED,
+ "Handle is null");
return;
}
String number = request.getHandle().getSchemeSpecificPart();
if (TextUtils.isEmpty(number)) {
- respondWithError(request, response, "Unable to parse number");
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.INVALID_NUMBER,
+ "Unable to parse number");
+ return;
+ }
+
+ if (!checkServiceStateForOutgoingCall(phone, request, response)) {
return;
}
@@ -84,12 +107,20 @@
connection = phone.dial(number);
} catch (CallStateException e) {
Log.e(this, e, "Call to Phone.dial failed with exception");
- respondWithError(request, response, e.getMessage());
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.ERROR_UNSPECIFIED, // Generic internal error
+ e.getMessage());
return;
}
if (connection == null) {
- respondWithError(request, response, "Call to phone.dial failed");
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.ERROR_UNSPECIFIED, // Generic internal error
+ "Call to phone.dial failed");
return;
}
@@ -97,16 +128,63 @@
respondWithResult(request, response, createTelephonyConnection(request, connection));
} catch (Exception e) {
Log.e(this, e, "Call to createConnection failed with exception");
- respondWithError(request, response, e.getMessage());
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.ERROR_UNSPECIFIED, // Generic internal error
+ e.getMessage());
}
}
+ private boolean checkServiceStateForOutgoingCall(
+ Phone phone,
+ ConnectionRequest request,
+ Response<ConnectionRequest, Connection> response) {
+ int state = phone.getServiceState().getState();
+ switch (state) {
+ case ServiceState.STATE_IN_SERVICE:
+ return true;
+ case ServiceState.STATE_OUT_OF_SERVICE:
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.OUT_OF_SERVICE,
+ null);
+ break;
+ case ServiceState.STATE_EMERGENCY_ONLY:
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.EMERGENCY_ONLY,
+ null);
+ break;
+ case ServiceState.STATE_POWER_OFF:
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.POWER_OFF,
+ null);
+ break;
+ default:
+ // Internal error, but we pass it upwards and do not crash.
+ Log.d(this, "Unrecognized service state %d", state);
+ respondWithError(
+ request,
+ response,
+ DisconnectCause.ERROR_UNSPECIFIED,
+ "Unrecognized service state " + state);
+ break;
+ }
+ return false;
+ }
+
protected <REQUEST, RESULT> void respondWithError(
REQUEST request,
Response<REQUEST, RESULT> response,
- String reason) {
- Log.d(this, "respondWithError %s: %s", request, reason);
- response.onError(request, reason);
+ int errorCode,
+ String errorMsg) {
+ Log.d(this, "respondWithError %s: %d %s", request, errorCode, errorMsg);
+ response.onError(request, errorCode, errorMsg);
}
protected void respondWithResult(