Merge "Import translations. DO NOT MERGE ANYWHERE" into main
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c950337..9d9f5e1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -423,6 +423,9 @@
<!-- In-call screen: error message shown when the user attempts to place a call, but the live
call cannot be held. -->
<string name="callFailed_unholdable_call">Cannot place a call as there is an unholdable call. Disconnect the call prior to placing a new call.</string>
+ <!-- In-call screen: error message shown when the user has attempted to place a new outgoing
+ call while there is already a call in ringing state. -->
+ <string name="callFailed_already_ringing">Cannot place a call as there is an unanswered incoming call. Answer or reject the incoming call prior to placing a new call.</string>
<!-- In-call screen: error message shown when the user attempts to dial an MMI code, but there
is an ongoing call on a different phone account. -->
<string name="callFailed_reject_mmi">This MMI code is not available for calls across multiple accounts.</string>
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 39cd379..abcdd18 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -4461,6 +4461,11 @@
CallState.SIMULATED_RINGING, CallState.RINGING, CallState.ANSWERED) != null;
}
+ public boolean hasManagedRingingOrSimulatedRingingCall() {
+ return getFirstCallWithState(null /* callToSkip */, true /* skipSelfManaged */,
+ CallState.SIMULATED_RINGING, CallState.RINGING, CallState.ANSWERED) != null;
+ }
+
@VisibleForTesting
public boolean onMediaButton(int type) {
if (hasAnyCalls()) {
@@ -4604,11 +4609,11 @@
@VisibleForTesting
public Call getFirstCallWithState(int... states) {
- return getFirstCallWithState(null, states);
+ return getFirstCallWithState(null, false /* skipSelfManaged */, states);
}
public Call getFirstCallWithLiveState() {
- return getFirstCallWithState(null, LIVE_CALL_STATES);
+ return getFirstCallWithState(null, false /* skipSelfManaged */, LIVE_CALL_STATES);
}
@VisibleForTesting
@@ -4633,7 +4638,7 @@
*
* @param callToSkip Call that this method should skip while searching
*/
- Call getFirstCallWithState(Call callToSkip, int... states) {
+ Call getFirstCallWithState(Call callToSkip, boolean skipSelfManaged, int... states) {
for (int currentState : states) {
// check the foreground first
Call foregroundCall = getForegroundCall();
@@ -4655,6 +4660,10 @@
continue;
}
+ if (skipSelfManaged && call.isSelfManaged()) {
+ continue;
+ }
+
if (currentState == call.getState()) {
return call;
}
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index 68ef421..766db8e 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -602,7 +602,8 @@
Log.w(this, "disconnectSco: Trying to disconnect audio but no headset service exists.");
} else {
result = mBluetoothHeadset.disconnectAudio();
- Log.i(this, "disconnectSco: BluetoothHeadset#disconnectAudio()=%b", result);
+ Log.i(this, "disconnectSco: BluetoothHeadset#disconnectAudio()=%s",
+ btCodeToString(result));
}
return result;
}
@@ -888,8 +889,8 @@
}
if (getBluetoothHeadset() != null) {
int scoConnectionRequest = mBluetoothHeadset.connectAudio();
- Log.i(this, "connectAudio: BluetoothHeadset#connectAudio()=%d",
- scoConnectionRequest);
+ Log.i(this, "connectAudio: BluetoothHeadset#connectAudio()=%s",
+ btCodeToString(scoConnectionRequest));
return scoConnectionRequest == BluetoothStatusCodes.SUCCESS ||
scoConnectionRequest
== BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_CONNECTED;
@@ -944,8 +945,8 @@
}
if (getBluetoothHeadset() != null) {
int scoConnectionRequest = mBluetoothHeadset.connectAudio();
- Log.i(this, "connectAudio: BluetoothHeadset#connectAudio()=%d",
- scoConnectionRequest);
+ Log.i(this, "connectAudio: BluetoothHeadset#connectAudio()=%s",
+ btCodeToString(scoConnectionRequest));
return scoConnectionRequest == BluetoothStatusCodes.SUCCESS ||
scoConnectionRequest
== BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_CONNECTED;
@@ -1015,4 +1016,33 @@
public void dump(IndentingPrintWriter pw) {
mLocalLog.dump(pw);
}
+
+ private String btCodeToString(int code) {
+ switch (code) {
+ case BluetoothStatusCodes.SUCCESS:
+ return "SUCCESS";
+ case BluetoothStatusCodes.ERROR_UNKNOWN:
+ return "ERROR_UNKNOWN";
+ case BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND:
+ return "ERROR_PROFILE_SERVICE_NOT_BOUND";
+ case BluetoothStatusCodes.ERROR_TIMEOUT:
+ return "ERROR_TIMEOUT";
+ case BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_CONNECTED:
+ return "ERROR_AUDIO_DEVICE_ALREADY_CONNECTED";
+ case BluetoothStatusCodes.ERROR_NO_ACTIVE_DEVICES:
+ return "ERROR_NO_ACTIVE_DEVICES";
+ case BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE:
+ return "ERROR_NOT_ACTIVE_DEVICE";
+ case BluetoothStatusCodes.ERROR_AUDIO_ROUTE_BLOCKED:
+ return "ERROR_AUDIO_ROUTE_BLOCKED";
+ case BluetoothStatusCodes.ERROR_CALL_ACTIVE:
+ return "ERROR_CALL_ACTIVE";
+ case BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED:
+ return "ERROR_PROFILE_NOT_CONNECTED";
+ case BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED:
+ return "BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED";
+ default:
+ return Integer.toString(code);
+ }
+ }
}
diff --git a/src/com/android/server/telecom/callsequencing/CallSequencingController.java b/src/com/android/server/telecom/callsequencing/CallSequencingController.java
index 5166c03..713d155 100644
--- a/src/com/android/server/telecom/callsequencing/CallSequencingController.java
+++ b/src/com/android/server/telecom/callsequencing/CallSequencingController.java
@@ -697,6 +697,12 @@
* made for the outgoing call.
*/
private CompletableFuture<Boolean> makeRoomForOutgoingCall(Call call) {
+ // For the purely managed CS cases, check if there's a ringing call, in which case we will
+ // disallow the outgoing call.
+ if (!call.isSelfManaged() && mCallsManager.hasManagedRingingOrSimulatedRingingCall()) {
+ showErrorDialogForOutgoingDuringRingingCall(call);
+ return CompletableFuture.completedFuture(false);
+ }
// Already room!
if (!mCallsManager.hasMaximumLiveCalls(call)) {
return CompletableFuture.completedFuture(true);
@@ -921,20 +927,34 @@
}
private void showErrorDialogForMaxOutgoingCall(Call call) {
- call.setStartFailCause(CallFailureCause.MAX_OUTGOING_CALLS);
- int stringId = R.string.callFailed_too_many_calls;
+ int resourceId = R.string.callFailed_too_many_calls;
String reason = " there are two calls already in progress. Disconnect one of the calls "
+ "or merge the calls.";
- showErrorDialogForRestrictedOutgoingCall(mContext, stringId, TAG, reason);
+ showErrorDialogForFailedCall(call, CallFailureCause.MAX_OUTGOING_CALLS, resourceId, reason);
+ }
+
+ private void showErrorDialogForOutgoingDuringRingingCall(Call call) {
+ int resourceId = R.string.callFailed_already_ringing;
+ String reason = " can't place outgoing call with an unanswered incoming call.";
+ showErrorDialogForFailedCall(call, null, resourceId, reason);
}
private void showErrorDialogForCannotHoldCall(Call call, boolean setCallFailure) {
+ CallFailureCause cause = null;
if (setCallFailure) {
- call.setStartFailCause(CallFailureCause.CANNOT_HOLD_CALL);
+ cause = CallFailureCause.CANNOT_HOLD_CALL;
}
- int stringId = R.string.callFailed_unholdable_call;
+ int resourceId = R.string.callFailed_unholdable_call;
String reason = " unable to hold live call. Disconnect the unholdable call.";
- showErrorDialogForRestrictedOutgoingCall(mContext, stringId, TAG, reason);
+ showErrorDialogForFailedCall(call, cause, resourceId, reason);
+ }
+
+ private void showErrorDialogForFailedCall(Call call, CallFailureCause cause, int resourceId,
+ String reason) {
+ if (cause != null) {
+ call.setStartFailCause(cause);
+ }
+ showErrorDialogForRestrictedOutgoingCall(mContext, resourceId, TAG, reason);
}
public Handler getHandler() {
diff --git a/tests/src/com/android/server/telecom/tests/CallSequencingTests.java b/tests/src/com/android/server/telecom/tests/CallSequencingTests.java
index f1861cb..64d2d7d 100644
--- a/tests/src/com/android/server/telecom/tests/CallSequencingTests.java
+++ b/tests/src/com/android/server/telecom/tests/CallSequencingTests.java
@@ -560,6 +560,16 @@
@Test
@SmallTest
+ public void testMakeRoomForOutgoingCallFail_RingingCall() {
+ when(mNewCall.isSelfManaged()).thenReturn(false);
+ when(mCallsManager.hasManagedRingingOrSimulatedRingingCall()).thenReturn(true);
+
+ CompletableFuture<Boolean> future = mController.makeRoomForOutgoingCall(false, mNewCall);
+ assertFalse(waitForFutureResult(future, true));
+ }
+
+ @Test
+ @SmallTest
public void testDisconnectCallSuccess() {
when(mActiveCall.disconnect()).thenReturn(CompletableFuture.completedFuture(true));
int previousState = CallState.ACTIVE;