Don't acquire audio focus if ringtone will not play

When the system volume is at some level that prevents an audible
ringtone from playing, don't grab audio focus so as to not interrupt
music that is playing.

Fix: 31319655

Change-Id: Ia2e4bc4b2ca8fe88e893cfd307d33e94de2b33ba
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index aff1362..236df5f 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -422,8 +422,8 @@
     }
 
     @VisibleForTesting
-    public void startRinging() {
-        mRinger.startRinging(mForegroundCall);
+    public boolean startRinging() {
+        return mRinger.startRinging(mForegroundCall);
     }
 
     @VisibleForTesting
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index c4dbab1..57043bc 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -201,19 +201,22 @@
         @Override
         public void enter() {
             Log.i(LOG_TAG, "Audio focus entering RINGING state");
-            mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
-                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
-            if (mMostRecentMode == AudioManager.MODE_IN_CALL) {
-                // Preserving behavior from the old CallAudioManager.
-                Log.i(LOG_TAG, "Transition from IN_CALL -> RINGTONE."
-                        + "  Resetting to NORMAL first.");
-                mAudioManager.setMode(AudioManager.MODE_NORMAL);
+            if (mCallAudioManager.startRinging()) {
+                mAudioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
+                        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+                if (mMostRecentMode == AudioManager.MODE_IN_CALL) {
+                    // Preserving behavior from the old CallAudioManager.
+                    Log.i(LOG_TAG, "Transition from IN_CALL -> RINGTONE."
+                            + "  Resetting to NORMAL first.");
+                    mAudioManager.setMode(AudioManager.MODE_NORMAL);
+                }
+                mAudioManager.setMode(AudioManager.MODE_RINGTONE);
+                mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.RINGING_FOCUS);
+            } else {
+                Log.i(LOG_TAG, "Entering RINGING but not acquiring focus -- silent ringtone");
             }
-            mAudioManager.setMode(AudioManager.MODE_RINGTONE);
 
             mCallAudioManager.stopCallWaiting();
-            mCallAudioManager.startRinging();
-            mCallAudioManager.setCallAudioRouteFocusState(CallAudioRouteStateMachine.RINGING_FOCUS);
         }
 
         @Override
diff --git a/src/com/android/server/telecom/Ringer.java b/src/com/android/server/telecom/Ringer.java
index 77b1590..262f437 100644
--- a/src/com/android/server/telecom/Ringer.java
+++ b/src/com/android/server/telecom/Ringer.java
@@ -94,30 +94,32 @@
         mInCallController = inCallController;
     }
 
-    public void startRinging(Call foregroundCall) {
+    public boolean startRinging(Call foregroundCall) {
+        AudioManager audioManager =
+                (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        boolean isRingerAudible = audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0;
+
         if (mSystemSettingsUtil.isTheaterModeOn(mContext)) {
-            return;
+            return false;
         }
 
         if (foregroundCall == null) {
             Log.wtf(this, "startRinging called with null foreground call.");
-            return;
+            return false;
         }
 
         if (mInCallController.doesConnectedDialerSupportRinging()) {
             Log.event(foregroundCall, Log.Events.SKIP_RINGING);
-            return;
+            return isRingerAudible;
         }
 
         stopCallWaiting();
 
         if (!shouldRingForContact(foregroundCall.getContactUri())) {
-            return;
+            return false;
         }
 
-        AudioManager audioManager =
-                (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-        if (audioManager.getStreamVolume(AudioManager.STREAM_RING) > 0) {
+        if (isRingerAudible) {
             mRingingCall = foregroundCall;
             Log.event(foregroundCall, Log.Events.START_RINGER);
             // Because we wait until a contact info query to complete before processing a
@@ -126,7 +128,7 @@
             // request the custom ringtone from the call and expect it to be current.
             mRingtonePlayer.play(mRingtoneFactory, foregroundCall);
         } else {
-            Log.v(this, "startRingingOrCallWaiting, skipping because volume is 0");
+            Log.i(this, "startRingingOrCallWaiting, skipping because volume is 0");
         }
 
         if (shouldVibrate(mContext) && !mIsVibrating) {
@@ -134,6 +136,8 @@
                     VIBRATION_ATTRIBUTES);
             mIsVibrating = true;
         }
+
+        return isRingerAudible;
     }
 
     public void startCallWaiting(Call call) {
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
index f9502dd..38ea10e 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioModeStateMachineTest.java
@@ -18,6 +18,7 @@
 
 import android.media.AudioManager;
 import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.server.telecom.CallAudioManager;
 import com.android.server.telecom.CallAudioModeStateMachine;
@@ -32,6 +33,7 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 public class CallAudioModeStateMachineTest extends StateMachineTestBase<CallAudioModeStateMachine> {
     private static class ModeTestParameters extends TestParameters {
@@ -100,6 +102,37 @@
         parametrizedTestStateMachine(testCases);
     }
 
+    @SmallTest
+    public void testNoFocusWhenRingerSilenced() throws Throwable {
+        CallAudioModeStateMachine sm = new CallAudioModeStateMachine(mAudioManager);
+        sm.setCallAudioManager(mCallAudioManager);
+        sm.sendMessage(CallAudioModeStateMachine.ABANDON_FOCUS_FOR_TESTING);
+        waitForStateMachineActionCompletion(sm, CallAudioModeStateMachine.RUN_RUNNABLE);
+
+        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
+                ));
+        waitForStateMachineActionCompletion(sm, CallAudioModeStateMachine.RUN_RUNNABLE);
+
+        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();
+    }
+
     private List<ModeTestParameters> generateTestCases() {
         List<ModeTestParameters> result = new ArrayList<>();
         result.add(new ModeTestParameters(
@@ -516,6 +549,7 @@
         waitForStateMachineActionCompletion(sm, CallAudioModeStateMachine.RUN_RUNNABLE);
 
         resetMocks();
+        when(mCallAudioManager.startRinging()).thenReturn(true);
 
         sm.sendMessage(params.messageType, params.externalState);
         waitForStateMachineActionCompletion(sm, CallAudioModeStateMachine.RUN_RUNNABLE);