Guess the correct routing when initializing AudioModeProvider

Previously the default route for AudioModeProvider is ROUTE_EARPIECE. The in call ProximitySensor is initialized before InCallServiceImpl is fully bound, and the real route is not updated by telecom yet, which will cause a proximity wake lock to be held on bluetooth and turn off the screen.

In this CL, when initializing AudioModeProvider the routing will be guessed based on what audio devices is connected.

Bug: 64211001
Test: AudioModeProviderTest
PiperOrigin-RevId: 165987811
Change-Id: I0a976a9654fbf5b6f966d45d219a3d3685b207f5
diff --git a/java/com/android/incallui/InCallServiceImpl.java b/java/com/android/incallui/InCallServiceImpl.java
index a2e2432..a08ee0a 100644
--- a/java/com/android/incallui/InCallServiceImpl.java
+++ b/java/com/android/incallui/InCallServiceImpl.java
@@ -77,6 +77,7 @@
     Trace.beginSection("InCallServiceImpl.onBind");
     final Context context = getApplicationContext();
     final ContactInfoCache contactInfoCache = ContactInfoCache.getInstance(context);
+    AudioModeProvider.getInstance().initializeAudioState(this);
     InCallPresenter.getInstance()
         .setUp(
             context,
diff --git a/java/com/android/incallui/audiomode/AudioModeProvider.java b/java/com/android/incallui/audiomode/AudioModeProvider.java
index f62afa7..eb59e95 100644
--- a/java/com/android/incallui/audiomode/AudioModeProvider.java
+++ b/java/com/android/incallui/audiomode/AudioModeProvider.java
@@ -16,7 +16,11 @@
 
 package com.android.incallui.audiomode;
 
+import android.content.Context;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
 import android.telecom.CallAudioState;
+import com.android.dialer.common.LogUtil;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -61,6 +65,47 @@
     return audioState;
   }
 
+  /**
+   * Sets a approximated audio state before {@link #onAudioStateChanged} is called. Classes such as
+   * {@link com.android.incallui.ProximitySensor} fetches the audio state before it is updated by
+   * telecom. This method attempts to guess the correct routing based on connected audio devices.
+   * The audio state may still be wrong on a second call due to b/64811128, telecom setting the
+   * route back to earpiece when a call ends.
+   */
+  public void initializeAudioState(Context context) {
+    onAudioStateChanged(
+        new CallAudioState(false, getApproximatedAudioRoute(context), SUPPORTED_AUDIO_ROUTE_ALL));
+  }
+
+  private static int getApproximatedAudioRoute(Context context) {
+    AudioManager audioManager = context.getSystemService(AudioManager.class);
+    boolean hasBluetooth = false;
+    boolean hasHeadset = false;
+    for (AudioDeviceInfo info : audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)) {
+      switch (info.getType()) {
+        case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP:
+        case AudioDeviceInfo.TYPE_BLUETOOTH_SCO:
+          hasBluetooth = true;
+          continue;
+        case AudioDeviceInfo.TYPE_WIRED_HEADSET:
+          hasHeadset = true;
+          continue;
+        default:
+          continue;
+      }
+    }
+    if (hasBluetooth) {
+      LogUtil.i("AudioModeProvider.getApproximatedAudioRoute", "Routing to bluetooth");
+      return CallAudioState.ROUTE_BLUETOOTH;
+    }
+    if (hasHeadset) {
+      LogUtil.i("AudioModeProvider.getApproximatedAudioRoute", "Routing to headset");
+      return CallAudioState.ROUTE_WIRED_HEADSET;
+    }
+    LogUtil.i("AudioModeProvider.getApproximatedAudioRoute", "Routing to earpiece");
+    return CallAudioState.ROUTE_EARPIECE;
+  }
+
   /** Notified on changes to audio mode. */
   public interface AudioModeListener {