Merge "Phone Calls keeps stopping"
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index d315127..06d8fdc 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -2175,6 +2175,10 @@
     public void handleCarModeChange(int priority, String packageName, boolean isCarMode) {
         Log.i(this, "handleCarModeChange: packageName=%s, priority=%d, isCarMode=%b",
                 packageName, priority, isCarMode);
+        if (packageName == null) {
+            Log.i(this, "handleCarModeChange: Got null packageName, ignoring");
+            return;
+        }
         // Don't ignore the signal if we are disabling car mode; package may be uninstalled.
         if (isCarMode && !isCarModeInCallService(packageName)) {
             Log.i(this, "handleCarModeChange: not a valid InCallService; packageName=%s",
diff --git a/src/com/android/server/telecom/RespondViaSmsSettings.java b/src/com/android/server/telecom/RespondViaSmsSettings.java
old mode 100644
new mode 100755
index 6d7c5c6..661038b
--- a/src/com/android/server/telecom/RespondViaSmsSettings.java
+++ b/src/com/android/server/telecom/RespondViaSmsSettings.java
@@ -99,7 +99,7 @@
         Log.d(this, "  preference = '%s'", preference);
         Log.d(this, "  newValue = '%s'", newValue);
 
-        EditTextPreference pref = (EditTextPreference) preference;
+        EditTextPreference pref = (EditTextPreference)findPreference(preference.getKey());
 
         // Copy the new text over to the title, just like in onCreate().
         // (Watch out: onPreferenceChange() is called *before* the
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
index 228a489..2785739 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothDeviceManager.java
@@ -21,6 +21,7 @@
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothLeAudioCodecStatus;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothStatusCodes;
 import android.content.Context;
@@ -34,6 +35,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.concurrent.Executor;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
@@ -47,6 +49,37 @@
     public static final int DEVICE_TYPE_HEARING_AID = 1;
     public static final int DEVICE_TYPE_LE_AUDIO = 2;
 
+    private BluetoothLeAudio.Callback mLeAudioCallbacks =
+        new BluetoothLeAudio.Callback() {
+            @Override
+            public void onCodecConfigChanged(int groupId, BluetoothLeAudioCodecStatus status) {}
+            @Override
+            public void onGroupStatusChanged(int groupId, int groupStatus) {}
+            @Override
+            public void onGroupNodeAdded(BluetoothDevice device, int groupId) {
+                Log.i(this, device.getAddress() + " group added " + groupId);
+                if (device == null || groupId == BluetoothLeAudio.GROUP_ID_INVALID) {
+                    Log.w(this, "invalid parameter");
+                    return;
+                }
+
+                synchronized (mLock) {
+                    mGroupsByDevice.put(device, groupId);
+                }
+            }
+            @Override
+            public void onGroupNodeRemoved(BluetoothDevice device, int groupId) {
+                if (device == null || groupId == BluetoothLeAudio.GROUP_ID_INVALID) {
+                    Log.w(this, "invalid parameter");
+                    return;
+                }
+
+                synchronized (mLock) {
+                    mGroupsByDevice.remove(device);
+                }
+            }
+        };
+
     private final BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
             new BluetoothProfile.ServiceListener() {
                 @Override
@@ -66,6 +99,11 @@
                                 mBluetoothLeAudioService = (BluetoothLeAudio) proxy;
                                 logString = "Got BluetoothLeAudio: "
                                         + mBluetoothLeAudioService;
+                                if (!mLeAudioCallbackRegistered) {
+                                    mBluetoothLeAudioService.registerCallback(
+                                                mExecutor, mLeAudioCallbacks);
+                                    mLeAudioCallbackRegistered = true;
+                                }
                             } else {
                                 logString = "Connected to non-requested bluetooth service." +
                                         " Not changing bluetooth headset.";
@@ -145,11 +183,13 @@
     private BluetoothRouteManager mBluetoothRouteManager;
     private BluetoothHeadset mBluetoothHeadset;
     private BluetoothHearingAid mBluetoothHearingAid;
+    private boolean mLeAudioCallbackRegistered = false;
     private BluetoothLeAudio mBluetoothLeAudioService;
     private boolean mLeAudioSetAsCommunicationDevice = false;
     private BluetoothDevice mBluetoothHearingAidActiveDeviceCache;
     private BluetoothAdapter mBluetoothAdapter;
     private AudioManager mAudioManager;
+    private Executor mExecutor;
 
     public BluetoothDeviceManager(Context context, BluetoothAdapter bluetoothAdapter) {
         if (bluetoothAdapter != null) {
@@ -161,6 +201,7 @@
             bluetoothAdapter.getProfileProxy(context, mBluetoothProfileServiceListener,
                     BluetoothProfile.LE_AUDIO);
             mAudioManager = context.getSystemService(AudioManager.class);
+            mExecutor = context.getMainExecutor();
         }
     }
 
@@ -265,6 +306,7 @@
 
     public void setLeAudioServiceForTesting(BluetoothLeAudio bluetoothLeAudio) {
         mBluetoothLeAudioService = bluetoothLeAudio;
+        mBluetoothLeAudioService.registerCallback(mExecutor, mLeAudioCallbacks);
     }
 
     public static String getDeviceTypeString(int deviceType) {
@@ -339,29 +381,6 @@
         }
     }
 
-    void onGroupNodeAdded(BluetoothDevice device, int groupId) {
-        Log.i(this, device.getAddress() + " group added " + groupId);
-        if (device == null || groupId == BluetoothLeAudio.GROUP_ID_INVALID) {
-            Log.w(this, "invalid parameter");
-            return;
-        }
-
-        synchronized (mLock) {
-            mGroupsByDevice.put(device, groupId);
-        }
-    }
-
-    void onGroupNodeRemoved(BluetoothDevice device, int groupId) {
-        if (device == null || groupId == BluetoothLeAudio.GROUP_ID_INVALID) {
-            Log.w(this, "invalid parameter");
-            return;
-        }
-
-        synchronized (mLock) {
-            mGroupsByDevice.remove(device);
-        }
-    }
-
     public void disconnectAudio() {
         if (mBluetoothAdapter != null) {
             for (BluetoothDevice device: mBluetoothAdapter.getActiveDevices(
diff --git a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
index 17da806..5c5ded0 100644
--- a/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
+++ b/src/com/android/server/telecom/bluetooth/BluetoothStateReceiver.java
@@ -46,8 +46,6 @@
         INTENT_FILTER.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
         INTENT_FILTER.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
         INTENT_FILTER.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
-        INTENT_FILTER.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED);
-        INTENT_FILTER.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_STATUS_CHANGED);
     }
 
     // If not in a call, BSR won't listen to the Bluetooth stack's HFP on/off messages, since
@@ -74,9 +72,6 @@
                 case BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED:
                     handleActiveDeviceChanged(intent);
                     break;
-                case BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED:
-                    handleGroupNodeStatusChanged(intent);
-                    break;
             }
         } finally {
             Log.endSession();
@@ -199,22 +194,6 @@
         }
     }
 
-    private void handleGroupNodeStatusChanged(Intent intent) {
-        BluetoothDevice device =
-                intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
-        int groupId = intent.getIntExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID,
-                BluetoothLeAudio.GROUP_ID_INVALID);
-        int groupNodeStatus = intent.getIntExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_NODE_STATUS,
-                -1);
-
-        if (groupNodeStatus == BluetoothLeAudio.GROUP_NODE_ADDED) {
-            mBluetoothDeviceManager.onGroupNodeAdded(device, groupId);
-        } else {
-            mBluetoothDeviceManager.onGroupNodeRemoved(device, groupId);
-        }
-    }
-
     public BluetoothDeviceManager getBluetoothDeviceManager() {
         return mBluetoothDeviceManager;
     }
