Integrate the BT multi-hfp apis with Telecom

Add a call to setActiveDevice when setting a bluetooth device

Test: unit, testapps
Change-Id: Ibd7c7f976c2caf834228745f8bedf24767d500b8
Merged-In: I3a2f0ae4e683bd18332f5b986c2936040187b1dc
Fixes: 78653642
diff --git a/testapps/AndroidManifest.xml b/testapps/AndroidManifest.xml
index a539de9..48451d1 100644
--- a/testapps/AndroidManifest.xml
+++ b/testapps/AndroidManifest.xml
@@ -22,6 +22,7 @@
         android:minSdkVersion="23"
         android:targetSdkVersion="23" />
 
+    <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.CALL_PHONE" />
     <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE" />
diff --git a/testapps/res/layout/incall_screen.xml b/testapps/res/layout/incall_screen.xml
index 36ffb27..452cb2b 100644
--- a/testapps/res/layout/incall_screen.xml
+++ b/testapps/res/layout/incall_screen.xml
@@ -29,7 +29,7 @@
     <GridLayout
         android:columnCount="3"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:orientation="horizontal">
         <Button
             android:id="@+id/end_call_button"
@@ -72,4 +72,48 @@
             android:layout_height="wrap_content"
             android:text="@string/handoverButton"/>
     </GridLayout>
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <Spinner
+            android:id="@+id/available_bt_devices"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+        <Button
+            android:id="@+id/set_bt_device_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/setBtDeviceButton"/>
+    </LinearLayout>
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <Button
+            android:id="@+id/earpiece_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/earpieceButton"/>
+        <Button
+            android:id="@+id/speaker_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/speakerButton"/>
+    </LinearLayout>
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <TextView
+            android:id="@+id/current_route_label"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/currentRouteLabel"/>
+        <TextView
+            android:id="@+id/current_audio_route"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="10dp"/>
+    </LinearLayout>
 </LinearLayout>
diff --git a/testapps/res/values/donottranslate_strings.xml b/testapps/res/values/donottranslate_strings.xml
index a0485d0..abd2949 100644
--- a/testapps/res/values/donottranslate_strings.xml
+++ b/testapps/res/values/donottranslate_strings.xml
@@ -68,6 +68,13 @@
 
     <string name="getKeyButton">Get Key Json</string>
 
+    <string name="earpieceButton">Earpiece/Wired</string>
+
+    <string name="speakerButton">Speakerphone</string>
+
+    <string name="setBtDeviceButton">Set BT device</string>
+
+    <string name="currentRouteLabel">Current audio route</string>
     <!-- String for button in SelfManagedCallingActivity. -->
     <string name="checkIfPermittedBeforeCallingButton">Check if calls permitted before calling</string>
 
diff --git a/testapps/src/com/android/server/telecom/testapps/TestInCallServiceImpl.java b/testapps/src/com/android/server/telecom/testapps/TestInCallServiceImpl.java
index 03ca3d0..78b8bcc 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestInCallServiceImpl.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestInCallServiceImpl.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.telecom.Call;
+import android.telecom.CallAudioState;
 import android.telecom.InCallService;
 import android.telecom.Phone;
 import android.util.Log;
@@ -32,6 +33,7 @@
  */
 public class TestInCallServiceImpl extends InCallService {
     private static final String TAG = "TestInCallServiceImpl";
+    public static TestInCallServiceImpl sInstance;
 
     private Phone mPhone;
 
@@ -63,14 +65,24 @@
     }
 
     @Override
