Switch to speakerphone when upgrading to video

When an audio-only call gets upgraded to a video call, switch to
speakerphone if the call would have been started in speakerphone had it
been a video call from the beginning (i.e. if there's no headset or
bluetooth connected and config options support it)

Change-Id: I4b8eb1c0f21753a8878f72d9279335a946c9f5a9
Fixes: 29563103
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 6bb9bdb..c11ccca 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -103,7 +103,7 @@
         void onExtrasRemoved(Call c, int source, List<String> keys);
         void onHandleChanged(Call call);
         void onCallerDisplayNameChanged(Call call);
-        void onVideoStateChanged(Call call);
+        void onVideoStateChanged(Call call, int previousVideoState, int newVideoState);
         void onTargetPhoneAccountChanged(Call call);
         void onConnectionManagerPhoneAccountChanged(Call call);
         void onPhoneAccountChanged(Call call);
@@ -160,7 +160,7 @@
         @Override
         public void onCallerDisplayNameChanged(Call call) {}
         @Override
-        public void onVideoStateChanged(Call call) {}
+        public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {}
         @Override
         public void onTargetPhoneAccountChanged(Call call) {}
         @Override
@@ -1895,11 +1895,14 @@
             mVideoStateHistory = mVideoStateHistory | videoState;
         }
 
-        Log.event(this, Log.Events.VIDEO_STATE_CHANGED,
-                VideoProfile.videoStateToString(videoState));
+        int previousVideoState = mVideoState;
         mVideoState = videoState;
-        for (Listener l : mListeners) {
-            l.onVideoStateChanged(this);
+        if (mVideoState != previousVideoState) {
+            Log.event(this, Log.Events.VIDEO_STATE_CHANGED,
+                    VideoProfile.videoStateToString(videoState));
+            for (Listener l : mListeners) {
+                l.onVideoStateChanged(this, previousVideoState, mVideoState);
+            }
         }
     }
 
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index 75a0b55..0ff80f4 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -314,6 +314,25 @@
                 CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE);
     }
 
+    @Override
+    public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {
+        if (call != getForegroundCall()) {
+            Log.d(LOG_TAG, "Ignoring video state change from %s to %s for call %s -- not " +
+                    "foreground.", VideoProfile.videoStateToString(previousVideoState),
+                    VideoProfile.videoStateToString(newVideoState), call.getId());
+            return;
+        }
+
+        if (!VideoProfile.isVideo(previousVideoState) &&
+                mCallsManager.isSpeakerphoneAutoEnabledForVideoCalls(newVideoState)) {
+            Log.d(LOG_TAG, "Switching to speaker because call %s transitioned video state from %s" +
+                    " to %s", call.getId(), VideoProfile.videoStateToString(previousVideoState),
+                    VideoProfile.videoStateToString(newVideoState));
+            mCallAudioRouteStateMachine.sendMessageWithSessionInfo(
+                    CallAudioRouteStateMachine.SWITCH_SPEAKER);
+        }
+    }
+
     public CallAudioState getCallAudioState() {
         return mCallAudioRouteStateMachine.getCurrentCallAudioState();
     }
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 2ebe38c..a099a5f 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -102,7 +102,7 @@
         void onRingbackRequested(Call call, boolean ringback);
         void onIsConferencedChanged(Call call);
         void onIsVoipAudioModeChanged(Call call);
-        void onVideoStateChanged(Call call);
+        void onVideoStateChanged(Call call, int previousVideoState, int newVideoState);
         void onCanAddCallChanged(boolean canAddCall);
         void onSessionModifyRequestReceived(Call call, VideoProfile videoProfile);
         void onHoldToneRequested(Call call);
@@ -493,9 +493,9 @@
     }
 
     @Override
-    public void onVideoStateChanged(Call call) {
+    public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {
         for (CallsManagerListener listener : mListeners) {
-            listener.onVideoStateChanged(call);
+            listener.onVideoStateChanged(call, previousVideoState, newVideoState);
         }
     }
 
@@ -924,7 +924,7 @@
         final boolean useSpeakerWhenDocked = mContext.getResources().getBoolean(
                 R.bool.use_speaker_when_docked);
         final boolean useSpeakerForDock = isSpeakerphoneEnabledForDock();
-        final boolean useSpeakerForVideoCall = isSpeakerphoneAutoEnabled(videoState);
+        final boolean useSpeakerForVideoCall = isSpeakerphoneAutoEnabledForVideoCalls(videoState);
 
         // Auto-enable speakerphone if the originating intent specified to do so, if the call
         // is a video call, of if using speaker when docked
@@ -1023,7 +1023,7 @@
             // We do not update the UI until we get confirmation of the answer() through
             // {@link #markCallAsActive}.
             call.answer(videoState);
-            if (isSpeakerphoneAutoEnabled(videoState)) {
+            if (isSpeakerphoneAutoEnabledForVideoCalls(videoState)) {
                 call.setStartWithSpeakerphoneOn(true);
             }
         }
@@ -1037,7 +1037,7 @@
      * @param videoState The video state of the call.
      * @return {@code true} if the speakerphone should be enabled.
      */
-    private boolean isSpeakerphoneAutoEnabled(int videoState) {
+    public boolean isSpeakerphoneAutoEnabledForVideoCalls(int videoState) {
         return VideoProfile.isVideo(videoState) &&
             !mWiredHeadsetManager.isPluggedIn() &&
             !mBluetoothManager.isBluetoothAvailable() &&
diff --git a/src/com/android/server/telecom/CallsManagerListenerBase.java b/src/com/android/server/telecom/CallsManagerListenerBase.java
index 9bfa098..a4c76c1 100644
--- a/src/com/android/server/telecom/CallsManagerListenerBase.java
+++ b/src/com/android/server/telecom/CallsManagerListenerBase.java
@@ -69,7 +69,7 @@
     }
 
     @Override
-    public void onVideoStateChanged(Call call) {
+    public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {
     }
 
     @Override
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 9bca355..c482b42 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -546,7 +546,7 @@
         }
 
         @Override
-        public void onVideoStateChanged(Call call) {
+        public void onVideoStateChanged(Call call, int previousVideoState, int newVideoState) {
             updateCall(call);
         }