Loading src/com/android/server/telecom/CallAudioModeStateMachine.java +72 −14 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.telecom; import android.media.AudioAttributes; import android.media.AudioFocusRequest; import android.media.AudioManager; import android.os.Looper; import android.os.Message; Loading @@ -29,6 +31,7 @@ import com.android.internal.util.IState; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.server.telecom.flags.FeatureFlags; public class CallAudioModeStateMachine extends StateMachine { /** Loading @@ -38,11 +41,27 @@ public class CallAudioModeStateMachine extends StateMachine { private LocalLog mLocalLog = new LocalLog(20); public static class Factory { public CallAudioModeStateMachine create(SystemStateHelper systemStateHelper, AudioManager am) { return new CallAudioModeStateMachine(systemStateHelper, am); AudioManager am, FeatureFlags featureFlags) { return new CallAudioModeStateMachine(systemStateHelper, am, featureFlags); } } private static final AudioAttributes RING_AUDIO_ATTRIBUTES = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) .setLegacyStreamType(AudioManager.STREAM_RING) .build(); public static final AudioFocusRequest RING_AUDIO_FOCUS_REQUEST = new AudioFocusRequest .Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT) .setAudioAttributes(RING_AUDIO_ATTRIBUTES).build(); private static final AudioAttributes CALL_AUDIO_ATTRIBUTES = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) .setLegacyStreamType(AudioManager.STREAM_VOICE_CALL) .build(); public static final AudioFocusRequest CALL_AUDIO_FOCUS_REQUEST = new AudioFocusRequest .Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT) .setAudioAttributes(CALL_AUDIO_ATTRIBUTES).build(); public static class MessageArgs { public boolean hasActiveOrDialingCalls; public boolean hasRingingCalls; Loading Loading @@ -212,6 +231,8 @@ public class CallAudioModeStateMachine extends StateMachine { public static final String STREAMING_STATE_NAME = StreamingFocusState.class.getSimpleName(); public static final String COMMS_STATE_NAME = VoipCallFocusState.class.getSimpleName(); private AudioFocusRequest mCurrentAudioFocusRequest = null; private class BaseState extends State { @Override public boolean processMessage(Message msg) { Loading Loading @@ -310,7 +331,14 @@ public class CallAudioModeStateMachine extends StateMachine { return HANDLED; case AUDIO_OPERATIONS_COMPLETE: Log.i(LOG_TAG, "Abandoning audio focus: now UNFOCUSED"); if (mFeatureFlags.telecomResolveHiddenDependencies()) { if (mCurrentAudioFocusRequest != null) { mAudioManager.abandonAudioFocusRequest(mCurrentAudioFocusRequest); mCurrentAudioFocusRequest = null; } } else { mAudioManager.abandonAudioFocusForCall(); } return HANDLED; default: // The forced focus switch commands are handled by BaseState. Loading Loading @@ -381,7 +409,14 @@ public class CallAudioModeStateMachine extends StateMachine { return HANDLED; case AUDIO_OPERATIONS_COMPLETE: Log.i(LOG_TAG, "Abandoning audio focus: now AUDIO_PROCESSING"); if (mFeatureFlags.telecomResolveHiddenDependencies()) { if (mCurrentAudioFocusRequest != null) { mAudioManager.abandonAudioFocusRequest(mCurrentAudioFocusRequest); mCurrentAudioFocusRequest = null; } } else { mAudioManager.abandonAudioFocusForCall(); } return HANDLED; default: // The forced focus switch commands are handled by BaseState. Loading @@ -406,8 +441,13 @@ public class CallAudioModeStateMachine extends StateMachine { } if (mCallAudioManager.startRinging()) { if (mFeatureFlags.telecomResolveHiddenDependencies()) { mCurrentAudioFocusRequest = RING_AUDIO_FOCUS_REQUEST; mAudioManager.requestAudioFocus(RING_AUDIO_FOCUS_REQUEST); } else { mAudioManager.requestAudioFocusForCall( AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); } // Do not set MODE_RINGTONE if we were previously in the CALL_SCREENING mode -- // this trips up the audio system. if (mAudioManager.getMode() != AudioManager.MODE_CALL_SCREENING) { Loading Loading @@ -504,8 +544,13 @@ public class CallAudioModeStateMachine extends StateMachine { public void enter() { Log.i(LOG_TAG, "Audio focus entering SIM CALL state"); mLocalLog.log("Enter SIM_CALL"); if (mFeatureFlags.telecomResolveHiddenDependencies()) { mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST; mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST); } else { mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); } mAudioManager.setMode(AudioManager.MODE_IN_CALL); mLocalLog.log("Mode MODE_IN_CALL"); mMostRecentMode = AudioManager.MODE_IN_CALL; Loading Loading @@ -587,8 +632,13 @@ public class CallAudioModeStateMachine extends StateMachine { public void enter() { Log.i(LOG_TAG, "Audio focus entering VOIP CALL state"); mLocalLog.log("Enter VOIP_CALL"); if (mFeatureFlags.telecomResolveHiddenDependencies()) { mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST; mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST); } else { mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); } mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); mLocalLog.log("Mode MODE_IN_COMMUNICATION"); mMostRecentMode = AudioManager.MODE_IN_COMMUNICATION; Loading Loading @@ -742,8 +792,13 @@ public class CallAudioModeStateMachine extends StateMachine { public void enter() { Log.i(LOG_TAG, "Audio focus entering TONE/HOLDING state"); mLocalLog.log("Enter TONE/HOLDING"); if (mFeatureFlags.telecomResolveHiddenDependencies()) { mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST; mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST); } else { mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); } mAudioManager.setMode(mMostRecentMode); mLocalLog.log("Mode " + mMostRecentMode); mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS); Loading Loading @@ -815,16 +870,18 @@ public class CallAudioModeStateMachine extends StateMachine { private final AudioManager mAudioManager; private final SystemStateHelper mSystemStateHelper; private CallAudioManager mCallAudioManager; private FeatureFlags mFeatureFlags; private int mMostRecentMode; private boolean mIsInitialized = false; public CallAudioModeStateMachine(SystemStateHelper systemStateHelper, AudioManager audioManager) { AudioManager audioManager, FeatureFlags featureFlags) { super(CallAudioModeStateMachine.class.getSimpleName()); mAudioManager = audioManager; mSystemStateHelper = systemStateHelper; mMostRecentMode = AudioManager.MODE_NORMAL; mFeatureFlags = featureFlags; createStates(); } Loading @@ -833,11 +890,12 @@ public class CallAudioModeStateMachine extends StateMachine { * Used for testing */ public CallAudioModeStateMachine(SystemStateHelper systemStateHelper, AudioManager audioManager, Looper looper) { AudioManager audioManager, Looper looper, FeatureFlags featureFlags) { super(CallAudioModeStateMachine.class.getSimpleName(), looper); mAudioManager = audioManager; mSystemStateHelper = systemStateHelper; mMostRecentMode = AudioManager.MODE_NORMAL; mFeatureFlags = featureFlags; createStates(); } Loading src/com/android/server/telecom/CallsManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -655,7 +655,7 @@ public class CallsManager extends Call.ListenerBase mTimeoutsAdapter, mLock); mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine, this, callAudioModeStateMachineFactory.create(systemStateHelper, (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE)), (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE), featureFlags), playerFactory, mRinger, new RingbackPlayer(playerFactory), bluetoothStateReceiver, mDtmfLocalTonePlayer); Loading tests/src/com/android/server/telecom/tests/BasicCallTests.java +2 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.drawable.Icon; import android.media.AudioDeviceInfo; import android.media.AudioFocusRequest; import android.media.AudioManager; import android.net.Uri; import android.os.Binder; Loading Loading @@ -110,6 +111,7 @@ public class BasicCallTests extends TelecomSystemTest { doReturn(mContext).when(mContext).createContextAsUser(any(UserHandle.class), anyInt()); mPackageManager = mContext.getPackageManager(); when(mPackageManager.getPackageUid(anyString(), eq(0))).thenReturn(Binder.getCallingUid()); when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(false); } @Override Loading tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java +64 −18 Original line number Diff line number Diff line Loading @@ -16,14 +16,29 @@ package com.android.server.telecom.tests; import static com.android.server.telecom.CallAudioModeStateMachine.CALL_AUDIO_FOCUS_REQUEST; import static com.android.server.telecom.CallAudioModeStateMachine.RING_AUDIO_FOCUS_REQUEST; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.media.AudioFocusRequest; import android.media.AudioManager; import android.os.HandlerThread; import android.test.suitebuilder.annotation.SmallTest; import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.CallAudioModeStateMachine; import com.android.server.telecom.CallAudioRouteStateMachine; import com.android.server.telecom.CallAudioModeStateMachine.MessageArgs.Builder; import com.android.server.telecom.CallAudioRouteStateMachine; import com.android.server.telecom.SystemStateHelper; import org.junit.After; Loading @@ -31,18 +46,9 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(JUnit4.class) public class CallAudioModeStateMachineTest extends TelecomTestCase { private static final int TEST_TIMEOUT = 1000; Loading @@ -62,6 +68,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { super.setUp(); when(mCallAudioManager.getCallAudioRouteStateMachine()) .thenReturn(mCallAudioRouteStateMachine); when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(false); } @Override Loading @@ -76,7 +83,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testNoFocusWhenRingerSilenced() throws Throwable { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -108,7 +115,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testSwitchToStreamingMode() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -138,7 +145,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testExitStreamingMode() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ENTER_STREAMING_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -166,7 +173,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testNoRingWhenDeviceIsAtEar() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); sm.sendMessage(CallAudioModeStateMachine.NEW_HOLDING_CALL, new Builder() Loading Loading @@ -202,7 +209,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testRegainFocusWhenHfpIsConnectedSilenced() throws Throwable { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -246,7 +253,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testDoNotRingTwiceWhenHfpConnected() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -284,7 +291,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testStartRingingAfterHfpConnectedIfNotAlreadyPlaying() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -318,7 +325,46 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { verify(mCallAudioManager, times(2)).startRinging(); } @SmallTest @Test public void testAudioFocusRequestWithResolveHiddenDependencies() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper(), mFeatureFlags); when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(true); ArgumentCaptor<AudioFocusRequest> captor = ArgumentCaptor.forClass(AudioFocusRequest.class); sm.setCallAudioManager(mCallAudioManager); resetMocks(); when(mCallAudioManager.startRinging()).thenReturn(true); when(mCallAudioManager.isRingtonePlaying()).thenReturn(false); sm.sendMessage(CallAudioModeStateMachine.ENTER_RING_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); verify(mAudioManager).requestAudioFocus(captor.capture()); assertTrue(areAudioFocusRequestsMatch(captor.getValue(), RING_AUDIO_FOCUS_REQUEST)); sm.sendMessage(CallAudioModeStateMachine.ENTER_CALL_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); verify(mAudioManager, atLeast(1)).requestAudioFocus(captor.capture()); AudioFocusRequest request = captor.getValue(); assertTrue(areAudioFocusRequestsMatch(request, CALL_AUDIO_FOCUS_REQUEST)); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); } private void resetMocks() { clearInvocations(mCallAudioManager, mAudioManager); } private boolean areAudioFocusRequestsMatch(AudioFocusRequest r1, AudioFocusRequest r2) { if ((r1 == null) || (r2 == null)) { return false; } if (r1.getFocusGain() != r2.getFocusGain()) { return false; } return r1.getAudioAttributes().equals(r2.getAudioAttributes()); } } tests/src/com/android/server/telecom/tests/CallAudioModeTransitionTests.java +7 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.server.telecom.tests; import static com.android.server.telecom.CallAudioModeStateMachine.CALL_AUDIO_FOCUS_REQUEST; import static com.android.server.telecom.CallAudioModeStateMachine.RING_AUDIO_FOCUS_REQUEST; import android.media.AudioFocusRequest; import android.media.AudioManager; import android.os.HandlerThread; import android.test.suitebuilder.annotation.SmallTest; Loading @@ -37,6 +41,7 @@ import java.util.Collection; import java.util.List; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; Loading Loading @@ -130,13 +135,14 @@ public class CallAudioModeTransitionTests extends TelecomTestCase { @SmallTest public void modeTransitionTest() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(mParams.initialAudioState); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); resetMocks(); when(mCallAudioManager.startRinging()).thenReturn(true); when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(false); if (mParams.initialAudioState == CallAudioModeStateMachine.ENTER_AUDIO_PROCESSING_FOCUS_FOR_TESTING) { when(mAudioManager.getMode()) Loading Loading
src/com/android/server/telecom/CallAudioModeStateMachine.java +72 −14 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.telecom; import android.media.AudioAttributes; import android.media.AudioFocusRequest; import android.media.AudioManager; import android.os.Looper; import android.os.Message; Loading @@ -29,6 +31,7 @@ import com.android.internal.util.IState; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.server.telecom.flags.FeatureFlags; public class CallAudioModeStateMachine extends StateMachine { /** Loading @@ -38,11 +41,27 @@ public class CallAudioModeStateMachine extends StateMachine { private LocalLog mLocalLog = new LocalLog(20); public static class Factory { public CallAudioModeStateMachine create(SystemStateHelper systemStateHelper, AudioManager am) { return new CallAudioModeStateMachine(systemStateHelper, am); AudioManager am, FeatureFlags featureFlags) { return new CallAudioModeStateMachine(systemStateHelper, am, featureFlags); } } private static final AudioAttributes RING_AUDIO_ATTRIBUTES = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) .setLegacyStreamType(AudioManager.STREAM_RING) .build(); public static final AudioFocusRequest RING_AUDIO_FOCUS_REQUEST = new AudioFocusRequest .Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT) .setAudioAttributes(RING_AUDIO_ATTRIBUTES).build(); private static final AudioAttributes CALL_AUDIO_ATTRIBUTES = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) .setLegacyStreamType(AudioManager.STREAM_VOICE_CALL) .build(); public static final AudioFocusRequest CALL_AUDIO_FOCUS_REQUEST = new AudioFocusRequest .Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT) .setAudioAttributes(CALL_AUDIO_ATTRIBUTES).build(); public static class MessageArgs { public boolean hasActiveOrDialingCalls; public boolean hasRingingCalls; Loading Loading @@ -212,6 +231,8 @@ public class CallAudioModeStateMachine extends StateMachine { public static final String STREAMING_STATE_NAME = StreamingFocusState.class.getSimpleName(); public static final String COMMS_STATE_NAME = VoipCallFocusState.class.getSimpleName(); private AudioFocusRequest mCurrentAudioFocusRequest = null; private class BaseState extends State { @Override public boolean processMessage(Message msg) { Loading Loading @@ -310,7 +331,14 @@ public class CallAudioModeStateMachine extends StateMachine { return HANDLED; case AUDIO_OPERATIONS_COMPLETE: Log.i(LOG_TAG, "Abandoning audio focus: now UNFOCUSED"); if (mFeatureFlags.telecomResolveHiddenDependencies()) { if (mCurrentAudioFocusRequest != null) { mAudioManager.abandonAudioFocusRequest(mCurrentAudioFocusRequest); mCurrentAudioFocusRequest = null; } } else { mAudioManager.abandonAudioFocusForCall(); } return HANDLED; default: // The forced focus switch commands are handled by BaseState. Loading Loading @@ -381,7 +409,14 @@ public class CallAudioModeStateMachine extends StateMachine { return HANDLED; case AUDIO_OPERATIONS_COMPLETE: Log.i(LOG_TAG, "Abandoning audio focus: now AUDIO_PROCESSING"); if (mFeatureFlags.telecomResolveHiddenDependencies()) { if (mCurrentAudioFocusRequest != null) { mAudioManager.abandonAudioFocusRequest(mCurrentAudioFocusRequest); mCurrentAudioFocusRequest = null; } } else { mAudioManager.abandonAudioFocusForCall(); } return HANDLED; default: // The forced focus switch commands are handled by BaseState. Loading @@ -406,8 +441,13 @@ public class CallAudioModeStateMachine extends StateMachine { } if (mCallAudioManager.startRinging()) { if (mFeatureFlags.telecomResolveHiddenDependencies()) { mCurrentAudioFocusRequest = RING_AUDIO_FOCUS_REQUEST; mAudioManager.requestAudioFocus(RING_AUDIO_FOCUS_REQUEST); } else { mAudioManager.requestAudioFocusForCall( AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); } // Do not set MODE_RINGTONE if we were previously in the CALL_SCREENING mode -- // this trips up the audio system. if (mAudioManager.getMode() != AudioManager.MODE_CALL_SCREENING) { Loading Loading @@ -504,8 +544,13 @@ public class CallAudioModeStateMachine extends StateMachine { public void enter() { Log.i(LOG_TAG, "Audio focus entering SIM CALL state"); mLocalLog.log("Enter SIM_CALL"); if (mFeatureFlags.telecomResolveHiddenDependencies()) { mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST; mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST); } else { mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); } mAudioManager.setMode(AudioManager.MODE_IN_CALL); mLocalLog.log("Mode MODE_IN_CALL"); mMostRecentMode = AudioManager.MODE_IN_CALL; Loading Loading @@ -587,8 +632,13 @@ public class CallAudioModeStateMachine extends StateMachine { public void enter() { Log.i(LOG_TAG, "Audio focus entering VOIP CALL state"); mLocalLog.log("Enter VOIP_CALL"); if (mFeatureFlags.telecomResolveHiddenDependencies()) { mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST; mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST); } else { mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); } mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); mLocalLog.log("Mode MODE_IN_COMMUNICATION"); mMostRecentMode = AudioManager.MODE_IN_COMMUNICATION; Loading Loading @@ -742,8 +792,13 @@ public class CallAudioModeStateMachine extends StateMachine { public void enter() { Log.i(LOG_TAG, "Audio focus entering TONE/HOLDING state"); mLocalLog.log("Enter TONE/HOLDING"); if (mFeatureFlags.telecomResolveHiddenDependencies()) { mCurrentAudioFocusRequest = CALL_AUDIO_FOCUS_REQUEST; mAudioManager.requestAudioFocus(CALL_AUDIO_FOCUS_REQUEST); } else { mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); } mAudioManager.setMode(mMostRecentMode); mLocalLog.log("Mode " + mMostRecentMode); mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.ACTIVE_FOCUS); Loading Loading @@ -815,16 +870,18 @@ public class CallAudioModeStateMachine extends StateMachine { private final AudioManager mAudioManager; private final SystemStateHelper mSystemStateHelper; private CallAudioManager mCallAudioManager; private FeatureFlags mFeatureFlags; private int mMostRecentMode; private boolean mIsInitialized = false; public CallAudioModeStateMachine(SystemStateHelper systemStateHelper, AudioManager audioManager) { AudioManager audioManager, FeatureFlags featureFlags) { super(CallAudioModeStateMachine.class.getSimpleName()); mAudioManager = audioManager; mSystemStateHelper = systemStateHelper; mMostRecentMode = AudioManager.MODE_NORMAL; mFeatureFlags = featureFlags; createStates(); } Loading @@ -833,11 +890,12 @@ public class CallAudioModeStateMachine extends StateMachine { * Used for testing */ public CallAudioModeStateMachine(SystemStateHelper systemStateHelper, AudioManager audioManager, Looper looper) { AudioManager audioManager, Looper looper, FeatureFlags featureFlags) { super(CallAudioModeStateMachine.class.getSimpleName(), looper); mAudioManager = audioManager; mSystemStateHelper = systemStateHelper; mMostRecentMode = AudioManager.MODE_NORMAL; mFeatureFlags = featureFlags; createStates(); } Loading
src/com/android/server/telecom/CallsManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -655,7 +655,7 @@ public class CallsManager extends Call.ListenerBase mTimeoutsAdapter, mLock); mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine, this, callAudioModeStateMachineFactory.create(systemStateHelper, (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE)), (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE), featureFlags), playerFactory, mRinger, new RingbackPlayer(playerFactory), bluetoothStateReceiver, mDtmfLocalTonePlayer); Loading
tests/src/com/android/server/telecom/tests/BasicCallTests.java +2 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.drawable.Icon; import android.media.AudioDeviceInfo; import android.media.AudioFocusRequest; import android.media.AudioManager; import android.net.Uri; import android.os.Binder; Loading Loading @@ -110,6 +111,7 @@ public class BasicCallTests extends TelecomSystemTest { doReturn(mContext).when(mContext).createContextAsUser(any(UserHandle.class), anyInt()); mPackageManager = mContext.getPackageManager(); when(mPackageManager.getPackageUid(anyString(), eq(0))).thenReturn(Binder.getCallingUid()); when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(false); } @Override Loading
tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java +64 −18 Original line number Diff line number Diff line Loading @@ -16,14 +16,29 @@ package com.android.server.telecom.tests; import static com.android.server.telecom.CallAudioModeStateMachine.CALL_AUDIO_FOCUS_REQUEST; import static com.android.server.telecom.CallAudioModeStateMachine.RING_AUDIO_FOCUS_REQUEST; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.media.AudioFocusRequest; import android.media.AudioManager; import android.os.HandlerThread; import android.test.suitebuilder.annotation.SmallTest; import com.android.server.telecom.CallAudioManager; import com.android.server.telecom.CallAudioModeStateMachine; import com.android.server.telecom.CallAudioRouteStateMachine; import com.android.server.telecom.CallAudioModeStateMachine.MessageArgs.Builder; import com.android.server.telecom.CallAudioRouteStateMachine; import com.android.server.telecom.SystemStateHelper; import org.junit.After; Loading @@ -31,18 +46,9 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(JUnit4.class) public class CallAudioModeStateMachineTest extends TelecomTestCase { private static final int TEST_TIMEOUT = 1000; Loading @@ -62,6 +68,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { super.setUp(); when(mCallAudioManager.getCallAudioRouteStateMachine()) .thenReturn(mCallAudioRouteStateMachine); when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(false); } @Override Loading @@ -76,7 +83,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testNoFocusWhenRingerSilenced() throws Throwable { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -108,7 +115,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testSwitchToStreamingMode() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -138,7 +145,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testExitStreamingMode() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ENTER_STREAMING_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -166,7 +173,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testNoRingWhenDeviceIsAtEar() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); sm.sendMessage(CallAudioModeStateMachine.NEW_HOLDING_CALL, new Builder() Loading Loading @@ -202,7 +209,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testRegainFocusWhenHfpIsConnectedSilenced() throws Throwable { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -246,7 +253,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testDoNotRingTwiceWhenHfpConnected() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -284,7 +291,7 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { @Test public void testStartRingingAfterHfpConnectedIfNotAlreadyPlaying() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); Loading Loading @@ -318,7 +325,46 @@ public class CallAudioModeStateMachineTest extends TelecomTestCase { verify(mCallAudioManager, times(2)).startRinging(); } @SmallTest @Test public void testAudioFocusRequestWithResolveHiddenDependencies() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper(), mFeatureFlags); when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(true); ArgumentCaptor<AudioFocusRequest> captor = ArgumentCaptor.forClass(AudioFocusRequest.class); sm.setCallAudioManager(mCallAudioManager); resetMocks(); when(mCallAudioManager.startRinging()).thenReturn(true); when(mCallAudioManager.isRingtonePlaying()).thenReturn(false); sm.sendMessage(CallAudioModeStateMachine.ENTER_RING_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); verify(mAudioManager).requestAudioFocus(captor.capture()); assertTrue(areAudioFocusRequestsMatch(captor.getValue(), RING_AUDIO_FOCUS_REQUEST)); sm.sendMessage(CallAudioModeStateMachine.ENTER_CALL_FOCUS_FOR_TESTING); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); verify(mAudioManager, atLeast(1)).requestAudioFocus(captor.capture()); AudioFocusRequest request = captor.getValue(); assertTrue(areAudioFocusRequestsMatch(request, CALL_AUDIO_FOCUS_REQUEST)); sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING); } private void resetMocks() { clearInvocations(mCallAudioManager, mAudioManager); } private boolean areAudioFocusRequestsMatch(AudioFocusRequest r1, AudioFocusRequest r2) { if ((r1 == null) || (r2 == null)) { return false; } if (r1.getFocusGain() != r2.getFocusGain()) { return false; } return r1.getAudioAttributes().equals(r2.getAudioAttributes()); } }
tests/src/com/android/server/telecom/tests/CallAudioModeTransitionTests.java +7 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.server.telecom.tests; import static com.android.server.telecom.CallAudioModeStateMachine.CALL_AUDIO_FOCUS_REQUEST; import static com.android.server.telecom.CallAudioModeStateMachine.RING_AUDIO_FOCUS_REQUEST; import android.media.AudioFocusRequest; import android.media.AudioManager; import android.os.HandlerThread; import android.test.suitebuilder.annotation.SmallTest; Loading @@ -37,6 +41,7 @@ import java.util.Collection; import java.util.List; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; Loading Loading @@ -130,13 +135,14 @@ public class CallAudioModeTransitionTests extends TelecomTestCase { @SmallTest public void modeTransitionTest() { CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mSystemStateHelper, mAudioManager, mTestThread.getLooper()); mAudioManager, mTestThread.getLooper(), mFeatureFlags); sm.setCallAudioManager(mCallAudioManager); sm.sendMessage(mParams.initialAudioState); waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); resetMocks(); when(mCallAudioManager.startRinging()).thenReturn(true); when(mFeatureFlags.telecomResolveHiddenDependencies()).thenReturn(false); if (mParams.initialAudioState == CallAudioModeStateMachine.ENTER_AUDIO_PROCESSING_FOCUS_FOR_TESTING) { when(mAudioManager.getMode()) Loading