-    public void onPhoneDestroyed(Phone phone) {
+    public boolean onUnbind(Intent intent) {
         Log.i(TAG, "onPhoneDestroyed");
         mPhone.removeListener(mPhoneListener);
         mPhone = null;
         TestCallList.getInstance().clearCalls();
+        sInstance = null;
+        return super.onUnbind(intent);
+    }
+
+    @Override
+    public void onCallAudioStateChanged(CallAudioState cas) {
+        if (TestInCallUI.sInstance != null) {
+            TestInCallUI.sInstance.updateCallAudioState(cas);
+        }
     }
 
     private void startInCallUI() {
+        sInstance = this;
         Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.setClass(this, TestInCallUI.class);
diff --git a/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java b/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
index d99798c..9851253 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestInCallUI.java
@@ -17,9 +17,11 @@
 package com.android.server.telecom.testapps;
 
 import android.app.Activity;
+import android.bluetooth.BluetoothDevice;
 import android.content.Intent;
 import android.os.Bundle;
 import android.telecom.Call;
+import android.telecom.CallAudioState;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
@@ -27,21 +29,50 @@
 import android.util.Log;
 import android.view.View;
 import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
 import android.widget.ListView;
+import android.widget.Spinner;
+import android.widget.TextView;
 import android.widget.Toast;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
 
 public class TestInCallUI extends Activity {
+    private class BluetoothDeviceAdapter extends ArrayAdapter<BluetoothDevice> {
+        public BluetoothDeviceAdapter() {
+            super(TestInCallUI.this, android.R.layout.simple_spinner_item);
+            setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        }
 
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            BluetoothDevice info = getItem(position);
+            TextView result = new TextView(TestInCallUI.this);
+            result.setText(info.getName());
+            return result;
+        }
+
+        public void update(Collection<BluetoothDevice> devices) {
+            clear();
+            addAll(devices);
+        }
+    }
+
+    public static TestInCallUI sInstance;
     private ListView mListView;
     private TestCallList mCallList;
+    private Spinner mBtDeviceList;
+    private BluetoothDeviceAdapter mBluetoothDeviceAdapter;
+    private TextView mCurrentRouteDisplay;
 
     /** ${inheritDoc} */
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        sInstance = this;
 
         setContentView(R.layout.incall_screen);
 
@@ -90,6 +121,13 @@
         View startRttButton = findViewById(R.id.start_rtt_button);
         View acceptRttButton = findViewById(R.id.accept_rtt_button);
         View handoverButton = findViewById(R.id.request_handover_button);
+        View setBtDeviceButton = findViewById(R.id.set_bt_device_button);
+        View earpieceButton = findViewById(R.id.earpiece_button);
+        View speakerButton = findViewById(R.id.speaker_button);
+        mBtDeviceList = findViewById(R.id.available_bt_devices);
+        mBluetoothDeviceAdapter = new BluetoothDeviceAdapter();
+        mBtDeviceList.setAdapter(mBluetoothDeviceAdapter);
+        mCurrentRouteDisplay = findViewById(R.id.current_audio_route);
 
         endCallButton.setOnClickListener(new OnClickListener() {
             @Override
@@ -146,6 +184,22 @@
             }
         });
 
+        earpieceButton.setOnClickListener(view -> {
+            TestInCallServiceImpl.sInstance.setAudioRoute(CallAudioState.ROUTE_WIRED_OR_EARPIECE);
+        });
+
+        speakerButton.setOnClickListener(view -> {
+            TestInCallServiceImpl.sInstance.setAudioRoute(CallAudioState.ROUTE_SPEAKER);
+        });
+
+        setBtDeviceButton.setOnClickListener(view -> {
+            if (mBtDeviceList.getSelectedItem() != null
+                    && TestInCallServiceImpl.sInstance != null) {
+                TestInCallServiceImpl.sInstance.requestBluetoothAudio(
+                        (BluetoothDevice) mBtDeviceList.getSelectedItem());
+            }
+        });
+
         acceptRttButton.setOnClickListener(view -> {
             Call call = mCallList.getCall(0);
             if (!call.isRttActive()) {
@@ -163,9 +217,33 @@
         });
     }
 
+    public void updateCallAudioState(CallAudioState cas) {
+        mBluetoothDeviceAdapter.update(cas.getSupportedBluetoothDevices());
+        String routeText;
+        switch (cas.getRoute()) {
+            case CallAudioState.ROUTE_EARPIECE:
+                routeText = "Earpiece";
+                break;
+            case CallAudioState.ROUTE_SPEAKER:
+                routeText = "Speaker";
+                break;
+            case CallAudioState.ROUTE_WIRED_HEADSET:
+                routeText = "Wired";
+                break;
+            case CallAudioState.ROUTE_BLUETOOTH:
+                BluetoothDevice activeDevice = cas.getActiveBluetoothDevice();
+                routeText = activeDevice == null ? "null bt" : activeDevice.getName();
+                break;
+            default:
+                routeText = "unknown: " + cas.getRoute();
+        }
+        mCurrentRouteDisplay.setText(routeText);
+    }
+
     /** ${inheritDoc} */
     @Override
     protected void onDestroy() {
+        sInstance = null;
         super.onDestroy();
     }