Snap for 4677756 from d0c6caba1e909fc4a05ddc0c04cdd82936805e7e to pi-release
Change-Id: I926788b3606fc81b0cd2f3ac39290772a05a17c7
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index ad446ec..7bc2519 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -93,6 +93,7 @@
mPlayerFactory.setCallAudioManager(this);
mCallAudioModeStateMachine.setCallAudioManager(this);
+ mCallAudioRouteStateMachine.setCallAudioManager(this);
}
@Override
@@ -385,6 +386,11 @@
CallAudioRouteStateMachine.TOGGLE_MUTE);
}
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void onRingerModeChange() {
+ mCallAudioModeStateMachine.sendMessage(CallAudioModeStateMachine.RINGER_MODE_CHANGE);
+ }
+
@VisibleForTesting
public void mute(boolean shouldMute) {
Log.v(this, "mute, shouldMute: %b", shouldMute);
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index b5c7e7a..716f23a 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -87,6 +87,8 @@
public static final int FOREGROUND_VOIP_MODE_CHANGE = 4001;
+ public static final int RINGER_MODE_CHANGE = 5001;
+
public static final int RUN_RUNNABLE = 9001;
private static final SparseArray<String> MESSAGE_CODE_TO_NAME = new SparseArray<String>() {{
@@ -105,6 +107,7 @@
put(TONE_STARTED_PLAYING, "TONE_STARTED_PLAYING");
put(TONE_STOPPED_PLAYING, "TONE_STOPPED_PLAYING");
put(FOREGROUND_VOIP_MODE_CHANGE, "FOREGROUND_VOIP_MODE_CHANGE");
+ put(RINGER_MODE_CHANGE, "RINGER_MODE_CHANGE");
put(RUN_RUNNABLE, "RUN_RUNNABLE");
}};
@@ -202,18 +205,22 @@
}
private class RingingFocusState extends BaseState {
- @Override
- public void enter() {
- Log.i(LOG_TAG, "Audio focus entering RINGING state");
+ private void tryStartRinging() {
if (mCallAudioManager.startRinging()) {
mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
mAudioManager.setMode(AudioManager.MODE_RINGTONE);
- mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.RINGING_FOCUS);
+ mCallAudioManager.setCallAudioRouteFocusState(
+ CallAudioRouteStateMachine.RINGING_FOCUS);
} else {
- Log.i(LOG_TAG, "Entering RINGING but not acquiring focus -- silent ringtone");
+ Log.i(LOG_TAG, "RINGING state, try start ringing but not acquiring audio focus");
}
+ }
+ @Override
+ public void enter() {
+ Log.i(LOG_TAG, "Audio focus entering RINGING state");
+ tryStartRinging();
mCallAudioManager.stopCallWaiting();
}
@@ -275,6 +282,11 @@
transitionTo(args.foregroundCallIsVoip
? mVoipCallFocusState : mSimCallFocusState);
return HANDLED;
+ case RINGER_MODE_CHANGE: {
+ Log.i(LOG_TAG, "RINGING state, received RINGER_MODE_CHANGE");
+ tryStartRinging();
+ return HANDLED;
+ }
default:
// The forced focus switch commands are handled by BaseState.
return NOT_HANDLED;
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index facbf39..dfa6042 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -745,6 +745,10 @@
mBluetoothRouteManager.getConnectedDevices());
setSystemAudioState(newState, true);
updateInternalCallAudioState();
+ // Do not send RINGER_MODE_CHANGE if no Bluetooth SCO audio device is available
+ if (mBluetoothRouteManager.getBluetoothAudioConnectedDevice() != null) {
+ mCallAudioManager.onRingerModeChange();
+ }
}
@Override
@@ -770,7 +774,9 @@
}
return HANDLED;
case BT_AUDIO_CONNECTED:
- // Nothing to do
+ // Send ringer mode change because we transit to ActiveBluetoothState even
+ // when HFP is connecting
+ mCallAudioManager.onRingerModeChange();
return HANDLED;
case SWITCH_BLUETOOTH:
case USER_SWITCH_BLUETOOTH:
@@ -1276,6 +1282,8 @@
private CallAudioState mCurrentCallAudioState;
private CallAudioState mLastKnownCallAudioState;
+ private CallAudioManager mCallAudioManager;
+
public CallAudioRouteStateMachine(
Context context,
CallsManager callsManager,
@@ -1332,6 +1340,10 @@
mRouteCodeToQuiescentState.put(ROUTE_WIRED_HEADSET, mQuiescentHeadsetRoute);
}
+ public void setCallAudioManager(CallAudioManager callAudioManager) {
+ mCallAudioManager = callAudioManager;
+ }
+
/**
* Initializes the state machine with info on initial audio route, supported audio routes,
* and mute status.
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 7db4bd2..72443b4 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -1460,8 +1460,21 @@
Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
Log.d(this, "Incoming call = %s Ongoing call %s", call, activeCall);
if (activeCall != null && activeCall != call) {
- // Hold the telephony call even if it doesn't have the hold capability.
- if (canHold(activeCall)) {
+ // We purposely don't check if the active call CAN current hold, but rather we check
+ // whether it CAN support hold. Consider this scenario:
+ // Call A - Active (CAPABILITY_SUPPORT_HOLD, but not CAPABILITY_HOLD)
+ // Call B - Held (CAPABILITY_SUPPORT_HOLD, but not CAPABILITY_HOLD)
+ // Call C - Incoming call
+ // In this scenario we are going to first disconnect the held call (Call B), which
+ // will mean that the active call (Call A) will now support hold.
+ if (supportsHold(activeCall)) {
+ Call heldCall = getHeldCall();
+ if (heldCall != null) {
+ Log.i(this, "Disconnecting held call %s before holding active call.",
+ heldCall);
+ heldCall.disconnect();
+ }
+
Log.d(this, "Answer %s, hold %s", call, activeCall);
activeCall.hold();
} else {
@@ -3436,7 +3449,7 @@
// Send an error back if there are any ongoing emergency calls.
if (hasEmergencyCall()) {
handoverFromCall.onHandoverFailed(
- android.telecom.Call.Callback.HANDOVER_FAILURE_ONGOING_EMERG_CALL);
+ android.telecom.Call.Callback.HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL);
return;
}
@@ -3733,6 +3746,10 @@
return call.can(Connection.CAPABILITY_HOLD);
}
+ private boolean supportsHold(Call call) {
+ return call.can(Connection.CAPABILITY_SUPPORT_HOLD);
+ }
+
private final class ActionSetCallState implements PendingAction {
private final Call mCall;
diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml
index a55aeed..cbca5a7 100644
--- a/tests/AndroidTest.xml
+++ b/tests/AndroidTest.xml
@@ -14,11 +14,13 @@
limitations under the License.
-->
<configuration description="Runs Telecom Test Cases.">
- <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
<option name="test-file-name" value="TelecomUnitTests.apk" />
</target_preparer>
- <option name="test-suite-tag" value="apct" />
<option name="test-tag" value="TelecomUnitTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.server.telecom.tests" />
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
index 64f5fb8..f253d19 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
@@ -21,6 +21,7 @@
import com.android.server.telecom.CallAudioManager;
import com.android.server.telecom.CallAudioModeStateMachine;
+import com.android.server.telecom.CallAudioRouteStateMachine;
import org.junit.Before;
import org.junit.Test;
@@ -80,6 +81,51 @@
verify(mCallAudioManager).stopCallWaiting();
}
+ @SmallTest
+ @Test
+ public void testRegainFocusWhenHfpIsConnectedSilenced() throws Throwable {
+ CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mAudioManager);
+ sm.setCallAudioManager(mCallAudioManager);
+ sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
+ waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
+
+ resetMocks();
+ when(mCallAudioManager.startRinging()).thenReturn(false);
+
+ sm.sendMessage(CallAudioModeStateMachine.NEW_RINGING_CALL,
+ new CallAudioModeStateMachine.MessageArgs(
+ false, // hasActiveOrDialingCalls
+ true, // hasRingingCalls
+ false, // hasHoldingCalls
+ false, // isTonePlaying
+ false, // foregroundCallIsVoip
+ null // session
+ ));
+ waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
+
+ assertEquals(CallAudioModeStateMachine.RING_STATE_NAME, sm.getCurrentStateName());
+
+ verify(mAudioManager, never()).requestAudioFocusForCall(anyInt(), anyInt());
+ verify(mAudioManager, never()).setMode(anyInt());
+
+ verify(mCallAudioManager, never()).stopRinging();
+
+ verify(mCallAudioManager).stopCallWaiting();
+
+ when(mCallAudioManager.startRinging()).thenReturn(true);
+
+ sm.sendMessage(CallAudioModeStateMachine.RINGER_MODE_CHANGE);
+ waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT);
+
+ verify(mCallAudioManager).startRinging();
+ verify(mAudioManager).requestAudioFocusForCall(AudioManager.STREAM_RING,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ verify(mAudioManager).setMode(AudioManager.MODE_RINGTONE);
+ verify(mCallAudioManager).setCallAudioRouteFocusState(
+ CallAudioRouteStateMachine.RINGING_FOCUS);
+ }
+
+
private void resetMocks() {
reset(mCallAudioManager, mAudioManager);
}
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
index 76048b7..d4c3d1d 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteStateMachineTest.java
@@ -82,6 +82,7 @@
@Mock WiredHeadsetManager mockWiredHeadsetManager;
@Mock StatusBarNotifier mockStatusBarNotifier;
@Mock Call fakeCall;
+ @Mock CallAudioManager mockCallAudioManager;
private CallAudioManager.AudioServiceFactory mAudioServiceFactory;
private static final int TEST_TIMEOUT = 500;
@@ -187,6 +188,7 @@
mockStatusBarNotifier,
mAudioServiceFactory,
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED);
+ stateMachine.setCallAudioManager(mockCallAudioManager);
when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true);
@@ -229,6 +231,7 @@
mockStatusBarNotifier,
mAudioServiceFactory,
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED);
+ stateMachine.setCallAudioManager(mockCallAudioManager);
Collection<BluetoothDevice> availableDevices = Collections.singleton(bluetoothDevice1);
when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
@@ -301,6 +304,7 @@
mockStatusBarNotifier,
mAudioServiceFactory,
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED);
+ stateMachine.setCallAudioManager(mockCallAudioManager);
when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true);
@@ -335,6 +339,7 @@
mockStatusBarNotifier,
mAudioServiceFactory,
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED);
+ stateMachine.setCallAudioManager(mockCallAudioManager);
setInBandRing(false);
when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false);
when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(false);
@@ -368,6 +373,12 @@
CallAudioRouteStateMachine.ACTIVE_FOCUS);
waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
verify(mockBluetoothRouteManager, times(1)).connectBluetoothAudio(null);
+
+ when(mockBluetoothRouteManager.getBluetoothAudioConnectedDevice())
+ .thenReturn(bluetoothDevice1);
+ stateMachine.sendMessage(CallAudioRouteStateMachine.BT_AUDIO_CONNECTED);
+ waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
+ verify(mockCallAudioManager, times(1)).onRingerModeChange();
}
@SmallTest
@@ -381,6 +392,7 @@
mockStatusBarNotifier,
mAudioServiceFactory,
CallAudioRouteStateMachine.EARPIECE_FORCE_ENABLED);
+ stateMachine.setCallAudioManager(mockCallAudioManager);
List<BluetoothDevice> availableDevices =
Arrays.asList(bluetoothDevice1, bluetoothDevice2, bluetoothDevice3);
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
index 345312e..609a488 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
@@ -146,6 +146,7 @@
@Mock WiredHeadsetManager mockWiredHeadsetManager;
@Mock StatusBarNotifier mockStatusBarNotifier;
@Mock Call fakeCall;
+ @Mock CallAudioManager mockCallAudioManager;
private CallAudioManager.AudioServiceFactory mAudioServiceFactory;
private static final int TEST_TIMEOUT = 500;
private AudioManager mockAudioManager;
@@ -218,6 +219,7 @@
mockStatusBarNotifier,
mAudioServiceFactory,
mParams.earpieceControl);
+ stateMachine.setCallAudioManager(mockCallAudioManager);
setupMocksForParams(stateMachine, mParams);
@@ -303,6 +305,7 @@
mockStatusBarNotifier,
mAudioServiceFactory,
mParams.earpieceControl);
+ stateMachine.setCallAudioManager(mockCallAudioManager);
// Set up bluetooth and speakerphone state
when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(