diff --git a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
index 29462f5..f011f0c 100644
--- a/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/BluetoothDeviceManagerTest.java
@@ -45,6 +45,7 @@
 import static org.junit.Assert.assertNull;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -68,6 +69,7 @@
     BluetoothDeviceManager mBluetoothDeviceManager;
     BluetoothProfile.ServiceListener serviceListenerUnderTest;
     BluetoothStateReceiver receiverUnderTest;
+    ArgumentCaptor<BluetoothLeAudio.Callback> leAudioCallbacksTest;
 
     private BluetoothDevice device1;
     private BluetoothDevice device2;
@@ -109,7 +111,11 @@
 
         mBluetoothDeviceManager.setHeadsetServiceForTesting(mBluetoothHeadset);
         mBluetoothDeviceManager.setHearingAidServiceForTesting(mBluetoothHearingAid);
+
+        leAudioCallbacksTest =
+                         ArgumentCaptor.forClass(BluetoothLeAudio.Callback.class);
         mBluetoothDeviceManager.setLeAudioServiceForTesting(mBluetoothLeAudio);
+        verify(mBluetoothLeAudio).registerCallback(any(), leAudioCallbacksTest.capture());
     }
 
     @Override
@@ -162,8 +168,7 @@
         receiverUnderTest.onReceive(mContext,
                 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
                         BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
-        receiverUnderTest.onReceive(mContext,
-                buildGroupNodeStatusChangedIntent(1, device5, BluetoothLeAudio.GROUP_NODE_ADDED));
+        leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1);
         when(mBluetoothLeAudio.getConnectedGroupLeadDevice(1)).thenReturn(device5);
 
         receiverUnderTest.onReceive(mContext,
@@ -172,8 +177,7 @@
         receiverUnderTest.onReceive(mContext,
                 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device6,
                         BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
-        receiverUnderTest.onReceive(mContext,
-                buildGroupNodeStatusChangedIntent(2, device6, BluetoothLeAudio.GROUP_NODE_ADDED));
+        leAudioCallbacksTest.getValue().onGroupNodeAdded(device6, 2);
         when(mBluetoothLeAudio.getConnectedGroupLeadDevice(2)).thenReturn(device6);
         receiverUnderTest.onReceive(mContext,
                 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device3,
@@ -216,13 +220,11 @@
         receiverUnderTest.onReceive(mContext,
                 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
                         BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
-        receiverUnderTest.onReceive(mContext,
-                buildGroupNodeStatusChangedIntent(1, device5, BluetoothLeAudio.GROUP_NODE_ADDED));
+        leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1);
         receiverUnderTest.onReceive(mContext,
                 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device6,
                         BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
-        receiverUnderTest.onReceive(mContext,
-                buildGroupNodeStatusChangedIntent(1, device6, BluetoothLeAudio.GROUP_NODE_ADDED));
+        leAudioCallbacksTest.getValue().onGroupNodeAdded(device6, 1);
         when(mBluetoothLeAudio.getConnectedGroupLeadDevice(1)).thenReturn(device5);
         assertEquals(2, mBluetoothDeviceManager.getNumConnectedDevices());
         assertEquals(2, mBluetoothDeviceManager.getUniqueConnectedDevices().size());
@@ -376,8 +378,7 @@
         receiverUnderTest.onReceive(mContext,
                 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
                         BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
-        receiverUnderTest.onReceive(mContext,
-                buildGroupNodeStatusChangedIntent(1, device5, BluetoothLeAudio.GROUP_NODE_ADDED));
+        leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1);
         when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
                 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
 
@@ -408,13 +409,11 @@
         receiverUnderTest.onReceive(mContext,
                 buildConnectionActionIntent(BluetoothHeadset.STATE_CONNECTED, device5,
                         BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
-        receiverUnderTest.onReceive(mContext,
-                buildGroupNodeStatusChangedIntent(1, device5, BluetoothLeAudio.GROUP_NODE_ADDED));
+        leAudioCallbacksTest.getValue().onGroupNodeAdded(device5, 1);
         receiverUnderTest.onReceive(mContext,
                 buildConnectionActionIntent(BluetoothLeAudio.STATE_CONNECTED, device6,
                         BluetoothDeviceManager.DEVICE_TYPE_LE_AUDIO));
-        receiverUnderTest.onReceive(mContext,
-                buildGroupNodeStatusChangedIntent(1, device6, BluetoothLeAudio.GROUP_NODE_ADDED));
+        leAudioCallbacksTest.getValue().onGroupNodeAdded(device6, 1);
         when(mAdapter.setActiveDevice(nullable(BluetoothDevice.class),
                 eq(BluetoothAdapter.ACTIVE_DEVICE_ALL))).thenReturn(true);
         mBluetoothDeviceManager.connectAudio(device5.getAddress());
@@ -457,22 +456,6 @@
         return i;
     }
 
-    private Intent buildGroupNodeStatusChangedIntent(int groupId, BluetoothDevice device,
-                int nodeStatus) {
-        Intent i = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED);
-        i.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-        i.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, groupId);
-        i.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_NODE_STATUS, nodeStatus);
-        return i;
-    }
-
-    private Intent buildGroupStatusChangedIntent(int groupId, int groupStatus) {
-        Intent i = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_STATUS_CHANGED);
-        i.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, groupId);
-        i.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_STATUS, groupStatus);
-        return i;
-    }
-
     private BluetoothDevice makeBluetoothDevice(String address) {
         Parcel p1 = Parcel.obtain();
         p1.writeString(address);