Merge "Improve A2DP autoreconnect policy"
diff --git a/Android.bp b/Android.bp
index dc523cc..347b22b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -51,7 +51,7 @@
         "libbluetooth_headers",
     ],
     include_dirs: [
-        "system/bt/types",
+        "packages/modules/Bluetooth/system/types",
     ],
     shared_libs: [
         "libbase",
diff --git a/OWNERS b/OWNERS
index 2c1bdc4..cc15db5 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1 +1 @@
-include platform/system/bt:/OWNERS
+include platform/packages/modules/Bluetooth:/OWNERS
diff --git a/jni/com_android_bluetooth_gatt.cpp b/jni/com_android_bluetooth_gatt.cpp
index bf6cba8..642e589 100644
--- a/jni/com_android_bluetooth_gatt.cpp
+++ b/jni/com_android_bluetooth_gatt.cpp
@@ -302,12 +302,22 @@
                                conn_id, status, p_data->handle, jb.get());
 }
 
-void btgattc_write_characteristic_cb(int conn_id, int status, uint16_t handle) {
+void btgattc_write_characteristic_cb(int conn_id, int status, uint16_t handle,
+                                     uint16_t len, const uint8_t* value) {
   CallbackEnv sCallbackEnv(__func__);
   if (!sCallbackEnv.valid()) return;
 
+  ScopedLocalRef<jbyteArray> jb(sCallbackEnv.get(), NULL);
+  if (status == 0) {  // Success
+    jb.reset(sCallbackEnv->NewByteArray(len));
+    sCallbackEnv->SetByteArrayRegion(jb.get(), 0, len, (jbyte*)value);
+  } else {
+    uint8_t value = 0;
+    jb.reset(sCallbackEnv->NewByteArray(1));
+    sCallbackEnv->SetByteArrayRegion(jb.get(), 0, 1, (jbyte*)&value);
+  }
   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteCharacteristic,
-                               conn_id, status, handle);
+                               conn_id, status, handle, jb.get());
 }
 
 void btgattc_execute_write_cb(int conn_id, int status) {
@@ -336,12 +346,22 @@
                                status, p_data.handle, jb.get());
 }
 
-void btgattc_write_descriptor_cb(int conn_id, int status, uint16_t handle) {
+void btgattc_write_descriptor_cb(int conn_id, int status, uint16_t handle,
+                                 uint16_t len, const uint8_t* value) {
   CallbackEnv sCallbackEnv(__func__);
   if (!sCallbackEnv.valid()) return;
 
+  ScopedLocalRef<jbyteArray> jb(sCallbackEnv.get(), NULL);
+  if (status == 0) {  // Success
+    jb.reset(sCallbackEnv->NewByteArray(len));
+    sCallbackEnv->SetByteArrayRegion(jb.get(), 0, len, (jbyte*)value);
+  } else {
+    uint8_t value = 0;
+    jb.reset(sCallbackEnv->NewByteArray(1));
+    sCallbackEnv->SetByteArrayRegion(jb.get(), 0, 1, (jbyte*)&value);
+  }
   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteDescriptor, conn_id,
-                               status, handle);
+                               status, handle, jb.get());
 }
 
 void btgattc_remote_rssi_cb(int client_if, const RawAddress& bda, int rssi,
@@ -983,7 +1003,7 @@
   method_onReadCharacteristic =
       env->GetMethodID(clazz, "onReadCharacteristic", "(III[B)V");
   method_onWriteCharacteristic =
-      env->GetMethodID(clazz, "onWriteCharacteristic", "(III)V");
+      env->GetMethodID(clazz, "onWriteCharacteristic", "(III[B)V");
   method_onExecuteCompleted =
       env->GetMethodID(clazz, "onExecuteCompleted", "(II)V");
   method_onSearchCompleted =
@@ -991,7 +1011,7 @@
   method_onReadDescriptor =
       env->GetMethodID(clazz, "onReadDescriptor", "(III[B)V");
   method_onWriteDescriptor =
-      env->GetMethodID(clazz, "onWriteDescriptor", "(III)V");
+      env->GetMethodID(clazz, "onWriteDescriptor", "(III[B)V");
   method_onNotify =
       env->GetMethodID(clazz, "onNotify", "(ILjava/lang/String;IZ[B)V");
   method_onRegisterForNotifications =
diff --git a/src/com/android/bluetooth/a2dpsink/OWNERS b/src/com/android/bluetooth/a2dpsink/OWNERS
index 06dc3f8..fd47bd7 100644
--- a/src/com/android/bluetooth/a2dpsink/OWNERS
+++ b/src/com/android/bluetooth/a2dpsink/OWNERS
@@ -1 +1 @@
-include platform/system/bt:/OWNERS_automotive
+include platform/packages/modules/Bluetooth:/OWNERS_automotive
diff --git a/src/com/android/bluetooth/audio_util/helpers/PlayStatus.java b/src/com/android/bluetooth/audio_util/helpers/PlayStatus.java
index 922b151..75a760b 100644
--- a/src/com/android/bluetooth/audio_util/helpers/PlayStatus.java
+++ b/src/com/android/bluetooth/audio_util/helpers/PlayStatus.java
@@ -31,7 +31,7 @@
     static final byte REV_SEEK = 4;
     static final byte ERROR = -1;
 
-    public long position = 0xFFFFFFFFFFFFFFFFL;
+    public long position = 0;
     public long duration = 0x00L;
     public byte state = STOPPED;
 
@@ -41,7 +41,7 @@
         if (state == null) return ret;
 
         ret.state = playbackStateToAvrcpState(state.getState());
-        ret.position = state.getPosition();
+        ret.position = (state.getPosition() > 0) ? state.getPosition() : 0;
         ret.duration = duration;
         return ret;
     }
diff --git a/src/com/android/bluetooth/avrcpcontroller/OWNERS b/src/com/android/bluetooth/avrcpcontroller/OWNERS
index 06dc3f8..fd47bd7 100644
--- a/src/com/android/bluetooth/avrcpcontroller/OWNERS
+++ b/src/com/android/bluetooth/avrcpcontroller/OWNERS
@@ -1 +1 @@
-include platform/system/bt:/OWNERS_automotive
+include platform/packages/modules/Bluetooth:/OWNERS_automotive
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index 9c4f6bb..f735641 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -98,6 +98,7 @@
 import com.android.bluetooth.Utils;
 import com.android.bluetooth.a2dp.A2dpService;
 import com.android.bluetooth.a2dpsink.A2dpSinkService;
+import com.android.bluetooth.btservice.MetricsLogger;
 import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
 import com.android.bluetooth.btservice.activityattribution.ActivityAttributionService;
 import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreService;
@@ -305,6 +306,8 @@
 
     private volatile boolean mTestModeEnabled = false;
 
+    private MetricsLogger mMetricsLogger;
+
     /**
      * Register a {@link ProfileService} with AdapterService.
      *
@@ -445,6 +448,7 @@
     @Override
     public void onCreate() {
         super.onCreate();
+        initMetricsLogger();
         debugLog("onCreate()");
         mDeviceConfigListener.start();
         mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper());
@@ -456,8 +460,6 @@
         mJniCallbacks = new JniCallbacks(this, mAdapterProperties);
         mBluetoothKeystoreService = new BluetoothKeystoreService(isCommonCriteriaMode());
         mBluetoothKeystoreService.start();
-        mActivityAttributionService = new ActivityAttributionService();
-        mActivityAttributionService.start();
         int configCompareResult = mBluetoothKeystoreService.getCompareResult();
 
         // Start tracking Binder latency for the bluetooth process.
@@ -512,6 +514,9 @@
 
         mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this);
 
+        mActivityAttributionService = new ActivityAttributionService();
+        mActivityAttributionService.start();
+
         setAdapterService(this);
 
         invalidateBluetoothCaches();
@@ -582,6 +587,27 @@
         }
     };
 
+    private boolean initMetricsLogger() {
+        if (mMetricsLogger != null) {
+            return false;
+        }
+        mMetricsLogger = MetricsLogger.getInstance();
+        return mMetricsLogger.init(this);
+    }
+
+    private boolean closeMetricsLogger() {
+        if (mMetricsLogger == null) {
+            return false;
+        }
+        boolean result = mMetricsLogger.close();
+        mMetricsLogger = null;
+        return result;
+    }
+
+    public void setMetricsLogger(MetricsLogger metricsLogger) {
+        mMetricsLogger = metricsLogger;
+    }
+
     void bringUpBle() {
         debugLog("bleOnProcessStart()");
 
@@ -776,6 +802,8 @@
             return;
         }
 
+        closeMetricsLogger();
+
         clearAdapterService(this);
 
         mCleaningUp = true;
@@ -3817,7 +3845,7 @@
             initFlags.add(String.format("%s=%s", LOGGING_DEBUG_DISABLED_FOR_TAGS_FLAG,
                     debugLoggingDisabledTags));
         }
-        if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH, BTAA_HCI_LOG_FLAG, false)) {
+        if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH, BTAA_HCI_LOG_FLAG, true)) {
             initFlags.add(String.format("%s=%s", BTAA_HCI_LOG_FLAG, "true"));
         }
         return initFlags.toArray(new String[0]);
diff --git a/src/com/android/bluetooth/btservice/Config.java b/src/com/android/bluetooth/btservice/Config.java
index f4f6413..6b6f1cb 100644
--- a/src/com/android/bluetooth/btservice/Config.java
+++ b/src/com/android/bluetooth/btservice/Config.java
@@ -17,6 +17,7 @@
 package com.android.bluetooth.btservice;
 
 import android.bluetooth.BluetoothProfile;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
@@ -221,6 +222,11 @@
         if (systemConfigManager == null) {
             return null;
         }
-        return systemConfigManager.getEnabledComponentOverrides(ctx.getPackageName());
+        List<String> enabledComponent = new ArrayList<>();
+        for (ComponentName comp :
+                systemConfigManager.getEnabledComponentOverrides(ctx.getPackageName())) {
+            enabledComponent.add(comp.getClassName());
+        }
+        return enabledComponent;
     }
 }
diff --git a/src/com/android/bluetooth/btservice/MetricsLogger.java b/src/com/android/bluetooth/btservice/MetricsLogger.java
index b8a3d18..e47b303 100644
--- a/src/com/android/bluetooth/btservice/MetricsLogger.java
+++ b/src/com/android/bluetooth/btservice/MetricsLogger.java
@@ -15,18 +15,113 @@
  */
 package com.android.bluetooth.btservice;
 
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.SystemClock;
+import android.util.Log;
+
 import com.android.bluetooth.BluetoothMetricsProto.BluetoothLog;
 import com.android.bluetooth.BluetoothMetricsProto.ProfileConnectionStats;
 import com.android.bluetooth.BluetoothMetricsProto.ProfileId;
