Merge changes from topic "hookup-callscreening-api-2" am: 70338952d2 am: d8b7828fe8 am: dd4ae3fa46
am: a60734b438

Change-Id: Ia357f68438f989b234365ea4ff01013e7169a49a
diff --git a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
index 33dddbd..e80eeba 100644
--- a/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
+++ b/src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
@@ -78,12 +78,15 @@
     // Add all held calls to a conference
     private static final int CHLD_TYPE_ADDHELDTOCONF = 3;
 
+    // Indicates that no call is ringing
+    private static final int DEFAULT_RINGING_ADDRESS_TYPE = 128;
+
     private int mNumActiveCalls = 0;
     private int mNumHeldCalls = 0;
     private int mNumChildrenOfActiveCall = 0;
     private int mBluetoothCallState = CALL_STATE_IDLE;
-    private String mRingingAddress = null;
-    private int mRingingAddressType = 0;
+    private String mRingingAddress = "";
+    private int mRingingAddressType = DEFAULT_RINGING_ADDRESS_TYPE;
     private Call mOldHeldCall = null;
     private boolean mIsDisconnectedTonePlaying = false;
 
@@ -101,7 +104,7 @@
                 long token = Binder.clearCallingIdentity();
                 try {
                     Log.i(TAG, "BT - answering call");
-                    Call call = mCallsManager.getRingingCall();
+                    Call call = mCallsManager.getRingingOrSimulatedRingingCall();
                     if (call != null) {
                         mCallsManager.answerCall(call, VideoProfile.STATE_AUDIO_ONLY);
                         return true;
@@ -493,7 +496,7 @@
 
     private boolean processChld(int chld) {
         Call activeCall = mCallsManager.getActiveCall();
-        Call ringingCall = mCallsManager.getRingingCall();
+        Call ringingCall = mCallsManager.getRingingOrSimulatedRingingCall();
         Call heldCall = mCallsManager.getHeldCall();
 
         // TODO: Keeping as Log.i for now.  Move to Log.d after L release if BT proves stable.
@@ -699,13 +702,13 @@
      */
     private void updateHeadsetWithCallState(boolean force) {
         Call activeCall = mCallsManager.getActiveCall();
-        Call ringingCall = mCallsManager.getRingingCall();
+        Call ringingCall = mCallsManager.getRingingOrSimulatedRingingCall();
         Call heldCall = mCallsManager.getHeldCall();
 
         int bluetoothCallState = getBluetoothCallStateForUpdate();
 
         String ringingAddress = null;
-        int ringingAddressType = 128;
+        int ringingAddressType = DEFAULT_RINGING_ADDRESS_TYPE;
         String ringingName = null;
         if (ringingCall != null && ringingCall.getHandle() != null
             && !ringingCall.isSilentRingingRequested()) {
@@ -832,7 +835,7 @@
     }
 
     private int getBluetoothCallStateForUpdate() {
-        Call ringingCall = mCallsManager.getRingingCall();
+        Call ringingCall = mCallsManager.getRingingOrSimulatedRingingCall();
         Call dialingCall = mCallsManager.getOutgoingCall();
         boolean hasOnlyDisconnectedCalls = mCallsManager.hasOnlyDisconnectedCalls();
 
@@ -862,6 +865,7 @@
             case CallState.NEW:
             case CallState.ABORTED:
             case CallState.DISCONNECTED:
+            case CallState.AUDIO_PROCESSING:
                 return CALL_STATE_IDLE;
 
             case CallState.ACTIVE:
@@ -885,6 +889,7 @@
 
             case CallState.RINGING:
             case CallState.ANSWERED:
+            case CallState.SIMULATED_RINGING:
                 if (call.isSilentRingingRequested()) {
                     return CALL_STATE_IDLE;
                 } else if (isForeground) {
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index 06d9854..87ca26c 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -115,6 +115,7 @@
         if (newBinForCall != null) {
             newBinForCall.add(call);
         }
+        sendCallStatusToBluetoothStateReceiver();
 
         updateForegroundCall();
         if (shouldPlayDisconnectTone(oldState, newState)) {
@@ -158,9 +159,7 @@
         }
         updateForegroundCall();
         mCalls.add(call);
-        if (mCalls.size() == 1) {
-            mBluetoothStateReceiver.setIsInCall(true);
-        }
+        sendCallStatusToBluetoothStateReceiver();
 
         onCallEnteringState(call, call.getState());
     }
@@ -177,13 +176,17 @@
 
         updateForegroundCall();
         mCalls.remove(call);
-        if (mCalls.size() == 0) {
-            mBluetoothStateReceiver.setIsInCall(false);
-        }
+        sendCallStatusToBluetoothStateReceiver();
 
         onCallLeavingState(call, call.getState());
     }
 
+    private void sendCallStatusToBluetoothStateReceiver() {
+        // We're in a call if there are calls in mCalls that are not in mAudioProcessingCalls.
+        boolean isInCall = !mAudioProcessingCalls.containsAll(mCalls);
+        mBluetoothStateReceiver.setIsInCall(isInCall);
+    }
+
     /**
      * Handles changes to the external state of a call.  External calls which become regular calls
      * should be tracked, and regular calls which become external should no longer be tracked.
diff --git a/src/com/android/server/telecom/CallAudioModeStateMachine.java b/src/com/android/server/telecom/CallAudioModeStateMachine.java
index 06be216..1d3752b 100644
--- a/src/com/android/server/telecom/CallAudioModeStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioModeStateMachine.java
@@ -329,8 +329,7 @@
                     transitionTo(mOtherFocusState);
                     return HANDLED;
                 case NEW_AUDIO_PROCESSING_CALL:
-                    Log.w(LOG_TAG, "Unexpected behavior! New audio processing call appeared while"
-                            + " in audio processing state.");
+                    // Can happen as a duplicate message
                     return HANDLED;
                 case TONE_STARTED_PLAYING:
                     // This shouldn't happen either, but perform the action anyway.
@@ -404,8 +403,7 @@
                                 + "ringing");
                     }
                 case NEW_RINGING_CALL:
-                    Log.w(LOG_TAG, "Unexpected behavior! New ringing call appeared while in " +
-                            "ringing state.");
+                    // Can happen as a duplicate message
                     return HANDLED;
                 case NEW_HOLDING_CALL:
                     // This really shouldn't happen, but transition to the focused state anyway.
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index e96a61a..e7c03fb 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -2733,6 +2733,11 @@
         return getFirstCallWithState(CallState.RINGING, CallState.ANSWERED) != null;
     }
 
+    boolean hasRingingOrSimulatedRingingCall() {
+        return getFirstCallWithState(
+                CallState.SIMULATED_RINGING, CallState.RINGING, CallState.ANSWERED) != null;
+    }
+
     @VisibleForTesting
     public boolean onMediaButton(int type) {
         if (hasAnyCalls()) {
@@ -2835,8 +2840,9 @@
     }
 
     @VisibleForTesting
-    public Call getRingingCall() {
-        return getFirstCallWithState(CallState.RINGING, CallState.ANSWERED);
+    public Call getRingingOrSimulatedRingingCall() {
+        return getFirstCallWithState(CallState.RINGING,
+                CallState.ANSWERED, CallState.SIMULATED_RINGING);
     }
 
     public Call getActiveCall() {
diff --git a/src/com/android/server/telecom/InCallWakeLockController.java b/src/com/android/server/telecom/InCallWakeLockController.java
index ac93bb5..b37883d 100644
--- a/src/com/android/server/telecom/InCallWakeLockController.java
+++ b/src/com/android/server/telecom/InCallWakeLockController.java
@@ -62,7 +62,7 @@
 
     private void handleWakeLock() {
         // We grab a full lock as long as there exists a ringing call.
-        Call ringingCall = mCallsManager.getRingingCall();
+        Call ringingCall = mCallsManager.getRingingOrSimulatedRingingCall();
         if (ringingCall != null) {
             mTelecomWakeLock.acquire();
             Log.i(this, "Acquiring full wake lock");
diff --git a/src/com/android/server/telecom/PhoneStateBroadcaster.java b/src/com/android/server/telecom/PhoneStateBroadcaster.java
index 8493c5b..533c81c 100644
--- a/src/com/android/server/telecom/PhoneStateBroadcaster.java
+++ b/src/com/android/server/telecom/PhoneStateBroadcaster.java
@@ -85,7 +85,7 @@
         // Note: CallsManager#hasRingingCall() and CallsManager#getFirstCallWithState(..) do not
         // consider external calls, so an external call is going to cause the state to be idle.
         int callState = TelephonyManager.CALL_STATE_IDLE;
-        if (mCallsManager.hasRingingCall()) {
+        if (mCallsManager.hasRingingOrSimulatedRingingCall()) {
             callState = TelephonyManager.CALL_STATE_RINGING;
         } else if (mCallsManager.getFirstCallWithState(CallState.DIALING, CallState.PULLING,
                 CallState.ACTIVE, CallState.ON_HOLD) != null) {
diff --git a/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java b/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java
index 68129f2..544eb28 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestCallScreeningService.java
@@ -21,6 +21,11 @@
 import android.telecom.CallScreeningService;
 import android.telecom.Log;
 
+/**
+ * To use this while testing, use:
+ * adb shell setprop com.android.server.telecom.testapps.callscreeningresult n,
+ * where n is one of the codes defined below.
+ */
 public class TestCallScreeningService extends CallScreeningService {
     private Call.Details mDetails;
     private static TestCallScreeningService sTestCallScreeningService;
diff --git a/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java b/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
index e31c6ba..edcbba1 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
@@ -177,7 +177,8 @@
 
         answerButton.setOnClickListener(view -> {
             Call call = mCallList.getCall(0);
-            if (call.getState() == Call.STATE_RINGING) {
+            if (call.getState() == Call.STATE_RINGING
+                    || call.getState() == Call.STATE_SIMULATED_RINGING) {
                 call.answer(VideoProfile.STATE_AUDIO_ONLY);
             }
         });
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java b/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java
index 882f437..16e6355 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothPhoneServiceTest.java
@@ -113,7 +113,7 @@
         doNothing().when(mMockCallsManager).addListener(any(
                 CallsManager.CallsManagerListener.class));
         doReturn(null).when(mMockCallsManager).getActiveCall();
-        doReturn(null).when(mMockCallsManager).getRingingCall();
+        doReturn(null).when(mMockCallsManager).getRingingOrSimulatedRingingCall();
         doReturn(null).when(mMockCallsManager).getHeldCall();
         doReturn(null).when(mMockCallsManager).getOutgoingCall();
         doReturn(0).when(mMockCallsManager).getNumHeldCalls();
@@ -147,7 +147,7 @@
     @SmallTest
     @Test
     public void testHeadsetAnswerCallNull() throws Exception {
-        when(mMockCallsManager.getRingingCall()).thenReturn(null);
+        when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
 
         boolean callAnswered = mBluetoothPhoneService.mBinder.answerCall();
 
@@ -282,7 +282,7 @@
         when(silentRingingCall.isConference()).thenReturn(false);
         when(silentRingingCall.getHandle()).thenReturn(Uri.parse("tel:555-000"));
         when(mMockCallsManager.getCalls()).thenReturn(calls);
-        when(mMockCallsManager.getRingingCall()).thenReturn(silentRingingCall);
+        when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(silentRingingCall);
 
         mBluetoothPhoneService.mBinder.listCurrentCalls();
 
@@ -819,8 +819,8 @@
 
         mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);
 
-        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
-            eq(""), eq(128), nullable(String.class));
+        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
+                anyString(), anyInt(), nullable(String.class));
     }
 
     @MediumTest
@@ -876,6 +876,64 @@
 
     @MediumTest
     @Test
+    public void testOnCallAddedAudioProcessing() throws Exception {
+        Call call = mock(Call.class);
+        when(call.getState()).thenReturn(CallState.AUDIO_PROCESSING);
+        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(call);
+
+        verify(mMockBluetoothHeadset, never()).phoneStateChanged(anyInt(), anyInt(), anyInt(),
+                anyString(), anyInt(), nullable(String.class));
+    }
+
+    @MediumTest
+    @Test
+    public void testOnCallStateChangedRingingToAudioProcessing() throws Exception {
+        Call ringingCall = createRingingCall();
+        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555000"));
+
+        mBluetoothPhoneService.mCallsManagerListener.onCallAdded(ringingCall);
+
+        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
+                eq("555000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
+
+        when(ringingCall.getState()).thenReturn(CallState.AUDIO_PROCESSING);
+        when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
+
+        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(ringingCall,
+                CallState.RINGING, CallState.AUDIO_PROCESSING);
+
+        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_IDLE),
+                eq(""), eq(128), nullable(String.class));
+    }
+
+    @MediumTest
+    @Test
+    public void testOnCallStateChangedAudioProcessingToSimulatedRinging() throws Exception {
+        Call ringingCall = createRingingCall();
+        when(ringingCall.getHandle()).thenReturn(Uri.parse("tel:555-0000"));
+
+        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(ringingCall,
+                CallState.AUDIO_PROCESSING, CallState.SIMULATED_RINGING);
+
+        verify(mMockBluetoothHeadset).phoneStateChanged(eq(0), eq(0), eq(CALL_STATE_INCOMING),
+                eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
+    }
+
+    @MediumTest
+    @Test
+    public void testOnCallStateChangedAudioProcessingToActive() throws Exception {
+        Call activeCall = createActiveCall();
+        when(activeCall.getState()).thenReturn(CallState.ACTIVE);
+
+        mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(activeCall,
+                CallState.AUDIO_PROCESSING, CallState.ACTIVE);
+
+        verify(mMockBluetoothHeadset).phoneStateChanged(eq(1), eq(0), eq(CALL_STATE_IDLE),
+                eq(""), eq(128), nullable(String.class));
+    }
+
+    @MediumTest
+    @Test
     public void testOnCallStateChangedDialing() throws Exception {
         Call activeCall = createActiveCall();
 
@@ -931,7 +989,7 @@
                 eq("555-0000"), eq(PhoneNumberUtils.TOA_Unknown), nullable(String.class));
 
         //Switch to active
-        doReturn(null).when(mMockCallsManager).getRingingCall();
+        doReturn(null).when(mMockCallsManager).getRingingOrSimulatedRingingCall();
         when(mMockCallsManager.getActiveCall()).thenReturn(ringingCall);
 
         mBluetoothPhoneService.mCallsManagerListener.onCallStateChanged(ringingCall,
@@ -1021,7 +1079,7 @@
 
     private Call createRingingCall() {
         Call call = mock(Call.class);
-        when(mMockCallsManager.getRingingCall()).thenReturn(call);
+        when(mMockCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(call);
         return call;
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/InCallWakeLockControllerTest.java b/tests/src/com/android/server/telecom/tests/InCallWakeLockControllerTest.java
index fd581f3..fd7505b 100644
--- a/tests/src/com/android/server/telecom/tests/InCallWakeLockControllerTest.java
+++ b/tests/src/com/android/server/telecom/tests/InCallWakeLockControllerTest.java
@@ -66,7 +66,7 @@
     @SmallTest
     @Test
     public void testRingingCallAdded() throws Exception {
-        when(mCallsManager.getRingingCall()).thenReturn(mCall);
+        when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(mCall);
         when(mWakeLockAdapter.isHeld()).thenReturn(false);
 
         mInCallWakeLockController.onCallAdded(mCall);
@@ -77,7 +77,7 @@
     @SmallTest
     @Test
     public void testNonRingingCallAdded() throws Exception {
-        when(mCallsManager.getRingingCall()).thenReturn(null);
+        when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
         when(mWakeLockAdapter.isHeld()).thenReturn(false);
 
         mInCallWakeLockController.onCallAdded(mCall);
@@ -88,7 +88,7 @@
     @SmallTest
     @Test
     public void testRingingCallTransition() throws Exception {
-        when(mCallsManager.getRingingCall()).thenReturn(mCall);
+        when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(mCall);
         when(mWakeLockAdapter.isHeld()).thenReturn(false);
 
         mInCallWakeLockController.onCallStateChanged(mCall, CallState.NEW, CallState.RINGING);
@@ -99,7 +99,7 @@
     @SmallTest
     @Test
     public void testRingingCallRemoved() throws Exception {
-        when(mCallsManager.getRingingCall()).thenReturn(null);
+        when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
         when(mWakeLockAdapter.isHeld()).thenReturn(false);
 
         mInCallWakeLockController.onCallRemoved(mCall);
@@ -110,7 +110,7 @@
     @SmallTest
     @Test
     public void testWakeLockReleased() throws Exception {
-        when(mCallsManager.getRingingCall()).thenReturn(null);
+        when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(null);
         when(mWakeLockAdapter.isHeld()).thenReturn(true);
 
         mInCallWakeLockController.onCallRemoved(mCall);
@@ -121,7 +121,7 @@
     @SmallTest
     @Test
     public void testAcquireWakeLockWhenHeld() throws Exception {
-        when(mCallsManager.getRingingCall()).thenReturn(mCall);
+        when(mCallsManager.getRingingOrSimulatedRingingCall()).thenReturn(mCall);
         when(mWakeLockAdapter.isHeld()).thenReturn(true);
 
         mInCallWakeLockController.onCallAdded(mock(Call.class));