+import com.android.bluetooth.BluetoothStatsLog;
 
 import java.util.HashMap;
 
 /**
- * Class with static methods for logging metrics data
+ * Class of Bluetooth Metrics
  */
 public class MetricsLogger {
+    private static final String TAG = "BluetoothMetricsLogger";
+
+    public static final boolean DEBUG = false;
+
+    /**
+     * Intent indicating Bluetooth counter metrics should send logs to BluetoothStatsLog
+     */
+    public static final String BLUETOOTH_COUNTER_METRICS_ACTION =
+            "com.android.bluetooth.map.BLUETOOTH_COUNTER_METRICS_ACTION";
+    // 6 hours timeout for counter metrics
+    private static final long BLUETOOTH_COUNTER_METRICS_ACTION_DURATION_MILLIS = 6L * 3600L * 1000L;
+
     private static final HashMap<ProfileId, Integer> sProfileConnectionCounts = new HashMap<>();
 
+    HashMap<Integer, Long> mCounters = new HashMap<>();
+    private static MetricsLogger sInstance = null;
+    private Context mContext = null;
+    private AlarmManager mAlarmManager = null;
+    private boolean mInitialized = false;
+    static final private Object mLock = new Object();
+
+    private BroadcastReceiver mDrainReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (DEBUG) {
+                Log.d(TAG, "onReceive: " + action);
+            }
+            if (action.equals(BLUETOOTH_COUNTER_METRICS_ACTION)) {
+                drainBufferedCounters();
+            }
+        }
+    };
+
+    public static MetricsLogger getInstance() {
+        if (sInstance == null) {
+            synchronized (mLock) {
+                if (sInstance == null) {
+                    sInstance = new MetricsLogger();
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    public boolean isInitialized() {
+        return mInitialized;
+    }
+
+    public boolean init(Context context) {
+        if (mInitialized) {
+            return false;
+        }
+        mInitialized = true;
+        mContext = context;
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(BLUETOOTH_COUNTER_METRICS_ACTION);
+        mContext.registerReceiver(mDrainReceiver, filter);
+        scheduleDrains();
+        return true;
+    }
+
+    public boolean count(int key, long count) {
+        if (!mInitialized) {
+            Log.w(TAG, "MetricsLogger isn't initialized");
+            return false;
+        }
+        if (count <= 0) {
+            Log.w(TAG, "count is not larger than 0. count: " + count + " key: " + key);
+            return false;
+        }
+        long total = 0;
+
+        synchronized (mLock) {
+            if (mCounters.containsKey(key)) {
+                total = mCounters.get(key);
+            }
+            if (Long.MAX_VALUE - total < count) {
+                Log.w(TAG, "count overflows. count: " + count + " current total: " + total);
+                mCounters.put(key, Long.MAX_VALUE);
+                return false;
+            }
+            mCounters.put(key, total + count);
+        }
+        return true;
+    }
+
     /**
      * Log profile connection event by incrementing an internal counter for that profile.
      * This log persists over adapter enable/disable and only get cleared when metrics are
@@ -57,4 +152,60 @@
             sProfileConnectionCounts.clear();
         }
     }
+
+    protected void scheduleDrains() {
+        if (DEBUG) {
+            Log.d(TAG, "setCounterMetricsAlarm()");
+        }
+        if (mAlarmManager == null) {
+            mAlarmManager = mContext.getSystemService(AlarmManager.class);
+        }
+        mAlarmManager.setRepeating(
+                AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                SystemClock.elapsedRealtime(),
+                BLUETOOTH_COUNTER_METRICS_ACTION_DURATION_MILLIS,
+                getDrainIntent());
+    }
+
+    protected void writeCounter(int key, long count) {
+        BluetoothStatsLog.write(
+                BluetoothStatsLog.BLUETOOTH_CODE_PATH_COUNTER, key, count);
+    }
+
+    protected void drainBufferedCounters() {
+        Log.i(TAG, "drainBufferedCounters().");
+        synchronized (mLock) {
+            // send mCounters to westworld
+            for (int key : mCounters.keySet()) {
+                writeCounter(key, mCounters.get(key));
+            }
+            mCounters.clear();
+        }
+    }
+
+    public boolean close() {
+        if (!mInitialized) {
+            return false;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "close()");
+        }
+        cancelPendingDrain();
+        drainBufferedCounters();
+        mAlarmManager = null;
+        mContext = null;
+        mInitialized = false;
+        return true;
+    }
+    protected void cancelPendingDrain() {
+        PendingIntent pIntent = getDrainIntent();
+        pIntent.cancel();
+        mAlarmManager.cancel(pIntent);
+    }
+
+    private PendingIntent getDrainIntent() {
+        Intent counterMetricsIntent = new Intent(BLUETOOTH_COUNTER_METRICS_ACTION);
+        return PendingIntent.getBroadcast(
+                mContext, 0, counterMetricsIntent, PendingIntent.FLAG_IMMUTABLE);
+    }
 }
diff --git a/src/com/android/bluetooth/btservice/PhonePolicy.java b/src/com/android/bluetooth/btservice/PhonePolicy.java
index 286c344..94a5355 100644
--- a/src/com/android/bluetooth/btservice/PhonePolicy.java
+++ b/src/com/android/bluetooth/btservice/PhonePolicy.java
@@ -19,12 +19,14 @@
 import android.annotation.RequiresPermission;
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
+import android.bluetooth.BluetoothVolumeControl;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -39,10 +41,13 @@
 import com.android.bluetooth.Utils;
 import com.android.bluetooth.a2dp.A2dpService;
 import com.android.bluetooth.btservice.storage.DatabaseManager;
+import com.android.bluetooth.csip.CsipSetCoordinatorService;
 import com.android.bluetooth.hearingaid.HearingAidService;
 import com.android.bluetooth.hfp.HeadsetService;
 import com.android.bluetooth.hid.HidHostService;
+import com.android.bluetooth.le_audio.LeAudioService;
 import com.android.bluetooth.pan.PanService;
+import com.android.bluetooth.vc.VolumeControlService;
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -118,11 +123,21 @@
                             BluetoothProfile.A2DP, -1, // No-op argument
                             intent).sendToTarget();
                     break;
+                case BluetoothCsipSetCoordinator.ACTION_CSIS_CONNECTION_STATE_CHANGED:
+                    mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED,
+                            BluetoothProfile.CSIP_SET_COORDINATOR, -1, // No-op argument
+                            intent).sendToTarget();
+                    break;
                 case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED:
                     mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED,
                             BluetoothProfile.LE_AUDIO, -1, // No-op argument
                             intent).sendToTarget();
                     break;
+                case BluetoothVolumeControl.ACTION_CONNECTION_STATE_CHANGED:
+                    mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED,
+                            BluetoothProfile.VOLUME_CONTROL, -1, // No-op argument
+                            intent).sendToTarget();
+                    break;
                 case BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED:
                     mHandler.obtainMessage(MESSAGE_PROFILE_ACTIVE_DEVICE_CHANGED,
                             BluetoothProfile.A2DP, -1, // No-op argument
@@ -242,6 +257,8 @@
         filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
+        filter.addAction(BluetoothCsipSetCoordinator.ACTION_CSIS_CONNECTION_STATE_CHANGED);
+        filter.addAction(BluetoothVolumeControl.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
         filter.addAction(BluetoothDevice.ACTION_UUID);
         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
@@ -274,6 +291,11 @@
         HeadsetService headsetService = mFactory.getHeadsetService();
         PanService panService = mFactory.getPanService();
         HearingAidService hearingAidService = mFactory.getHearingAidService();
+        LeAudioService leAudioService = mFactory.getLeAudioService();
+        CsipSetCoordinatorService csipSetCooridnatorService =
+             mFactory.getCsipSetCoordinatorService();
+        VolumeControlService volumeControlService =
+             mFactory.getVolumeControlService();
 
         // Set profile priorities only for the profiles discovered on the remote device.
         // This avoids needless auto-connect attempts to profiles non-existent on the remote device
@@ -302,6 +324,14 @@
                     BluetoothProfile.A2DP, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
         }
 
+        if ((csipSetCooridnatorService != null)
+                && (Utils.arrayContains(uuids, BluetoothUuid.COORDINATED_SET))
+                && (csipSetCooridnatorService.getConnectionPolicy(device)
+                        == BluetoothProfile.CONNECTION_POLICY_UNKNOWN)) {
+            mAdapterService.getDatabase().setProfileConnectionPolicy(device,
+                    BluetoothProfile.CSIP_SET_COORDINATOR, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+        }
+
         if ((panService != null) && (Utils.arrayContains(uuids, BluetoothUuid.PANU) && (
                 panService.getConnectionPolicy(device)
                         == BluetoothProfile.CONNECTION_POLICY_UNKNOWN)
@@ -311,6 +341,14 @@
                     BluetoothProfile.PAN, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
         }
 
+        if ((leAudioService != null) && Utils.arrayContains(uuids,
+                BluetoothUuid.LE_AUDIO) && (leAudioService.getConnectionPolicy(device)
+                == BluetoothProfile.CONNECTION_POLICY_UNKNOWN)) {
+            debugLog("setting le audio profile priority for device " + device);
+            mAdapterService.getDatabase().setProfileConnectionPolicy(device,
+                    BluetoothProfile.LE_AUDIO, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+        }
+
         if ((hearingAidService != null) && Utils.arrayContains(uuids,
                 BluetoothUuid.HEARING_AID) && (hearingAidService.getConnectionPolicy(device)
                 == BluetoothProfile.CONNECTION_POLICY_UNKNOWN)) {
@@ -318,6 +356,14 @@
             mAdapterService.getDatabase().setProfileConnectionPolicy(device,
                     BluetoothProfile.HEARING_AID, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
         }
+
+        if ((volumeControlService != null) && Utils.arrayContains(uuids,
+                BluetoothUuid.VOLUME_CONTROL) && (volumeControlService.getConnectionPolicy(device)
+                == BluetoothProfile.CONNECTION_POLICY_UNKNOWN)) {
+            debugLog("setting volume control profile priority for device " + device);
+            mAdapterService.getDatabase().setProfileConnectionPolicy(device,
+                    BluetoothProfile.VOLUME_CONTROL, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+        }
     }
 
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
@@ -326,7 +372,9 @@
         debugLog("processProfileStateChanged, device=" + device + ", profile=" + profileId + ", "
                 + prevState + " -> " + nextState);
         if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET)
-                || (profileId == BluetoothProfile.LE_AUDIO))) {
+                || (profileId == BluetoothProfile.LE_AUDIO)
+                || (profileId == BluetoothProfile.CSIP_SET_COORDINATOR)
+                || (profileId == BluetoothProfile.VOLUME_CONTROL))) {
             if (nextState == BluetoothProfile.STATE_CONNECTED) {
                 switch (profileId) {
                     case BluetoothProfile.A2DP:
@@ -375,6 +423,9 @@
         HeadsetService hsService = mFactory.getHeadsetService();
         A2dpService a2dpService = mFactory.getA2dpService();
         PanService panService = mFactory.getPanService();
+        LeAudioService leAudioService = mFactory.getLeAudioService();
+        CsipSetCoordinatorService csipSetCooridnatorService =
+        mFactory.getCsipSetCoordinatorService();
 
         if (hsService != null) {
             List<BluetoothDevice> hsConnDevList = hsService.getConnectedDevices();
@@ -386,11 +437,21 @@
             allProfilesEmpty &= a2dpConnDevList.isEmpty();
             atLeastOneProfileConnectedForDevice |= a2dpConnDevList.contains(device);
         }
+        if (csipSetCooridnatorService != null) {
+            List<BluetoothDevice> csipConnDevList = csipSetCooridnatorService.getConnectedDevices();
+            allProfilesEmpty &= csipConnDevList.isEmpty();
+            atLeastOneProfileConnectedForDevice |= csipConnDevList.contains(device);
+        }
         if (panService != null) {
             List<BluetoothDevice> panConnDevList = panService.getConnectedDevices();
             allProfilesEmpty &= panConnDevList.isEmpty();
             atLeastOneProfileConnectedForDevice |= panConnDevList.contains(device);
         }
+        if (leAudioService != null) {
+            List<BluetoothDevice> leAudioConnDevList = leAudioService.getConnectedDevices();
+            allProfilesEmpty &= leAudioConnDevList.isEmpty();
+            atLeastOneProfileConnectedForDevice |= leAudioConnDevList.contains(device);
+        }
 
         if (!atLeastOneProfileConnectedForDevice) {
             // Consider this device as fully disconnected, don't bother connecting others
@@ -507,6 +568,11 @@
         HeadsetService hsService = mFactory.getHeadsetService();
         A2dpService a2dpService = mFactory.getA2dpService();
         PanService panService = mFactory.getPanService();
+        LeAudioService leAudioService = mFactory.getLeAudioService();
+        CsipSetCoordinatorService csipSetCooridnatorService =
+            mFactory.getCsipSetCoordinatorService();
+        VolumeControlService volumeControlService =
+            mFactory.getVolumeControlService();
 
         if (hsService != null) {
             if (!mHeadsetRetrySet.contains(device) && (hsService.getConnectionPolicy(device)
@@ -540,6 +606,36 @@
                 panService.connect(device);
             }
         }
+        if (leAudioService != null) {
+            List<BluetoothDevice> leAudioConnDevList = leAudioService.getConnectedDevices();
+            if (!leAudioConnDevList.contains(device) && (leAudioService.getConnectionPolicy(device)
+                    == BluetoothProfile.CONNECTION_POLICY_ALLOWED)
+                    && (leAudioService.getConnectionState(device)
+                    == BluetoothProfile.STATE_DISCONNECTED)) {
+                debugLog("Retrying connection to LEAudio with device " + device);
+                leAudioService.connect(device);
+            }
+        }
+        if (csipSetCooridnatorService != null) {
+            List<BluetoothDevice> csipConnDevList = csipSetCooridnatorService.getConnectedDevices();
+            if (!csipConnDevList.contains(device) && (csipSetCooridnatorService.getConnectionPolicy(device)
+                    == BluetoothProfile.CONNECTION_POLICY_ALLOWED)
+                    && (csipSetCooridnatorService.getConnectionState(device)
+                    == BluetoothProfile.STATE_DISCONNECTED)) {
+                debugLog("Retrying connection to CSIP with device " + device);
+                csipSetCooridnatorService.connect(device);
+            }
+        }
+        if (volumeControlService != null) {
+            List<BluetoothDevice> vcConnDevList = volumeControlService.getConnectedDevices();
+            if (!vcConnDevList.contains(device) && (volumeControlService.getConnectionPolicy(device)
+                    == BluetoothProfile.CONNECTION_POLICY_ALLOWED)
+                    && (volumeControlService.getConnectionState(device)
+                    == BluetoothProfile.STATE_DISCONNECTED)) {
+                debugLog("Retrying connection to CSIP with device " + device);
+                volumeControlService.connect(device);
+            }
+        }
     }
 
     private static void debugLog(String msg) {
diff --git a/src/com/android/bluetooth/btservice/RemoteDevices.java b/src/com/android/bluetooth/btservice/RemoteDevices.java
index a28105a..2f0a8d4 100644
--- a/src/com/android/bluetooth/btservice/RemoteDevices.java
+++ b/src/com/android/bluetooth/btservice/RemoteDevices.java
@@ -600,6 +600,9 @@
                             if (sAdapterService.getState() == BluetoothAdapter.STATE_ON) {
                                 sAdapterService.deviceUuidUpdated(bdDevice);
                                 sendUuidIntent(bdDevice, device);
+                            } else if (sAdapterService.getState()
+                                    == BluetoothAdapter.STATE_BLE_ON) {
+                                sAdapterService.deviceUuidUpdated(bdDevice);
                             }
                             break;
                         case AbstractionLayer.BT_PROPERTY_TYPE_OF_DEVICE:
diff --git a/src/com/android/bluetooth/btservice/ServiceFactory.java b/src/com/android/bluetooth/btservice/ServiceFactory.java
index fd1b6d8..6842dc0 100644
--- a/src/com/android/bluetooth/btservice/ServiceFactory.java
+++ b/src/com/android/bluetooth/btservice/ServiceFactory.java
@@ -18,6 +18,7 @@
 
 import com.android.bluetooth.a2dp.A2dpService;
 import com.android.bluetooth.avrcp.AvrcpTargetService;
+import com.android.bluetooth.csip.CsipSetCoordinatorService;
 import com.android.bluetooth.hearingaid.HearingAidService;
 import com.android.bluetooth.hfp.HeadsetService;
 import com.android.bluetooth.hid.HidDeviceService;
@@ -25,6 +26,7 @@
 import com.android.bluetooth.le_audio.LeAudioService;
 import com.android.bluetooth.mcp.McpService;
 import com.android.bluetooth.pan.PanService;
+import com.android.bluetooth.vc.VolumeControlService;
 
 // Factory class to create instances of static services. Useful in mocking the service objects.
 public class ServiceFactory {
@@ -32,6 +34,10 @@
         return A2dpService.getA2dpService();
     }
 
+    public CsipSetCoordinatorService getCsipSetCoordinatorService() {
+        return CsipSetCoordinatorService.getCsipSetCoordinatorService();
+    }
+
     public HeadsetService getHeadsetService() {
         return HeadsetService.getHeadsetService();
     }
@@ -63,4 +69,8 @@
     public McpService getMcpService() {
         return McpService.getMcpService();
     }
+
+    public VolumeControlService getVolumeControlService() {
+        return VolumeControlService.getVolumeControlService();
+    }
 }
diff --git a/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java b/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
index 61f4cdf..7fe1345 100644
--- a/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
+++ b/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
@@ -284,7 +284,7 @@
         return true;
     }
 
-    List<BluetoothDevice> getConnectedDevices() {
+    public List<BluetoothDevice> getConnectedDevices() {
         enforceCallingOrSelfPermission(BLUETOOTH_CONNECT, "Need BLUETOOTH_CONNECT permission");
         synchronized (mStateMachines) {
             List<BluetoothDevice> devices = new ArrayList<>();
diff --git a/src/com/android/bluetooth/gatt/CallbackInfo.java b/src/com/android/bluetooth/gatt/CallbackInfo.java
index 330422d..f6035b3 100644
--- a/src/com/android/bluetooth/gatt/CallbackInfo.java
+++ b/src/com/android/bluetooth/gatt/CallbackInfo.java
@@ -26,16 +26,38 @@
     public String address;
     public int status;
     public int handle;
+    public byte[] value;
 
-    CallbackInfo(String address, int status, int handle) {
+    static class Builder {
+        private String mAddress;
+        private int mStatus;
+        private int mHandle;
+        private byte[] mValue;
+
+        Builder(String address, int status) {
+            mAddress = address;
+            mStatus = status;
+        }
+
+        Builder setHandle(int handle) {
+            mHandle = handle;
+            return this;
+        }
+
+        Builder setValue(byte[] value) {
+            mValue = value;
+            return this;
+        }
+
+        CallbackInfo build() {
+            return new CallbackInfo(mAddress, mStatus, mHandle, mValue);
+        }
+    }
+
+    private CallbackInfo(String address, int status, int handle, byte[] value) {
         this.address = address;
         this.status = status;
         this.handle = handle;
     }
-
-    CallbackInfo(String address, int status) {
-        this.address = address;
-        this.status = status;
-    }
 }
 
diff --git a/src/com/android/bluetooth/gatt/GattService.java b/src/com/android/bluetooth/gatt/GattService.java
index 17f7fca..e7b6aac 100644
--- a/src/com/android/bluetooth/gatt/GattService.java
+++ b/src/com/android/bluetooth/gatt/GattService.java
@@ -30,6 +30,7 @@
 import android.bluetooth.BluetoothGattDescriptor;
 import android.bluetooth.BluetoothGattService;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothStatusCodes;
 import android.bluetooth.IBluetoothGatt;
 import android.bluetooth.IBluetoothGattCallback;
 import android.bluetooth.IBluetoothGattServerCallback;
@@ -734,7 +735,7 @@
                 int authReq, byte[] value, AttributionSource attributionSource) {
             GattService service = getService();
             if (service == null) {
-                return BluetoothGatt.GATT_WRITE_REQUEST_FAIL;
+                return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
             }
             return service.writeCharacteristic(clientIf, address, handle, writeType, authReq, value,
                     attributionSource);
@@ -751,13 +752,14 @@
         }
 
         @Override
-        public void writeDescriptor(int clientIf, String address, int handle, int authReq,
+        public int writeDescriptor(int clientIf, String address, int handle, int authReq,
                 byte[] value, AttributionSource attributionSource) {
             GattService service = getService();
             if (service == null) {
-                return;
+                return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
             }
-            service.writeDescriptor(clientIf, address, handle, authReq, value, attributionSource);
+            return service.writeDescriptor(clientIf, address, handle, authReq, value,
+                    attributionSource);
         }
 
         @Override
@@ -1694,7 +1696,8 @@
         }
     }
 
-    void onWriteCharacteristic(int connId, int status, int handle) throws RemoteException {
+    void onWriteCharacteristic(int connId, int status, int handle, byte[] data)
+            throws RemoteException {
         String address = mClientMap.addressByConnId(connId);
         synchronized (mPermits) {
             Log.d(TAG, "onWriteCharacteristic() - increasing permit for address="
@@ -1703,7 +1706,8 @@
         }
 
         if (VDBG) {
-            Log.d(TAG, "onWriteCharacteristic() - address=" + address + ", status=" + status);
+            Log.d(TAG, "onWriteCharacteristic() - address=" + address + ", status=" + status
+                    + ", length=" + data.length);
         }
 
         ClientMap.App app = mClientMap.getByConnId(connId);
@@ -1712,12 +1716,15 @@
         }
 
         if (!app.isCongested) {
-            app.callback.onCharacteristicWrite(address, status, handle);
+            app.callback.onCharacteristicWrite(address, status, handle, data);
         } else {
             if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
                 status = BluetoothGatt.GATT_SUCCESS;
             }
-            CallbackInfo callbackInfo = new CallbackInfo(address, status, handle);
+            CallbackInfo callbackInfo = new CallbackInfo.Builder(address, status)
+                    .setHandle(handle)
+                    .setValue(data)
+                    .build();
             app.queueCallback(callbackInfo);
         }
     }
@@ -1749,16 +1756,18 @@
         }
     }
 
-    void onWriteDescriptor(int connId, int status, int handle) throws RemoteException {
+    void onWriteDescriptor(int connId, int status, int handle, byte[] data)
+            throws RemoteException {
         String address = mClientMap.addressByConnId(connId);
 
         if (VDBG) {
-            Log.d(TAG, "onWriteDescriptor() - address=" + address + ", status=" + status);
+            Log.d(TAG, "onWriteDescriptor() - address=" + address + ", status=" + status
+                    + ", length=" + data.length);
         }
 
         ClientMap.App app = mClientMap.getByConnId(connId);
         if (app != null) {
-            app.callback.onDescriptorWrite(address, status, handle);
+            app.callback.onDescriptorWrite(address, status, handle, data);
         }
     }
 
@@ -2181,7 +2190,7 @@
                     return;
                 }
                 app.callback.onCharacteristicWrite(callbackInfo.address, callbackInfo.status,
-                        callbackInfo.handle);
+                        callbackInfo.handle, callbackInfo.value);
             }
         }
     }
@@ -2915,7 +2924,7 @@
             byte[] value, AttributionSource attributionSource) {
         if (!Utils.checkConnectPermissionForDataDelivery(
                 this, attributionSource, "GattService writeCharacteristic")) {
-            return BluetoothGatt.GATT_WRITE_REQUEST_FAIL;
+            return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
         }
 
         if (VDBG) {
@@ -2929,12 +2938,12 @@
         Integer connId = mClientMap.connIdByAddress(clientIf, address);
         if (connId == null) {
             Log.e(TAG, "writeCharacteristic() - No connection for " + address + "...");
-            return BluetoothGatt.GATT_WRITE_REQUEST_FAIL;
+            return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
         }
 
         if (!permissionCheck(connId, handle)) {
             Log.w(TAG, "writeCharacteristic() - permission check failed!");
-            return BluetoothGatt.GATT_WRITE_REQUEST_FAIL;
+            return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION;
         }
 
         Log.d(TAG, "writeCharacteristic() - trying to acquire permit.");
@@ -2943,19 +2952,19 @@
             AtomicBoolean atomicBoolean = mPermits.get(address);
             if (atomicBoolean == null) {
                 Log.d(TAG, "writeCharacteristic() -  atomicBoolean uninitialized!");
-                return BluetoothGatt.GATT_WRITE_REQUEST_FAIL;
+                return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
             }
 
             boolean success = atomicBoolean.get();
             if (!success) {
-                 Log.d(TAG, "writeCharacteristic() - no permit available.");
-                 return BluetoothGatt.GATT_WRITE_REQUEST_BUSY;
+                Log.d(TAG, "writeCharacteristic() - no permit available.");
+                return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
             }
             atomicBoolean.set(false);
         }
 
         gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value);
-        return BluetoothGatt.GATT_WRITE_REQUEST_SUCCESS;
+        return BluetoothStatusCodes.SUCCESS;
     }
 
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@@ -2985,11 +2994,11 @@
     }
 
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
-    void writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value,
+    int writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value,
             AttributionSource attributionSource) {
         if (!Utils.checkConnectPermissionForDataDelivery(
                 this, attributionSource, "GattService writeDescriptor")) {
-            return;
+            return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
         }
         if (VDBG) {
             Log.d(TAG, "writeDescriptor() - address=" + address);
@@ -2998,15 +3007,16 @@
         Integer connId = mClientMap.connIdByAddress(clientIf, address);
         if (connId == null) {
             Log.e(TAG, "writeDescriptor() - No connection for " + address + "...");
-            return;
+            return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
         }
 
         if (!permissionCheck(connId, handle)) {
             Log.w(TAG, "writeDescriptor() - permission check failed!");
-            return;
+            return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION;
         }
 
         gattClientWriteDescriptorNative(connId, handle, authReq, value);
+        return BluetoothStatusCodes.SUCCESS;
     }
 
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@@ -3410,7 +3420,7 @@
             if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
                 status = BluetoothGatt.GATT_SUCCESS;
             }
-            app.queueCallback(new CallbackInfo(address, status));
+            app.queueCallback(new CallbackInfo.Builder(address, status).build());
         }
     }
 
diff --git a/src/com/android/bluetooth/hfp/HeadsetPhoneState.java b/src/com/android/bluetooth/hfp/HeadsetPhoneState.java
index 50094cf1..4bf7530 100644
--- a/src/com/android/bluetooth/hfp/HeadsetPhoneState.java
+++ b/src/com/android/bluetooth/hfp/HeadsetPhoneState.java
@@ -70,6 +70,8 @@
     private final HashMap<BluetoothDevice, Integer> mDeviceEventMap = new HashMap<>();
     private PhoneStateListener mPhoneStateListener;
     private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener;
+    // TODO(b/205585585): Re-enable SignalStrengthUpdateRequest to support "always report signal
+    // strength" when the crash is fixed.
 
     HeadsetPhoneState(HeadsetService headsetService) {
         Objects.requireNonNull(headsetService, "headsetService is null");
diff --git a/src/com/android/bluetooth/hfp/HeadsetService.java b/src/com/android/bluetooth/hfp/HeadsetService.java
index 9548eac..7c3784e 100644
--- a/src/com/android/bluetooth/hfp/HeadsetService.java
+++ b/src/com/android/bluetooth/hfp/HeadsetService.java
@@ -1645,7 +1645,7 @@
             // Suspend A2DP when call about is about to become active
             if (mActiveDevice != null && callState != HeadsetHalConstants.CALL_STATE_DISCONNECTED
                     && !mSystemInterface.isCallIdle() && isCallIdleBefore) {
-                mSystemInterface.getAudioManager().setParameters("A2dpSuspended=true");
+                mSystemInterface.getAudioManager().setA2dpSuspended(true);
             }
         });
         doForEachConnectedStateMachine(
@@ -1655,7 +1655,7 @@
             if (callState == HeadsetHalConstants.CALL_STATE_IDLE
                     && mSystemInterface.isCallIdle() && !isAudioOn()) {
                 // Resume A2DP when call ended and SCO is not connected
-                mSystemInterface.getAudioManager().setParameters("A2dpSuspended=false");
+                mSystemInterface.getAudioManager().setA2dpSuspended(false);
             }
         });
 
@@ -1813,7 +1813,7 @@
                 }
                 // Unsuspend A2DP when SCO connection is gone and call state is idle
                 if (mSystemInterface.isCallIdle()) {
-                    mSystemInterface.getAudioManager().setParameters("A2dpSuspended=false");
+                    mSystemInterface.getAudioManager().setA2dpSuspended(false);
                 }
             }
         }
diff --git a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
index cddb9cc..bbc7878 100644
--- a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
+++ b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
@@ -80,12 +80,6 @@
     private static final String TAG = "HeadsetStateMachine";
     private static final boolean DBG = false;
 
-    private static final String HEADSET_NAME = "bt_headset_name";
-    private static final String HEADSET_NREC = "bt_headset_nrec";
-    private static final String HEADSET_WBS = "bt_wbs";
-    private static final String HEADSET_AUDIO_FEATURE_ON = "on";
-    private static final String HEADSET_AUDIO_FEATURE_OFF = "off";
-
     static final int CONNECT = 1;
     static final int DISCONNECT = 2;
     static final int CONNECT_AUDIO = 3;
@@ -147,8 +141,9 @@
     private HeadsetAgIndicatorEnableState mAgIndicatorEnableState;
     // The timestamp when the device entered connecting/connected state
     private long mConnectingTimestampMs = Long.MIN_VALUE;
-    // Audio Parameters like NREC
-    private final HashMap<String, String> mAudioParams = new HashMap<>();
+    // Audio Parameters
+    private boolean mHasNrecEnabled = false;
+    private boolean mHasWbsEnabled = false;
     // AT Phone book keeps a group of states used by AT+CPBR commands
     private final AtPhonebook mPhonebook;
     // HSP specific
@@ -227,7 +222,8 @@
         if (mPhonebook != null) {
             mPhonebook.cleanup();
         }
-        mAudioParams.clear();
+        mHasWbsEnabled = false;
+        mHasNrecEnabled = false;
     }
 
     public void dump(StringBuilder sb) {
@@ -322,8 +318,7 @@
             BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_SCO_CONNECTION_STATE_CHANGED,
                     mAdapterService.obfuscateAddress(device),
                     getConnectionStateFromAudioState(toState),
-                    TextUtils.equals(mAudioParams.get(HEADSET_WBS), HEADSET_AUDIO_FEATURE_ON)
-                            ? BluetoothHfpProtoEnums.SCO_CODEC_MSBC
+                    mHasWbsEnabled ? BluetoothHfpProtoEnums.SCO_CODEC_MSBC
                             : BluetoothHfpProtoEnums.SCO_CODEC_CVSD,
                     mAdapterService.getMetricId(device));
             mHeadsetService.onAudioStateChangedFromStateMachine(device, fromState, toState);
@@ -456,7 +451,8 @@
             mPhonebook.resetAtState();
             updateAgIndicatorEnableState(null);
             mNeedDialingOutReply = false;
-            mAudioParams.clear();
+            mHasWbsEnabled = false;
+            mHasNrecEnabled = false;
             broadcastStateTransitions();
             // Remove the state machine for unbonded devices
             if (mPrevState != null
@@ -1083,9 +1079,9 @@
                 break;
                 case CONNECT_AUDIO:
                     stateLogD("CONNECT_AUDIO, device=" + mDevice);
-                    mSystemInterface.getAudioManager().setParameters("A2dpSuspended=true");
+                    mSystemInterface.getAudioManager().setA2dpSuspended(true);
                     if (!mNativeInterface.connectAudio(mDevice)) {
-                        mSystemInterface.getAudioManager().setParameters("A2dpSuspended=false");
+                        mSystemInterface.getAudioManager().setA2dpSuspended(false);
                         stateLogE("Failed to connect SCO audio for " + mDevice);
                         // No state change involved, fire broadcast immediately
                         broadcastAudioState(mDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
@@ -1530,15 +1526,12 @@
     }
 
     private void setAudioParameters() {
-        String keyValuePairs = String.join(";", new String[]{
-                HEADSET_NAME + "=" + getCurrentDeviceName(),
-                HEADSET_NREC + "=" + mAudioParams.getOrDefault(HEADSET_NREC,
-                        HEADSET_AUDIO_FEATURE_OFF),
-                HEADSET_WBS + "=" + mAudioParams.getOrDefault(HEADSET_WBS,
-                        HEADSET_AUDIO_FEATURE_OFF)
-        });
-        Log.i(TAG, "setAudioParameters for " + mDevice + ": " + keyValuePairs);
-        mSystemInterface.getAudioManager().setParameters(keyValuePairs);
+        AudioManager am = mSystemInterface.getAudioManager();
+        Log.i(TAG, "setAudioParameters for " + mDevice + ":"
+                + " Name=" + getCurrentDeviceName()
+                + " hasNrecEnabled=" + mHasNrecEnabled
+                + " hasWbsEnabled=" + mHasWbsEnabled);
+        am.setBluetoothHeadsetProperties(getCurrentDeviceName(), mHasNrecEnabled, mHasWbsEnabled);
     }
 
     private String parseUnknownAt(String atString) {
@@ -1667,32 +1660,28 @@
     }
 
     private void processNoiseReductionEvent(boolean enable) {
-        String prevNrec = mAudioParams.getOrDefault(HEADSET_NREC, HEADSET_AUDIO_FEATURE_OFF);
-        String newNrec = enable ? HEADSET_AUDIO_FEATURE_ON : HEADSET_AUDIO_FEATURE_OFF;
-        mAudioParams.put(HEADSET_NREC, newNrec);
-        log("processNoiseReductionEvent: " + HEADSET_NREC + " change " + prevNrec + " -> "
-                + newNrec);
+        log("processNoiseReductionEvent: " + mHasNrecEnabled + " -> " + enable);
+        mHasNrecEnabled = enable;
         if (getAudioState() == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
             setAudioParameters();
         }
     }
 
     private void processWBSEvent(int wbsConfig) {
-        String prevWbs = mAudioParams.getOrDefault(HEADSET_WBS, HEADSET_AUDIO_FEATURE_OFF);
+        boolean prevWbs = mHasWbsEnabled;
         switch (wbsConfig) {
             case HeadsetHalConstants.BTHF_WBS_YES:
-                mAudioParams.put(HEADSET_WBS, HEADSET_AUDIO_FEATURE_ON);
+                mHasWbsEnabled = true;
                 break;
             case HeadsetHalConstants.BTHF_WBS_NO:
             case HeadsetHalConstants.BTHF_WBS_NONE:
-                mAudioParams.put(HEADSET_WBS, HEADSET_AUDIO_FEATURE_OFF);
+                mHasWbsEnabled = false;
                 break;
             default:
                 Log.e(TAG, "processWBSEvent: unknown wbsConfig " + wbsConfig);
                 return;
         }
-        log("processWBSEvent: " + HEADSET_NREC + " change " + prevWbs + " -> " + mAudioParams.get(
-                HEADSET_WBS));
+        log("processWBSEvent: " + prevWbs + " -> " + mHasWbsEnabled);
     }
 
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -2075,7 +2064,7 @@
             events |= PhoneStateListener.LISTEN_SERVICE_STATE;
         }
         if (mAgIndicatorEnableState != null && mAgIndicatorEnableState.signal) {
-            events |= PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH;
+            events |= PhoneStateListener.LISTEN_SIGNAL_STRENGTHS;
         }
         mSystemInterface.getHeadsetPhoneState().listenForPhoneState(mDevice, events);
     }
diff --git a/src/com/android/bluetooth/hfpclient/HeadsetClientService.java b/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
index 23e8e58..8c45847 100644
--- a/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
+++ b/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
@@ -111,7 +111,7 @@
                 Log.e(TAG, "AudioManager service doesn't exist?");
             } else {
                 // start AudioManager in a known state
-                mAudioManager.setParameters("hfp_enable=false");
+                mAudioManager.setHfpEnabled(false);
             }
 
             mSmFactory = new HeadsetClientStateMachineFactory();
@@ -200,7 +200,7 @@
                                 "Setting volume to audio manager: " + streamValue + " hands free: "
                                         + hfVol);
                     }
-                    mAudioManager.setParameters("hfp_volume=" + hfVol);
+                    mAudioManager.setHfpVolume(hfVol);
                     synchronized (mStateMachineMap) {
                         for (HeadsetClientStateMachine sm : mStateMachineMap.values()) {
                             if (sm != null) {
diff --git a/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java b/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
index 9f724a6..13eeee9 100644
--- a/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
+++ b/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
@@ -815,9 +815,9 @@
         }
         logD("hfp_enable=" + enable);
         if (enable && !sAudioIsRouted) {
-            mAudioManager.setParameters("hfp_enable=true");
+            mAudioManager.setHfpEnabled(true);
         } else if (!enable) {
-            mAudioManager.setParameters("hfp_enable=false");
+            mAudioManager.setHfpEnabled(false);
         }
         sAudioIsRouted = enable;
     }
@@ -1592,7 +1592,7 @@
                     // routing is handled by the bluetooth stack itself. The only reason to do so is
                     // because Bluetooth SCO connection from the HF role is not entirely supported
                     // for routing and volume purposes.
-                    // NOTE: All calls here are routed via the setParameters which changes the
+                    // NOTE: All calls here are routed via AudioManager methods which changes the
                     // routing at the Audio HAL level.
 
                     if (mService.isScoRouted()) {
@@ -1614,15 +1614,15 @@
                     logD("hfp_enable=true mAudioWbs is " + mAudioWbs);
                     if (mAudioWbs) {
                         logD("Setting sampling rate as 16000");
-                        mAudioManager.setParameters("hfp_set_sampling_rate=16000");
+                        mAudioManager.setHfpSamplingRate(16000);
                     } else {
                         logD("Setting sampling rate as 8000");
-                        mAudioManager.setParameters("hfp_set_sampling_rate=8000");
+                        mAudioManager.setHfpSamplingRate(8000);
                     }
                     logD("hf_volume " + hfVol);
                     routeHfpAudio(true);
                     mAudioFocusRequest = requestAudioFocus();
-                    mAudioManager.setParameters("hfp_volume=" + hfVol);
+                    mAudioManager.setHfpVolume(hfVol);
                     transitionTo(mAudioOn);
                     break;
 
diff --git a/src/com/android/bluetooth/hfpclient/OWNERS b/src/com/android/bluetooth/hfpclient/OWNERS
index 06dc3f8..fd47bd7 100644
--- a/src/com/android/bluetooth/hfpclient/OWNERS
+++ b/src/com/android/bluetooth/hfpclient/OWNERS
@@ -1 +1 @@
-include platform/system/bt:/OWNERS_automotive
+include platform/packages/modules/Bluetooth:/OWNERS_automotive
diff --git a/src/com/android/bluetooth/le_audio/LeAudioService.java b/src/com/android/bluetooth/le_audio/LeAudioService.java
index b03b161..da5828e 100644
--- a/src/com/android/bluetooth/le_audio/LeAudioService.java
+++ b/src/com/android/bluetooth/le_audio/LeAudioService.java
@@ -421,12 +421,6 @@
             return false;
         }
 
-        int groupId = getGroupId(device);
-
-        if (DBG) {
-            Log.d(TAG, "connect(): " + device + " group id: " + groupId);
-        }
-
         synchronized (mStateMachines) {
             LeAudioStateMachine sm = getOrCreateStateMachine(device);
             if (sm == null) {
@@ -437,25 +431,7 @@
         }
 
         // Connect other devices from this group
-        if (groupId != LE_AUDIO_GROUP_ID_INVALID) {
-            for (BluetoothDevice storedDevice : mDeviceGroupIdMap.keySet()) {
-                if (device.equals(storedDevice)) {
-                    continue;
-                }
-                if (getGroupId(storedDevice) != groupId) {
-                    continue;
-                }
-                synchronized (mStateMachines) {
-                     LeAudioStateMachine sm = getOrCreateStateMachine(storedDevice);
-                     if (sm == null) {
-                         Log.e(TAG, "Ignored connect request for " + storedDevice
-                                 + " : no state machine");
-                         continue;
-                     }
-                     sm.sendMessage(LeAudioStateMachine.CONNECT);
-                 }
-             }
-         }
+        connectSet(device);
 
         return true;
     }
@@ -507,7 +483,7 @@
         return true;
     }
 
-    List<BluetoothDevice> getConnectedDevices() {
+    public List<BluetoothDevice> getConnectedDevices() {
         synchronized (mStateMachines) {
             List<BluetoothDevice> devices = new ArrayList<>();
             for (LeAudioStateMachine sm : mStateMachines.values()) {
@@ -705,7 +681,7 @@
          * - If device stops supporting input
          */
         boolean inActiveDeviceReplace = (device != mPreviousAudioInDevice);
-        if (mPreviousAudioInDevice != null) {
+        if (inActiveDeviceReplace && (mPreviousAudioInDevice != null)) {
             mAudioManager.setBluetoothLeAudioInDeviceConnectionState(
                     mPreviousAudioInDevice, BluetoothProfile.STATE_DISCONNECTED);
         }
@@ -749,7 +725,7 @@
         if (device != null && mPreviousAudioOutDevice != null) {
             int previousGroupId = getGroupId(mPreviousAudioOutDevice);
             if (previousGroupId == groupId) {
-                /* This is thes same group as aleady notified to the system.
+                /* This is the same group as already notified to the system.
                 * Therefore do not change the device we have connected to the group,
                 * unless, previous one is disconnected now
                 */
@@ -763,7 +739,7 @@
          * - If device stops supporting output
          */
         boolean outActiveDeviceReplace = (device != mPreviousAudioOutDevice);
-        if (mPreviousAudioOutDevice != null) {
+        if (outActiveDeviceReplace && (mPreviousAudioOutDevice != null)) {
             boolean suppressNoisyIntent =
                     (getConnectionState(mPreviousAudioOutDevice) ==
                     BluetoothProfile.STATE_CONNECTED);
@@ -889,6 +865,42 @@
         return activeDevices;
     }
 
+    void connectSet(BluetoothDevice device) {
+        int groupId = getGroupId(device);
+        if (groupId == LE_AUDIO_GROUP_ID_INVALID) {
+            return;
+        }
+
+        if (DBG) {
+            Log.d(TAG, "connect() others from group id: " + groupId);
+        }
+
+        for (BluetoothDevice storedDevice : mDeviceGroupIdMap.keySet()) {
+            if (device.equals(storedDevice)) {
+                continue;
+            }
+
+            if (getGroupId(storedDevice) != groupId) {
+                continue;
+            }
+
+            if (DBG) {
+                Log.d(TAG, "connect(): " + device);
+            }
+
+            synchronized (mStateMachines) {
+                 LeAudioStateMachine sm = getOrCreateStateMachine(storedDevice);
+                 if (sm == null) {
+                     Log.e(TAG, "Ignored connect request for " + storedDevice
+                             + " : no state machine");
+                     continue;
+                 }
+                 sm.sendMessage(LeAudioStateMachine.CONNECT);
+             }
+         }
+
+    }
+
     // Suppressed since this is part of a local process
     @SuppressLint("AndroidFrameworkRequiresPermission")
     void messageFromNative(LeAudioStackEvent stackEvent) {
@@ -905,6 +917,8 @@
                         case LeAudioStackEvent.CONNECTION_STATE_CONNECTED:
                         case LeAudioStackEvent.CONNECTION_STATE_CONNECTING:
                             sm = getOrCreateStateMachine(device);
+                            /* Incoming connection try to connect other devices from the group */
+                            connectSet(device);
                             break;
                         default:
                             break;
@@ -976,6 +990,7 @@
         } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED) {
             int group_id = stackEvent.valueInt1;
             int group_status = stackEvent.valueInt2;
+            boolean send_intent = false;
 
             switch (group_status) {
                 case LeAudioStackEvent.GROUP_STATUS_ACTIVE: {
@@ -985,6 +1000,7 @@
                             descriptor.mIsActive = true;
                             updateActiveDevices(group_id, ACTIVE_CONTEXTS_NONE,
                                                 descriptor.mActiveContexts, descriptor.mIsActive);
+                            send_intent = true;
                         }
                     } else {
                         Log.e(TAG, "no descriptors for group: " + group_id);
@@ -998,6 +1014,7 @@
                             descriptor.mIsActive = false;
                             updateActiveDevices(group_id, descriptor.mActiveContexts,
                                     ACTIVE_CONTEXTS_NONE, descriptor.mIsActive);
+                            send_intent = true;
                         }
                     } else {
                         Log.e(TAG, "no descriptors for group: " + group_id);
@@ -1008,10 +1025,11 @@
                     break;
             }
 
-            intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_STATUS_CHANGED);
-            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, group_id);
-            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_STATUS, group_status);
-
+            if (send_intent) {
+                intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_STATUS_CHANGED);
+                intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, group_id);
+                intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_STATUS, group_status);
+            }
         }
 
         if (intent != null) {
diff --git a/src/com/android/bluetooth/mapclient/OWNERS b/src/com/android/bluetooth/mapclient/OWNERS
index 06dc3f8..fd47bd7 100644
--- a/src/com/android/bluetooth/mapclient/OWNERS
+++ b/src/com/android/bluetooth/mapclient/OWNERS
@@ -1 +1 @@
-include platform/system/bt:/OWNERS_automotive
+include platform/packages/modules/Bluetooth:/OWNERS_automotive
diff --git a/src/com/android/bluetooth/pbapclient/OWNERS b/src/com/android/bluetooth/pbapclient/OWNERS
index 06dc3f8..fd47bd7 100644
--- a/src/com/android/bluetooth/pbapclient/OWNERS
+++ b/src/com/android/bluetooth/pbapclient/OWNERS
@@ -1 +1 @@
-include platform/system/bt:/OWNERS_automotive
+include platform/packages/modules/Bluetooth:/OWNERS_automotive
diff --git a/src/com/android/bluetooth/vc/VolumeControlService.java b/src/com/android/bluetooth/vc/VolumeControlService.java
index cb22e4d..b47a0ff 100644
--- a/src/com/android/bluetooth/vc/VolumeControlService.java
+++ b/src/com/android/bluetooth/vc/VolumeControlService.java
@@ -260,7 +260,7 @@
     }
 
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
-    List<BluetoothDevice> getConnectedDevices() {
+    public List<BluetoothDevice> getConnectedDevices() {
         enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
                 "Need BLUETOOTH_PRIVILEGED permission");
         synchronized (mStateMachines) {
diff --git a/tests/OWNERS b/tests/OWNERS
index 06dc3f8..fd47bd7 100644
--- a/tests/OWNERS
+++ b/tests/OWNERS
@@ -1 +1 @@
-include platform/system/bt:/OWNERS_automotive
+include platform/packages/modules/Bluetooth:/OWNERS_automotive
diff --git a/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java b/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
index 71843c5..ef26da1 100644
--- a/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
+++ b/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
@@ -97,6 +97,7 @@
     private @Mock Binder mBinder;
     private @Mock AudioManager mAudioManager;
     private @Mock android.app.Application mApplication;
+    private @Mock MetricsLogger mMockMetricsLogger;
 
     // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
     // underlying binder calls.
@@ -215,6 +216,10 @@
         when(mMockService.getName()).thenReturn("Service1");
         when(mMockService2.getName()).thenReturn("Service2");
 
+        when(mMockMetricsLogger.init(any())).thenReturn(true);
+        when(mMockMetricsLogger.close()).thenReturn(true);
+        mAdapterService.setMetricsLogger(mMockMetricsLogger);
+
         // Attach a context to the service for permission checks.
         mAdapterService.attach(mMockContext, null, null, null, mApplication, null);
         mAdapterService.onCreate();
diff --git a/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java b/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java
index cc4e8b7..235a25c 100644
--- a/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java
+++ b/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java
@@ -15,9 +15,13 @@
  */
 package com.android.bluetooth.btservice;
 
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+
 import androidx.test.filters.MediumTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.bluetooth.btservice.AdapterService;
 import com.android.bluetooth.BluetoothMetricsProto.BluetoothLog;
 import com.android.bluetooth.BluetoothMetricsProto.ProfileConnectionStats;
 import com.android.bluetooth.BluetoothMetricsProto.ProfileId;
@@ -27,6 +31,8 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 import java.util.HashMap;
 import java.util.List;
@@ -37,17 +43,42 @@
 @MediumTest
 @RunWith(AndroidJUnit4.class)
 public class MetricsLoggerTest {
+    private TestableMetricsLogger mTestableMetricsLogger;
+    @Mock
+    private AdapterService mMockAdapterService;
+
+    public class TestableMetricsLogger extends MetricsLogger {
+        public HashMap<Integer, Long> mTestableCounters = new HashMap<>();
+
+        @Override
+        protected void writeCounter(int key, long count) {
+            mTestableCounters.put(key, count);
+        }
+
+        @Override
+        protected void scheduleDrains() {
+        }
+
+        @Override
+        protected void cancelPendingDrain() {
+        }
+    }
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         // Dump metrics to clean up internal states
         MetricsLogger.dumpProto(BluetoothLog.newBuilder());
+        mTestableMetricsLogger = new TestableMetricsLogger();
+        doReturn(null)
+                .when(mMockAdapterService).registerReceiver(any(), any());
     }
 
     @After
     public void tearDown() {
         // Dump metrics to clean up internal states
         MetricsLogger.dumpProto(BluetoothLog.newBuilder());
+        mTestableMetricsLogger.close();
     }
 
     /**
@@ -104,4 +135,75 @@
         return profileUsageStatsMap;
     }
 
-}
+    /**
+     * Test add counters and send them to westworld
+     */
+    @Test
+    public void testAddAndSendCountersNormalCases() {
+        mTestableMetricsLogger.init(mMockAdapterService);
+        mTestableMetricsLogger.count(1, 10);
+        mTestableMetricsLogger.count(1, 10);
+        mTestableMetricsLogger.count(2, 5);
+        mTestableMetricsLogger.drainBufferedCounters();
+
+        Assert.assertEquals(20L, mTestableMetricsLogger.mTestableCounters.get(1).longValue());
+        Assert.assertEquals(5L, mTestableMetricsLogger.mTestableCounters.get(2).longValue());
+
+        mTestableMetricsLogger.count(1, 3);
+        mTestableMetricsLogger.count(2, 5);
+        mTestableMetricsLogger.count(2, 5);
+        mTestableMetricsLogger.count(3, 1);
+        mTestableMetricsLogger.drainBufferedCounters();
+        Assert.assertEquals(
+                3L, mTestableMetricsLogger.mTestableCounters.get(1).longValue());
+        Assert.assertEquals(
+                10L, mTestableMetricsLogger.mTestableCounters.get(2).longValue());
+        Assert.assertEquals(
+                1L, mTestableMetricsLogger.mTestableCounters.get(3).longValue());
+    }
+
+    @Test
+    public void testAddAndSendCountersCornerCases() {
+        mTestableMetricsLogger.init(mMockAdapterService);
+        Assert.assertTrue(mTestableMetricsLogger.isInitialized());
+        mTestableMetricsLogger.count(1, -1);
+        mTestableMetricsLogger.count(3, 0);
+        mTestableMetricsLogger.count(2, 10);
+        mTestableMetricsLogger.count(2, Long.MAX_VALUE - 8L);
+        mTestableMetricsLogger.drainBufferedCounters();
+
+        Assert.assertFalse(mTestableMetricsLogger.mTestableCounters.containsKey(1));
+        Assert.assertFalse(mTestableMetricsLogger.mTestableCounters.containsKey(3));
+        Assert.assertEquals(
+                Long.MAX_VALUE, mTestableMetricsLogger.mTestableCounters.get(2).longValue());
+    }
+
+    @Test
+    public void testMetricsLoggerClose() {
+        mTestableMetricsLogger.init(mMockAdapterService);
+        mTestableMetricsLogger.count(1, 1);
+        mTestableMetricsLogger.count(2, 10);
+        mTestableMetricsLogger.count(2, Long.MAX_VALUE);
+        mTestableMetricsLogger.close();
+
+        Assert.assertEquals(
+                1, mTestableMetricsLogger.mTestableCounters.get(1).longValue());
+        Assert.assertEquals(
+                Long.MAX_VALUE, mTestableMetricsLogger.mTestableCounters.get(2).longValue());
+    }
+
+    @Test
+    public void testMetricsLoggerNotInit() {
+        Assert.assertFalse(mTestableMetricsLogger.count(1, 1));
+        mTestableMetricsLogger.drainBufferedCounters();
+        Assert.assertFalse(mTestableMetricsLogger.mTestableCounters.containsKey(1));
+        Assert.assertFalse(mTestableMetricsLogger.close());
+    }
+
+    @Test
+    public void testAddAndSendCountersDoubleInit() {
+        Assert.assertTrue(mTestableMetricsLogger.init(mMockAdapterService));
+        Assert.assertTrue(mTestableMetricsLogger.isInitialized());
+        Assert.assertFalse(mTestableMetricsLogger.init(mMockAdapterService));
+    }
+}
\ No newline at end of file
diff --git a/tests/unit/src/com/android/bluetooth/hfp/HeadsetPhoneStateTest.java b/tests/unit/src/com/android/bluetooth/hfp/HeadsetPhoneStateTest.java
index 99a9f34..130f457 100644
--- a/tests/unit/src/com/android/bluetooth/hfp/HeadsetPhoneStateTest.java
+++ b/tests/unit/src/com/android/bluetooth/hfp/HeadsetPhoneStateTest.java
@@ -137,9 +137,9 @@
     public void testListenForPhoneState_ServiceAndSignalStrength() {
         BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1);
         mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH);
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
         verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH));
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS));
     }
 
     /**
@@ -150,9 +150,9 @@
     public void testListenForPhoneState_ServiceAndSignalStrengthUpdateTurnOffSignalStrengh() {
         BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1);
         mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH);
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
         verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH));
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS));
         mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE);
         verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE));
         verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE));
@@ -165,9 +165,9 @@
     public void testListenForPhoneState_ServiceAndSignalStrengthUpdateTurnOffAll() {
         BluetoothDevice device1 = TestUtils.getTestDevice(mAdapter, 1);
         mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH);
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
         verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH));
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS));
         mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE);
         verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE));
     }
@@ -183,12 +183,12 @@
         BluetoothDevice device2 = TestUtils.getTestDevice(mAdapter, 2);
         // Enabling updates from first device should trigger subscription
         mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH);
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
         verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH));
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS));
         // Enabling updates from second device should not trigger the same subscription
         mHeadsetPhoneState.listenForPhoneState(device2, PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH);
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
         // Disabling updates from first device should not cancel subscription
         mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE);
         // Disabling updates from second device should cancel subscription
@@ -211,15 +211,15 @@
         verifyNoMoreInteractions(mTelephonyManager);
         // Partially enabling updates from second device should trigger partial subscription
         mHeadsetPhoneState.listenForPhoneState(device2,
-                PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH);
+                PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
         verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE));
         verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH));
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS));
         // Partially disabling updates from first device should not cancel all subscription
         mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE);
         verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE));
         verify(mTelephonyManager).listen(
-                any(), eq(PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH));
+                any(), eq(PhoneStateListener.LISTEN_SIGNAL_STRENGTHS));
         // Partially disabling updates from second device should cancel subscription
         mHeadsetPhoneState.listenForPhoneState(device2, PhoneStateListener.LISTEN_NONE);
         verify(mTelephonyManager, times(3)).listen(any(), eq(PhoneStateListener.LISTEN_NONE));
diff --git a/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java b/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java
index 7ff5f1c..3ebcc05 100644
--- a/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java
+++ b/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java
@@ -954,8 +954,7 @@
         mHeadsetService.startVoiceRecognition(deviceA);
         verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).atResponseCode(deviceA,
                 HeadsetHalConstants.AT_RESPONSE_OK, 0);
-        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS))
-                .setParameters("A2dpSuspended=true");
+        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setA2dpSuspended(true);
         verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).connectAudio(deviceA);
         verifyNoMoreInteractions(mNativeInterface);
     }
@@ -1008,8 +1007,7 @@
         // We still continue on the initiating HF
         verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).atResponseCode(deviceA,
                 HeadsetHalConstants.AT_RESPONSE_OK, 0);
-        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS))
-                .setParameters("A2dpSuspended=true");
+        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setA2dpSuspended(true);
         verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).connectAudio(deviceA);
         verifyNoMoreInteractions(mNativeInterface);
     }
@@ -1084,8 +1082,7 @@
         verify(mNativeInterface).setActiveDevice(deviceA);
         Assert.assertEquals(deviceA, mHeadsetService.getActiveDevice());
         verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).startVoiceRecognition(deviceA);
-        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS))
-                .setParameters("A2dpSuspended=true");
+        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setA2dpSuspended(true);
         verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).connectAudio(deviceA);
         waitAndVerifyAudioStateIntent(ASYNC_CALL_TIMEOUT_MILLIS, deviceA,
                 BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
@@ -1133,8 +1130,7 @@
         Assert.assertTrue(mHeadsetService.startVoiceRecognition(device));
         verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).atResponseCode(device,
                 HeadsetHalConstants.AT_RESPONSE_OK, 0);
-        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS))
-                .setParameters("A2dpSuspended=true");
+        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setA2dpSuspended(true);
         verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).connectAudio(device);
         waitAndVerifyAudioStateIntent(ASYNC_CALL_TIMEOUT_MILLIS, device,
                 BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
@@ -1151,8 +1147,7 @@
         Assert.assertNotNull(device);
         Assert.assertTrue(mHeadsetService.startVoiceRecognition(device));
         verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).startVoiceRecognition(device);
-        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS))
-                .setParameters("A2dpSuspended=true");
+        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setA2dpSuspended(true);
         verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).connectAudio(device);
         waitAndVerifyAudioStateIntent(ASYNC_CALL_TIMEOUT_MILLIS, device,
                 BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
diff --git a/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java b/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java
index 1a4e877..d1888bb 100644
--- a/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java
+++ b/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java
@@ -706,7 +706,7 @@
                 headsetCallState.mType, headsetCallState.mName, mAdapter.getAttributionSource());
         TestUtils.waitForLooperToFinishScheduledTask(
                 mHeadsetService.getStateMachinesThreadLooper());
-        verify(mAudioManager, never()).setParameters("A2dpSuspended=true");
+        verify(mAudioManager, never()).setA2dpSuspended(true);
         HeadsetTestUtils.verifyPhoneStateChangeSetters(mPhoneState, headsetCallState,
                 ASYNC_CALL_TIMEOUT_MILLIS);
     }
@@ -765,7 +765,7 @@
                 mHeadsetService.getStateMachinesThreadLooper());
 
         // Should not ask Audio HAL to suspend A2DP without active device
-        verify(mAudioManager, never()).setParameters("A2dpSuspended=true");
+        verify(mAudioManager, never()).setA2dpSuspended(true);
         // Make sure we notify device about this change
         verify(mStateMachines.get(mCurrentDevice)).sendMessage(
                 HeadsetStateMachine.CALL_STATE_CHANGED, headsetCallState);
@@ -783,7 +783,7 @@
         TestUtils.waitForLooperToFinishScheduledTask(
                 mHeadsetService.getStateMachinesThreadLooper());
         // Ask Audio HAL to suspend A2DP
-        verify(mAudioManager).setParameters("A2dpSuspended=true");
+        verify(mAudioManager).setA2dpSuspended(true);
         // Make sure state is updated
         verify(mStateMachines.get(mCurrentDevice)).sendMessage(
                 HeadsetStateMachine.CALL_STATE_CHANGED, headsetCallState);
@@ -847,8 +847,7 @@
                 headsetCallState.mNumHeld, headsetCallState.mCallState, headsetCallState.mNumber,
                 headsetCallState.mType, headsetCallState.mName, mAdapter.getAttributionSource());
         // Ask Audio HAL to suspend A2DP
-        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS))
-                .setParameters("A2dpSuspended=true");
+        verify(mAudioManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).setA2dpSuspended(true);
         // Make sure we notify devices about this change
         for (BluetoothDevice device : connectedDevices) {
             verify(mStateMachines.get(device)).sendMessage(HeadsetStateMachine.CALL_STATE_CHANGED,
diff --git a/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java b/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java
index fde7dd6..f927a61 100644
--- a/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java
+++ b/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java
@@ -896,7 +896,7 @@
     public void testAtBiaEvent_initialSubscriptionWithUpdates() {
         setUpConnectedState();
         verify(mPhoneState).listenForPhoneState(mTestDevice, PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH);
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIA,
                         new HeadsetAgIndicatorEnableState(true, true, false, false), mTestDevice));
@@ -906,7 +906,7 @@
                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIA,
                         new HeadsetAgIndicatorEnableState(false, true, true, false), mTestDevice));
         verify(mPhoneState, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).listenForPhoneState(mTestDevice,
-                PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH);
+                PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
         mHeadsetStateMachine.sendMessage(HeadsetStateMachine.STACK_EVENT,
                 new HeadsetStackEvent(HeadsetStackEvent.EVENT_TYPE_BIA,
                         new HeadsetAgIndicatorEnableState(false, true, false, false), mTestDevice));