From 2a6137f7374d47b3a9307516af2c0107f5dca887 Mon Sep 17 00:00:00 2001
From: Rahul Arya <aryarahul@google.com>
Date: Wed, 18 Jan 2023 02:35:27 +0000
Subject: [PATCH] [Offload] Alternative API for getAclHandle()

This is a synchronous API on BluetoothDevice rather than a
callback-based one on BluetoothGatt.

Test: compiles
Bug: 261093955
Change-Id: I3e008e84e1b2e19158984ecee963b9a63e74b8b1
---
 ...oid_bluetooth_btservice_AdapterService.cpp | 10 +++--
 .../bluetooth/btservice/AdapterService.java   | 36 ++++++++++++++++
 .../bluetooth/btservice/JniCallbacks.java     |  4 +-
 .../bluetooth/btservice/RemoteDevices.java    | 41 ++++++++++++++++++-
 .../btservice/RemoteDevicesTest.java          |  3 +-
 framework/api/system-current.txt              |  1 +
 .../android/bluetooth/BluetoothDevice.java    | 36 ++++++++++++++++
 .../binder/android/bluetooth/IBluetooth.aidl  |  2 +
 system/bta/dm/bta_dm_act.cc                   | 10 +++--
 system/bta/dm/bta_dm_int.h                    |  3 +-
 system/bta/include/bta_api.h                  |  1 +
 system/bta/include/bta_dm_acl.h               |  3 +-
 system/btif/include/btif_common.h             |  3 +-
 system/btif/include/core_callbacks.h          |  3 +-
 system/btif/src/bluetooth.cc                  | 11 +++--
 system/btif/src/btif_dm.cc                    |  8 ++--
 system/btif/test/btif_core_test.cc            |  3 +-
 system/gd/rust/linux/stack/src/bluetooth.rs   |  2 +
 system/gd/rust/topshim/src/btif.rs            | 12 +++++-
 system/include/hardware/bluetooth.h           | 12 +++---
 system/main/shim/l2c_api.cc                   |  2 +-
 system/service/adapter.cc                     |  3 +-
 system/service/hal/bluetooth_interface.cc     | 12 +++---
 system/service/hal/bluetooth_interface.h      |  3 +-
 .../service/hal/fake_bluetooth_interface.cc   |  6 +--
 system/service/hal/fake_bluetooth_interface.h | 10 ++---
 system/service/test/adapter_unittest.cc       |  6 +--
 system/stack/acl/btm_acl.cc                   |  2 +-
 system/test/headless/headless.cc              |  4 +-
 system/test/headless/interface.h              | 10 +++--
 system/test/mock/mock_bluetooth_interface.cc  |  3 +-
 system/test/mock/mock_bta_dm_act.cc           | 10 +++--
 system/test/mock/mock_bta_dm_act.h            | 22 ++++++----
 33 files changed, 226 insertions(+), 71 deletions(-)

diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
index c67ea1b5dd0..c1ac9a57272 100644
--- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -367,7 +367,8 @@ static void acl_state_changed_callback(bt_status_t status, RawAddress* bd_addr,
                                        bt_acl_state_t state,
                                        int transport_link_type,
                                        bt_hci_error_code_t hci_reason,
-                                       bt_conn_direction_t direction) {
+                                       bt_conn_direction_t direction,
+                                       uint16_t acl_handle) {
   if (!bd_addr) {
     ALOGE("Address is null in %s", __func__);
     return;
@@ -387,7 +388,8 @@ static void acl_state_changed_callback(bt_status_t status, RawAddress* bd_addr,
 
   sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback,
                                (jint)status, addr.get(), (jint)state,
-                               (jint)transport_link_type, (jint)hci_reason);
+                               (jint)transport_link_type, (jint)hci_reason,
+                               (jint)acl_handle);
 }
 
 static void discovery_state_changed_callback(bt_discovery_state_t state) {
@@ -959,8 +961,8 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
   method_leAddressAssociateCallback = env->GetMethodID(
       jniCallbackClass, "leAddressAssociateCallback", "([B[B)V");
 
-  method_aclStateChangeCallback =
-      env->GetMethodID(jniCallbackClass, "aclStateChangeCallback", "(I[BIII)V");
+  method_aclStateChangeCallback = env->GetMethodID(
+      jniCallbackClass, "aclStateChangeCallback", "(I[BIIII)V");
 
   method_linkQualityReportCallback = env->GetMethodID(
       jniCallbackClass, "linkQualityReportCallback", "(JIIIIII)V");
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
index ec9c9c8f91e..03604a957f3 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
@@ -2466,6 +2466,34 @@ public class AdapterService extends Service {
             return service.getConnectionState(device);
         }
 
+        @Override
+        public void getConnectionHandle(BluetoothDevice device, int transport,
+                AttributionSource source, SynchronousResultReceiver receiver) {
+            try {
+                receiver.send(getConnectionHandle(device, transport, source));
+            } catch (RuntimeException e) {
+                receiver.propagateException(e);
+            }
+        }
+        @RequiresPermission(allOf = {
+                android.Manifest.permission.BLUETOOTH_CONNECT,
+                android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+        })
+        private int getConnectionHandle(
+                BluetoothDevice device, int transport, AttributionSource attributionSource) {
+            AdapterService service = getService();
+            if (service == null
+                    || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveDevice")
+                    || !Utils.checkConnectPermissionForDataDelivery(
+                        service, attributionSource, TAG)) {
+                return BluetoothDevice.ERROR;
+            }
+
+            enforceBluetoothPrivilegedPermission(service);
+
+            return service.getConnectionHandle(device, transport);
+        }
+
         @Override
         public void canBondWithoutDialog(BluetoothDevice device, AttributionSource source,
                 SynchronousResultReceiver receiver) {
@@ -4453,6 +4481,14 @@ public class AdapterService extends Service {
         return getConnectionStateNative(getBytesFromAddress(device.getAddress()));
     }
 
+    int getConnectionHandle(BluetoothDevice device, int transport) {
+        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+        if (deviceProp == null) {
+            return BluetoothDevice.ERROR;
+        }
+        return deviceProp.getConnectionHandle(transport);
+    }
+
     /**
      * Checks whether the device was recently associated with the comapnion app that called
      * {@link BluetoothDevice#createBond}. This allows these devices to skip the pairing dialog if
diff --git a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java
index a5c986942aa..f7108f494b2 100644
--- a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java
+++ b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java
@@ -76,9 +76,9 @@ final class JniCallbacks {
     }
 
     void aclStateChangeCallback(int status, byte[] address, int newState,
-            int transportLinkType, int hciReason) {
+            int transportLinkType, int hciReason, int handle) {
         mRemoteDevices.aclStateChangeCallback(status, address, newState,
-                transportLinkType, hciReason);
+                transportLinkType, hciReason, handle);
     }
 
     void stateChangeCallback(int status) {
diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java
index 7176fed0449..4dd5c6e7828 100644
--- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java
+++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java
@@ -307,6 +307,8 @@ final class RemoteDevices {
         private String mIdentityAddress;
         private boolean mIsConsolidated = false;
         private int mBluetoothClass = BluetoothClass.Device.Major.UNCATEGORIZED;
+        private int mBredrConnectionHandle = BluetoothDevice.ERROR;
+        private int mLeConnectionHandle = BluetoothDevice.ERROR;
         private short mRssi;
         private String mAlias;
         private BluetoothDevice mDevice;
@@ -394,6 +396,38 @@ final class RemoteDevices {
             }
         }
 
+        /**
+         * @param transport the transport on which the connection exists
+         * @return the mConnectionHandle
+         */
+        int getConnectionHandle(int transport) {
+            synchronized (mObject) {
+                if (transport == BluetoothDevice.TRANSPORT_BREDR) {
+                    return mBredrConnectionHandle;
+                } else if (transport == BluetoothDevice.TRANSPORT_LE) {
+                    return mLeConnectionHandle;
+                } else {
+                    return BluetoothDevice.ERROR;
+                }
+            }
+        }
+
+        /**
+         * @param connectionHandle the connectionHandle to set
+         * @param transport the transport on which to set the handle
+         */
+        void setConnectionHandle(int connectionHandle, int transport) {
+            synchronized (mObject) {
+                if (transport == BluetoothDevice.TRANSPORT_BREDR) {
+                    mBredrConnectionHandle = connectionHandle;
+                } else if (transport == BluetoothDevice.TRANSPORT_LE) {
+                    mLeConnectionHandle = connectionHandle;
+                } else {
+                    errorLog("setConnectionHandle() unexpected transport value " + transport);
+                }
+            }
+        }
+
         /**
          * @return the mUuids
          */
@@ -945,7 +979,7 @@ final class RemoteDevices {
             android.Manifest.permission.BLUETOOTH_PRIVILEGED,
     })
     void aclStateChangeCallback(int status, byte[] address, int newState,
-                                int transportLinkType, int hciReason) {
+                                int transportLinkType, int hciReason, int handle) {
         if (status != AbstractionLayer.BT_STATUS_SUCCESS) {
             debugLog("aclStateChangeCallback status is " + status + ", skipping");
             return;
@@ -958,10 +992,14 @@ final class RemoteDevices {
                     + Utils.getAddressStringFromByte(address) + ", newState=" + newState);
             return;
         }
+
+        DeviceProperties deviceProperties = getDeviceProperties(device);
+
         int state = mAdapterService.getState();
 
         Intent intent = null;
         if (newState == AbstractionLayer.BT_ACL_STATE_CONNECTED) {
+            deviceProperties.setConnectionHandle(handle, transportLinkType);
             if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_TURNING_ON) {
                 intent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED);
                 intent.putExtra(BluetoothDevice.EXTRA_TRANSPORT, transportLinkType);
@@ -979,6 +1017,7 @@ final class RemoteDevices {
                     "aclStateChangeCallback: Adapter State: " + BluetoothAdapter.nameForState(state)
                             + " Connected: " + device);
         } else {
+            deviceProperties.setConnectionHandle(BluetoothDevice.ERROR, transportLinkType);
             if (device.getBondState() == BluetoothDevice.BOND_BONDING) {
                 // Send PAIRING_CANCEL intent to dismiss any dialog requesting bonding.
                 intent = new Intent(BluetoothDevice.ACTION_PAIRING_CANCEL);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java
index b7ba057d248..54a2930f947 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java
@@ -296,7 +296,8 @@ public class RemoteDevicesTest {
         // BluetoothDevice.BATTERY_LEVEL_UNKNOWN
         when(mAdapterService.getState()).thenReturn(BluetoothAdapter.STATE_ON);
         mRemoteDevices.aclStateChangeCallback(0, Utils.getByteAddress(mDevice1),
-                AbstractionLayer.BT_ACL_STATE_DISCONNECTED, 2, 19); // HCI code 19 remote terminated
+                AbstractionLayer.BT_ACL_STATE_DISCONNECTED, 2, 19,
+                BluetoothDevice.ERROR); // HCI code 19 remote terminated
         // Verify ACTION_ACL_DISCONNECTED and BATTERY_LEVEL_CHANGED intent are sent
         verify(mAdapterService, times(3)).sendBroadcast(mIntentArgument.capture(),
                 mStringArgument.capture(), any(Bundle.class));
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index 67db13f4d06..82c9095fe2c 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -172,6 +172,7 @@ package android.bluetooth {
     method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BluetoothAudioPolicy getAudioPolicy();
     method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getAudioPolicyRemoteSupported();
     method @IntRange(from=0xffffff9c, to=100) @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getBatteryLevel();
+    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionHandle(int);
     method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public String getIdentityAddress();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getMessageAccessPermission();
     method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public byte[] getMetadata(int);
diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java
index 8d88f26c52f..913d3102465 100644
--- a/framework/java/android/bluetooth/BluetoothDevice.java
+++ b/framework/java/android/bluetooth/BluetoothDevice.java
@@ -2206,6 +2206,42 @@ public final class BluetoothDevice implements Parcelable, Attributable {
         return false;
     }
 
+    /**
+     * Returns the ACL connection handle associated with an open connection to
+     * this device on the given transport.
+     *
+     * @return the ACL handle, or {@link BluetoothDevice#ERROR} if no connection currently exists on
+     *         the given transport.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.BLUETOOTH_CONNECT,
+            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+    })
+    public int getConnectionHandle(@Transport int transport) {
+        if (DBG) {
+            log("getConnectionHandle()");
+        }
+        final IBluetooth service = getService();
+        if (service == null || !isBluetoothEnabled()) {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) {
+                log(Log.getStackTraceString(new Throwable()));
+            }
+        } else {
+            try {
+                final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get();
+                service.getConnectionHandle(this, transport, mAttributionSource, recv);
+                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(-1);
+            } catch (RemoteException | TimeoutException e) {
+                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+            }
+        }
+        // BT is not enabled, we cannot be connected.
+        return BluetoothDevice.ERROR;
+    }
+
     /**
      * Returns whether there is an open connection to this device
      * that has been encrypted.
diff --git a/system/binder/android/bluetooth/IBluetooth.aidl b/system/binder/android/bluetooth/IBluetooth.aidl
index 5a7de732235..d14b7053f0e 100644
--- a/system/binder/android/bluetooth/IBluetooth.aidl
+++ b/system/binder/android/bluetooth/IBluetooth.aidl
@@ -120,6 +120,8 @@ interface IBluetooth
     oneway void getSupportedProfiles(in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
     oneway void getConnectionState(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
+    oneway void getConnectionHandle(in BluetoothDevice device, int transport, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
     oneway void getRemoteName(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc
index 1352336adcc..302935377c9 100644
--- a/system/bta/dm/bta_dm_act.cc
+++ b/system/bta/dm/bta_dm_act.cc
@@ -2525,7 +2525,8 @@ static tBTA_DM_PEER_DEVICE* allocate_device_for(const RawAddress& bd_addr,
   return nullptr;
 }
 
-void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
+void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport,
+                   uint16_t acl_handle) {
   auto device = allocate_device_for(bd_addr, transport);
   if (device == nullptr) {
     LOG_WARN("Unable to allocate device resources for new connection");
@@ -2552,6 +2553,7 @@ void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
     memset(&conn, 0, sizeof(tBTA_DM_SEC));
     conn.link_up.bd_addr = bd_addr;
     conn.link_up.transport_link_type = transport;
+    conn.link_up.acl_handle = acl_handle;
 
     bta_dm_cb.p_sec_cback(BTA_DM_LINK_UP_EVT, &conn);
     LOG_DEBUG("Executed security callback for new connection available");
@@ -2559,8 +2561,10 @@ void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
   bta_dm_adjust_roles(true);
 }
 
-void BTA_dm_acl_up(const RawAddress bd_addr, tBT_TRANSPORT transport) {
-  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_acl_up, bd_addr, transport));
+void BTA_dm_acl_up(const RawAddress bd_addr, tBT_TRANSPORT transport,
+                   uint16_t acl_handle) {
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(bta_dm_acl_up, bd_addr, transport, acl_handle));
 }
 
 static void bta_dm_acl_up_failed(const RawAddress bd_addr,
diff --git a/system/bta/dm/bta_dm_int.h b/system/bta/dm/bta_dm_int.h
index 1109a50cc41..8bd58c36971 100644
--- a/system/bta/dm/bta_dm_int.h
+++ b/system/bta/dm/bta_dm_int.h
@@ -242,7 +242,8 @@ struct tBTA_DM_PEER_DEVICE {
   bool in_use;
 
  private:
-  friend void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport);
+  friend void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport,
+                            uint16_t acl_handle);
   friend void bta_dm_pm_btm_status(const RawAddress& bd_addr,
                                    tBTM_PM_STATUS status, uint16_t value,
                                    tHCI_STATUS hci_status);
diff --git a/system/bta/include/bta_api.h b/system/bta/include/bta_api.h
index ff85ece8a9e..4331919f9e3 100644
--- a/system/bta/include/bta_api.h
+++ b/system/bta/include/bta_api.h
@@ -336,6 +336,7 @@ typedef struct {
 typedef struct {
   RawAddress bd_addr; /* BD address peer device. */
   tBT_TRANSPORT transport_link_type;
+  uint16_t acl_handle;
 } tBTA_DM_LINK_UP;
 
 /* Structure associated with BTA_DM_LINK_UP_FAILED_EVT */
diff --git a/system/bta/include/bta_dm_acl.h b/system/bta/include/bta_dm_acl.h
index a49d8ee8261..ec724851452 100644
--- a/system/bta/include/bta_dm_acl.h
+++ b/system/bta/include/bta_dm_acl.h
@@ -24,7 +24,8 @@
 #include "types/hci_role.h"
 #include "types/raw_address.h"
 
-void BTA_dm_acl_up(const RawAddress bd_addr, tBT_TRANSPORT transport);
+void BTA_dm_acl_up(const RawAddress bd_addr, tBT_TRANSPORT transport,
+                   uint16_t acl_handle);
 void BTA_dm_acl_up_failed(const RawAddress bd_addr, tBT_TRANSPORT transport,
                           tHCI_STATUS hci_status);
 void BTA_dm_acl_down(const RawAddress bd_addr, tBT_TRANSPORT transport);
diff --git a/system/btif/include/btif_common.h b/system/btif/include/btif_common.h
index 4d69014a9fa..72d2117a6f9 100644
--- a/system/btif/include/btif_common.h
+++ b/system/btif/include/btif_common.h
@@ -225,7 +225,8 @@ void invoke_le_address_associate_cb(RawAddress main_bd_addr,
 void invoke_acl_state_changed_cb(bt_status_t status, RawAddress bd_addr,
                                  bt_acl_state_t state, int transport_link_type,
                                  bt_hci_error_code_t hci_reason,
-                                 bt_conn_direction_t direction);
+                                 bt_conn_direction_t direction,
+                                 uint16_t acl_handle);
 void invoke_thread_evt_cb(bt_cb_thread_evt event);
 void invoke_le_test_mode_cb(bt_status_t status, uint16_t count);
 void invoke_energy_info_cb(bt_activity_energy_info energy_info,
diff --git a/system/btif/include/core_callbacks.h b/system/btif/include/core_callbacks.h
index 12a1ac62714..16e5856bf40 100644
--- a/system/btif/include/core_callbacks.h
+++ b/system/btif/include/core_callbacks.h
@@ -55,7 +55,8 @@ struct EventCallbacks {
                                       bt_acl_state_t state,
                                       int transport_link_type,
                                       bt_hci_error_code_t hci_reason,
-                                      bt_conn_direction_t direction);
+                                      bt_conn_direction_t direction,
+                                      uint16_t acl_handle);
   void (*invoke_thread_evt_cb)(bt_cb_thread_evt event);
   void (*invoke_le_test_mode_cb)(bt_status_t status, uint16_t count);
   void (*invoke_energy_info_cb)(bt_activity_energy_info energy_info,
diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc
index b303c3d095c..96b82330291 100644
--- a/system/btif/src/bluetooth.cc
+++ b/system/btif/src/bluetooth.cc
@@ -1239,17 +1239,20 @@ void invoke_le_address_associate_cb(RawAddress main_bd_addr,
 void invoke_acl_state_changed_cb(bt_status_t status, RawAddress bd_addr,
                                  bt_acl_state_t state, int transport_link_type,
                                  bt_hci_error_code_t hci_reason,
-                                 bt_conn_direction_t direction) {
+                                 bt_conn_direction_t direction,
+                                 uint16_t acl_handle) {
   do_in_jni_thread(
       FROM_HERE,
       base::BindOnce(
           [](bt_status_t status, RawAddress bd_addr, bt_acl_state_t state,
              int transport_link_type, bt_hci_error_code_t hci_reason,
-             bt_conn_direction_t direction) {
+             bt_conn_direction_t direction, uint16_t acl_handle) {
             HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, status, &bd_addr,
-                      state, transport_link_type, hci_reason, direction);
+                      state, transport_link_type, hci_reason, direction,
+                      acl_handle);
           },
-          status, bd_addr, state, transport_link_type, hci_reason, direction));
+          status, bd_addr, state, transport_link_type, hci_reason, direction,
+          acl_handle));
 }
 
 void invoke_thread_evt_cb(bt_cb_thread_evt event) {
diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc
index 84fdd66fafa..e8186ba3a73 100644
--- a/system/btif/src/btif_dm.cc
+++ b/system/btif/src/btif_dm.cc
@@ -1923,7 +1923,8 @@ static void btif_dm_upstreams_evt(uint16_t event, char* p_param) {
           (int)p_data->link_up.transport_link_type, HCI_SUCCESS,
           btm_is_acl_locally_initiated()
               ? bt_conn_direction_t::BT_CONN_DIRECTION_OUTGOING
-              : bt_conn_direction_t::BT_CONN_DIRECTION_INCOMING);
+              : bt_conn_direction_t::BT_CONN_DIRECTION_INCOMING,
+          p_data->link_up.acl_handle);
       break;
 
     case BTA_DM_LINK_UP_FAILED_EVT:
@@ -1933,7 +1934,8 @@ static void btif_dm_upstreams_evt(uint16_t event, char* p_param) {
           p_data->link_up_failed.status,
           btm_is_acl_locally_initiated()
               ? bt_conn_direction_t::BT_CONN_DIRECTION_OUTGOING
-              : bt_conn_direction_t::BT_CONN_DIRECTION_INCOMING);
+              : bt_conn_direction_t::BT_CONN_DIRECTION_INCOMING,
+          INVALID_ACL_HANDLE);
       break;
 
     case BTA_DM_LINK_DOWN_EVT: {
@@ -1961,7 +1963,7 @@ static void btif_dm_upstreams_evt(uint16_t event, char* p_param) {
           BT_STATUS_SUCCESS, bd_addr, BT_ACL_STATE_DISCONNECTED,
           (int)p_data->link_down.transport_link_type,
           static_cast<bt_hci_error_code_t>(btm_get_acl_disc_reason_code()),
-          direction);
+          direction, INVALID_ACL_HANDLE);
       LOG_DEBUG(
           "Sent BT_ACL_STATE_DISCONNECTED upward as ACL link down event "
           "device:%s reason:%s",
diff --git a/system/btif/test/btif_core_test.cc b/system/btif/test/btif_core_test.cc
index 9a7e6840b06..fae3b8ab954 100644
--- a/system/btif/test/btif_core_test.cc
+++ b/system/btif/test/btif_core_test.cc
@@ -78,7 +78,8 @@ void le_address_associate_callback(RawAddress* main_bd_addr,
 void acl_state_changed_callback(bt_status_t status, RawAddress* remote_bd_addr,
                                 bt_acl_state_t state, int transport_link_type,
                                 bt_hci_error_code_t hci_reason,
-                                bt_conn_direction_t direction) {}
+                                bt_conn_direction_t direction,
+                                uint16_t acl_handle) {}
 void link_quality_report_callback(uint64_t timestamp, int report_id, int rssi,
                                   int snr, int retransmission_count,
                                   int packets_not_receive_count,
diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs
index 54346a974a0..d0eb60b1154 100644
--- a/system/gd/rust/linux/stack/src/bluetooth.rs
+++ b/system/gd/rust/linux/stack/src/bluetooth.rs
@@ -782,6 +782,7 @@ pub(crate) trait BtifBluetoothCallbacks {
         link_type: BtTransport,
         hci_reason: BtHciErrorCode,
         conn_direction: BtConnectionDirection,
+        acl_handle: u16,
     ) {
     }
 
@@ -1143,6 +1144,7 @@ impl BtifBluetoothCallbacks for Bluetooth {
         link_type: BtTransport,
         hci_reason: BtHciErrorCode,
         conn_direction: BtConnectionDirection,
+        acl_handle: u16,
     ) {
         if status != BtStatus::Success {
             warn!(
diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs
index b5f9eab13a5..cd2d0f5aeb6 100644
--- a/system/gd/rust/topshim/src/btif.rs
+++ b/system/gd/rust/topshim/src/btif.rs
@@ -839,7 +839,15 @@ pub enum BaseCallbacks {
     BondState(BtStatus, RawAddress, BtBondState, i32),
     AddressConsolidate(RawAddress, RawAddress),
     LeAddressAssociate(RawAddress, RawAddress),
-    AclState(BtStatus, RawAddress, BtAclState, BtTransport, BtHciErrorCode, BtConnectionDirection),
+    AclState(
+        BtStatus,
+        RawAddress,
+        BtAclState,
+        BtTransport,
+        BtHciErrorCode,
+        BtConnectionDirection,
+        u16,
+    ),
     // Unimplemented so far:
     // thread_evt_cb
     // dut_mode_recv_cb
@@ -902,7 +910,7 @@ cb_variant!(BaseCb, le_address_associate_cb -> BaseCallbacks::LeAddressAssociate
 });
 
 cb_variant!(BaseCb, acl_state_cb -> BaseCallbacks::AclState,
-u32 -> BtStatus, *mut RawAddress, bindings::bt_acl_state_t -> BtAclState, i32 -> BtTransport, bindings::bt_hci_error_code_t -> BtHciErrorCode, bindings::bt_conn_direction_t -> BtConnectionDirection, {
+u32 -> BtStatus, *mut RawAddress, bindings::bt_acl_state_t -> BtAclState, i32 -> BtTransport, bindings::bt_hci_error_code_t -> BtHciErrorCode, bindings::bt_conn_direction_t -> BtConnectionDirection, u16 -> u16, {
     let _1 = unsafe { *(_1 as *const RawAddress) };
 });
 
diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h
index a5e1193f674..beae42218c6 100644
--- a/system/include/hardware/bluetooth.h
+++ b/system/include/hardware/bluetooth.h
@@ -183,6 +183,8 @@ typedef enum {
   BT_CONN_DIRECTION_INCOMING
 } bt_conn_direction_t;
 
+constexpr uint16_t INVALID_ACL_HANDLE = 0xFFFF;
+
 /** Bluetooth SDP service record */
 typedef struct {
   bluetooth::Uuid uuid;
@@ -495,12 +497,10 @@ typedef void (*le_address_associate_callback)(RawAddress* main_bd_addr,
                                               RawAddress* secondary_bd_addr);
 
 /** Bluetooth ACL connection state changed callback */
-typedef void (*acl_state_changed_callback)(bt_status_t status,
-                                           RawAddress* remote_bd_addr,
-                                           bt_acl_state_t state,
-                                           int transport_link_type,
-                                           bt_hci_error_code_t hci_reason,
-                                           bt_conn_direction_t direction);
+typedef void (*acl_state_changed_callback)(
+    bt_status_t status, RawAddress* remote_bd_addr, bt_acl_state_t state,
+    int transport_link_type, bt_hci_error_code_t hci_reason,
+    bt_conn_direction_t direction, uint16_t acl_handle);
 
 /** Bluetooth link quality report callback */
 typedef void (*link_quality_report_callback)(
diff --git a/system/main/shim/l2c_api.cc b/system/main/shim/l2c_api.cc
index df67c648c93..9783f555a17 100644
--- a/system/main/shim/l2c_api.cc
+++ b/system/main/shim/l2c_api.cc
@@ -482,7 +482,7 @@ class SecurityListenerShim
     address_to_handle_[bda] = handle;
     btm_sec_connected(bda, handle, HCI_SUCCESS, 0);
     BTM_PM_OnConnected(handle, bda);
-    BTA_dm_acl_up(bda, BT_TRANSPORT_BR_EDR);
+    BTA_dm_acl_up(bda, BT_TRANSPORT_BR_EDR, handle);
     address_to_interface_[bda] = std::move(interface);
   }
 
diff --git a/system/service/adapter.cc b/system/service/adapter.cc
index a89477240ec..73cf8360258 100644
--- a/system/service/adapter.cc
+++ b/system/service/adapter.cc
@@ -693,7 +693,8 @@ class AdapterImpl : public Adapter, public hal::BluetoothInterface::Observer {
                                const RawAddress& remote_bdaddr,
                                bt_acl_state_t state, int transport_link_type,
                                bt_hci_error_code_t hci_reason,
-                               bt_conn_direction_t direction) override {
+                               bt_conn_direction_t direction,
+                               uint16_t acl_handle) override {
     std::string device_address = BtAddrString(&remote_bdaddr);
     bool connected = (state == BT_ACL_STATE_CONNECTED);
     LOG(INFO) << "ACL state changed: " << device_address
diff --git a/system/service/hal/bluetooth_interface.cc b/system/service/hal/bluetooth_interface.cc
index 01f2ff57145..40cc2842b09 100644
--- a/system/service/hal/bluetooth_interface.cc
+++ b/system/service/hal/bluetooth_interface.cc
@@ -164,7 +164,8 @@ void LeAddressAssociateCallback(RawAddress* main_bd_addr,
 void AclStateChangedCallback(bt_status_t status, RawAddress* remote_bd_addr,
                              bt_acl_state_t state, int transport_link_type,
                              bt_hci_error_code_t hci_reason,
-                             bt_conn_direction_t direction) {
+                             bt_conn_direction_t direction,
+                             uint16_t acl_handle) {
   shared_lock<shared_mutex_impl> lock(g_instance_lock);
   VERIFY_INTERFACE_OR_RETURN();
   CHECK(remote_bd_addr);
@@ -173,9 +174,9 @@ void AclStateChangedCallback(bt_status_t status, RawAddress* remote_bd_addr,
           << " - BD_ADDR: " << BtAddrString(remote_bd_addr) << " - state: "
           << ((state == BT_ACL_STATE_CONNECTED) ? "CONNECTED" : "DISCONNECTED")
           << " - HCI_REASON: " << std::to_string(hci_reason);
-  FOR_EACH_BLUETOOTH_OBSERVER(
-      AclStateChangedCallback(status, *remote_bd_addr, state,
-                              transport_link_type, hci_reason, direction));
+  FOR_EACH_BLUETOOTH_OBSERVER(AclStateChangedCallback(
+      status, *remote_bd_addr, state, transport_link_type, hci_reason,
+      direction, acl_handle));
 }
 
 void ThreadEventCallback(bt_cb_thread_evt evt) {
@@ -454,7 +455,8 @@ void BluetoothInterface::Observer::BondStateChangedCallback(
 void BluetoothInterface::Observer::AclStateChangedCallback(
     bt_status_t /* status */, const RawAddress& /* remote_bdaddr */,
     bt_acl_state_t /* state */, int /* transport_link_type */,
-    bt_hci_error_code_t /* hci_reason */, bt_conn_direction_t /* direction */) {
+    bt_hci_error_code_t /* hci_reason */, bt_conn_direction_t /* direction */,
+    uint16_t /* acl_handle*/) {
   // Do nothing.
 }
 
diff --git a/system/service/hal/bluetooth_interface.h b/system/service/hal/bluetooth_interface.h
index 82f9f9c07a8..03b9f20e103 100644
--- a/system/service/hal/bluetooth_interface.h
+++ b/system/service/hal/bluetooth_interface.h
@@ -77,7 +77,8 @@ class BluetoothInterface {
                                          bt_acl_state_t state,
                                          int transport_link_type,
                                          bt_hci_error_code_t hci_reason,
-                                         bt_conn_direction_t direction);
+                                         bt_conn_direction_t direction,
+                                         uint16_t acl_handle);
     virtual void LinkQualityReportCallback(
         uint64_t timestamp, int report_id, int rssi, int snr,
         int retransmission_count, int packets_not_receive_count,
diff --git a/system/service/hal/fake_bluetooth_interface.cc b/system/service/hal/fake_bluetooth_interface.cc
index c0884f24be4..fa81ad20268 100644
--- a/system/service/hal/fake_bluetooth_interface.cc
+++ b/system/service/hal/fake_bluetooth_interface.cc
@@ -159,11 +159,11 @@ void FakeBluetoothInterface::NotifyAdapterLocalLeFeaturesPropertyChanged(
 void FakeBluetoothInterface::NotifyAclStateChangedCallback(
     bt_status_t status, const RawAddress& remote_bdaddr, bt_acl_state_t state,
     int transport_link_type, bt_hci_error_code_t hci_reason,
-    bt_conn_direction_t direction) {
+    bt_conn_direction_t direction, uint16_t acl_handle) {
   for (auto& observer : observers_) {
     observer.AclStateChangedCallback(status, remote_bdaddr, state,
-                                     transport_link_type, hci_reason,
-                                     direction);
+                                     transport_link_type, hci_reason, direction,
+                                     acl_handle);
   }
 }
 
diff --git a/system/service/hal/fake_bluetooth_interface.h b/system/service/hal/fake_bluetooth_interface.h
index 9beabe26ce7..28ed335686e 100644
--- a/system/service/hal/fake_bluetooth_interface.h
+++ b/system/service/hal/fake_bluetooth_interface.h
@@ -58,12 +58,10 @@ class FakeBluetoothInterface : public BluetoothInterface {
   void NotifyAdapterAddressPropertyChanged(const RawAddress* address);
   void NotifyAdapterLocalLeFeaturesPropertyChanged(
       const bt_local_le_features_t* features);
-  void NotifyAclStateChangedCallback(bt_status_t status,
-                                     const RawAddress& remote_bdaddr,
-                                     bt_acl_state_t state,
-                                     int transport_link_type,
-                                     bt_hci_error_code_t hci_reason,
-                                     bt_conn_direction_t direction);
+  void NotifyAclStateChangedCallback(
+      bt_status_t status, const RawAddress& remote_bdaddr, bt_acl_state_t state,
+      int transport_link_type, bt_hci_error_code_t hci_reason,
+      bt_conn_direction_t direction, uint16_t acl_handle);
 
   // hal::BluetoothInterface overrides:
   void AddObserver(Observer* observer) override;
diff --git a/system/service/test/adapter_unittest.cc b/system/service/test/adapter_unittest.cc
index c88dc2d6e7c..fb6a9a22633 100644
--- a/system/service/test/adapter_unittest.cc
+++ b/system/service/test/adapter_unittest.cc
@@ -263,7 +263,7 @@ TEST_F(AdapterTest, IsDeviceConnected) {
   // status != BT_STATUS_SUCCESS should be ignored
   fake_hal_iface_->NotifyAclStateChangedCallback(
       BT_STATUS_FAIL, hal_addr, BT_ACL_STATE_CONNECTED, BT_TRANSPORT_LE, 0xff,
-      BT_CONN_DIRECTION_OUTGOING);  // HCI_ERR_UNDEFINED
+      BT_CONN_DIRECTION_OUTGOING, 1);  // HCI_ERR_UNDEFINED
   EXPECT_FALSE(adapter_->IsDeviceConnected(kDeviceAddr));
   EXPECT_TRUE(observer.last_connection_state_address().empty());
   EXPECT_FALSE(observer.last_device_connected_state());
@@ -271,7 +271,7 @@ TEST_F(AdapterTest, IsDeviceConnected) {
   // Connected
   fake_hal_iface_->NotifyAclStateChangedCallback(
       BT_STATUS_SUCCESS, hal_addr, BT_ACL_STATE_CONNECTED, BT_TRANSPORT_LE,
-      0x00, BT_CONN_DIRECTION_OUTGOING);  // HCI_SUCCESS
+      0x00, BT_CONN_DIRECTION_OUTGOING, 1);  // HCI_SUCCESS
   EXPECT_TRUE(adapter_->IsDeviceConnected(kDeviceAddr));
   EXPECT_EQ(kDeviceAddr, observer.last_connection_state_address());
   EXPECT_TRUE(observer.last_device_connected_state());
@@ -279,7 +279,7 @@ TEST_F(AdapterTest, IsDeviceConnected) {
   // Disconnected
   fake_hal_iface_->NotifyAclStateChangedCallback(
       BT_STATUS_SUCCESS, hal_addr, BT_ACL_STATE_DISCONNECTED, BT_TRANSPORT_LE,
-      0x16, BT_CONN_DIRECTION_OUTGOING);  // HCI_ERR_CONN_CAUSE_LOCAL_HOST
+      0x16, BT_CONN_DIRECTION_OUTGOING, 1);  // HCI_ERR_CONN_CAUSE_LOCAL_HOST
   EXPECT_FALSE(adapter_->IsDeviceConnected(kDeviceAddr));
   EXPECT_EQ(kDeviceAddr, observer.last_connection_state_address());
   EXPECT_FALSE(observer.last_device_connected_state());
diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc
index add7c4a4fd7..5a2c47859ed 100644
--- a/system/stack/acl/btm_acl.cc
+++ b/system/stack/acl/btm_acl.cc
@@ -162,7 +162,7 @@ void NotifyAclLinkUp(tACL_CONN& p_acl) {
     return;
   }
   p_acl.link_up_issued = true;
-  BTA_dm_acl_up(p_acl.remote_addr, p_acl.transport);
+  BTA_dm_acl_up(p_acl.remote_addr, p_acl.transport, p_acl.hci_handle);
 }
 
 void NotifyAclLinkDown(tACL_CONN& p_acl) {
diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc
index 74a89e57999..9006afd139e 100644
--- a/system/test/headless/headless.cc
+++ b/system/test/headless/headless.cc
@@ -156,7 +156,7 @@ void le_address_associate([[maybe_unused]] RawAddress* main_bd_addr,
 void acl_state_changed(bt_status_t status, RawAddress* remote_bd_addr,
                        bt_acl_state_t state, int transport_link_type,
                        bt_hci_error_code_t hci_reason,
-                       bt_conn_direction_t direction) {
+                       bt_conn_direction_t direction, uint16_t acl_handle) {
   CHECK(remote_bd_addr != nullptr);
   const size_t num_callbacks = interface_api_callback_map_.size();
   auto callback_list = interface_api_callback_map_.find(__func__);
@@ -165,7 +165,7 @@ void acl_state_changed(bt_status_t status, RawAddress* remote_bd_addr,
     for (auto callback : callback_list->second) {
       acl_state_changed_params_t params(status, raw_address, state,
                                         transport_link_type, hci_reason,
-                                        direction);
+                                        direction, acl_handle);
       (callback)(&params);
     }
   }
diff --git a/system/test/headless/interface.h b/system/test/headless/interface.h
index 248285b72ad..370d86138ec 100644
--- a/system/test/headless/interface.h
+++ b/system/test/headless/interface.h
@@ -39,14 +39,15 @@ struct acl_state_changed_params_t : public callback_params_t {
   acl_state_changed_params_t(bt_status_t status, RawAddress remote_bd_addr,
                              bt_acl_state_t state, int transport_link_type,
                              bt_hci_error_code_t hci_reason,
-                             bt_conn_direction_t direction)
+                             bt_conn_direction_t direction, uint16_t acl_handle)
       : callback_params_t("acl_state_changed"),
         status(status),
         remote_bd_addr(remote_bd_addr),
         state(state),
         transport_link_type(transport_link_type),
         hci_reason(hci_reason),
-        direction(direction) {}
+        direction(direction),
+        acl_handle(acl_handle) {}
   acl_state_changed_params_t(const acl_state_changed_params_t& params) =
       default;
   virtual ~acl_state_changed_params_t() {}
@@ -57,17 +58,18 @@ struct acl_state_changed_params_t : public callback_params_t {
   int transport_link_type;
   bt_hci_error_code_t hci_reason;
   bt_conn_direction_t direction;
+  uint16_t acl_handle;
 
   std::string ToString() const override {
     return base::StringPrintf(
         "status:%s remote_bd_addr:%s state:%s transport:%s reason:%s "
-        "direction:%d",
+        "direction:%d handle:%d",
         bt_status_text(status).c_str(), remote_bd_addr.ToString().c_str(),
         (state == BT_ACL_STATE_CONNECTED) ? "CONNECTED" : "DISCONNECTED",
         bt_transport_text(static_cast<const tBT_TRANSPORT>(transport_link_type))
             .c_str(),
         bt_status_text(static_cast<const bt_status_t>(hci_reason)).c_str(),
-        direction);
+        direction, acl_handle);
   }
 };
 
diff --git a/system/test/mock/mock_bluetooth_interface.cc b/system/test/mock/mock_bluetooth_interface.cc
index 17be0f6e4c9..728547f6666 100644
--- a/system/test/mock/mock_bluetooth_interface.cc
+++ b/system/test/mock/mock_bluetooth_interface.cc
@@ -269,7 +269,8 @@ void invoke_le_address_associate_cb(RawAddress main_bd_addr,
 void invoke_acl_state_changed_cb(bt_status_t status, RawAddress bd_addr,
                                  bt_acl_state_t state, int transport_link_type,
                                  bt_hci_error_code_t hci_reason,
-                                 bt_conn_direction_t direction) {}
+                                 bt_conn_direction_t direction,
+                                 uint16_t acl_handle) {}
 
 void invoke_thread_evt_cb(bt_cb_thread_evt event) {}
 
diff --git a/system/test/mock/mock_bta_dm_act.cc b/system/test/mock/mock_bta_dm_act.cc
index b64f5f62fc6..5f6e2d7d750 100644
--- a/system/test/mock/mock_bta_dm_act.cc
+++ b/system/test/mock/mock_bta_dm_act.cc
@@ -116,9 +116,10 @@ void BTA_dm_acl_down(const RawAddress bd_addr, tBT_TRANSPORT transport) {
   mock_function_count_map[__func__]++;
   test::mock::bta_dm_act::BTA_dm_acl_down(bd_addr, transport);
 }
-void BTA_dm_acl_up(const RawAddress bd_addr, tBT_TRANSPORT transport) {
+void BTA_dm_acl_up(const RawAddress bd_addr, tBT_TRANSPORT transport,
+                   uint16_t acl_handle) {
   mock_function_count_map[__func__]++;
-  test::mock::bta_dm_act::BTA_dm_acl_up(bd_addr, transport);
+  test::mock::bta_dm_act::BTA_dm_acl_up(bd_addr, transport, acl_handle);
 }
 void BTA_dm_acl_up_failed(const RawAddress bd_addr, tBT_TRANSPORT transport,
                           tHCI_STATUS hci_status) {
@@ -143,9 +144,10 @@ void BTA_dm_report_role_change(const RawAddress bd_addr, tHCI_ROLE new_role,
   test::mock::bta_dm_act::BTA_dm_report_role_change(bd_addr, new_role,
                                                     hci_status);
 }
-void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
+void bta_dm_acl_up(const RawAddress& bd_addr, tBT_TRANSPORT transport,
+                   uint16_t acl_handle) {
   mock_function_count_map[__func__]++;
-  test::mock::bta_dm_act::bta_dm_acl_up(bd_addr, transport);
+  test::mock::bta_dm_act::bta_dm_acl_up(bd_addr, transport, acl_handle);
 }
 void bta_dm_add_ble_device(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type,
                            tBT_DEVICE_TYPE dev_type) {
diff --git a/system/test/mock/mock_bta_dm_act.h b/system/test/mock/mock_bta_dm_act.h
index 755e04d1815..3f2867a08c9 100644
--- a/system/test/mock/mock_bta_dm_act.h
+++ b/system/test/mock/mock_bta_dm_act.h
@@ -91,10 +91,13 @@ extern struct BTA_dm_acl_down BTA_dm_acl_down;
 // Params: const RawAddress bd_addr, tBT_TRANSPORT transport
 // Return: void
 struct BTA_dm_acl_up {
-  std::function<void(const RawAddress bd_addr, tBT_TRANSPORT transport)> body{
-      [](const RawAddress bd_addr, tBT_TRANSPORT transport) {}};
-  void operator()(const RawAddress bd_addr, tBT_TRANSPORT transport) {
-    body(bd_addr, transport);
+  std::function<void(const RawAddress bd_addr, tBT_TRANSPORT transport,
+                     uint16_t acl_handle)>
+      body{[](const RawAddress bd_addr, tBT_TRANSPORT transport,
+              uint16_t acl_handle) {}};
+  void operator()(const RawAddress bd_addr, tBT_TRANSPORT transport,
+                  uint16_t acl_handle) {
+    body(bd_addr, transport, acl_handle);
   };
 };
 extern struct BTA_dm_acl_up BTA_dm_acl_up;
@@ -162,10 +165,13 @@ extern struct BTA_dm_report_role_change BTA_dm_report_role_change;
 // Params: const RawAddress& bd_addr, tBT_TRANSPORT transport
 // Return: void
 struct bta_dm_acl_up {
-  std::function<void(const RawAddress& bd_addr, tBT_TRANSPORT transport)> body{
-      [](const RawAddress& bd_addr, tBT_TRANSPORT transport) {}};
-  void operator()(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
-    body(bd_addr, transport);
+  std::function<void(const RawAddress& bd_addr, tBT_TRANSPORT transport,
+                     uint16_t acl_handle)>
+      body{[](const RawAddress& bd_addr, tBT_TRANSPORT transport,
+              uint16_t acl_handle) {}};
+  void operator()(const RawAddress& bd_addr, tBT_TRANSPORT transport,
+                  uint16_t acl_handle) {
+    body(bd_addr, transport, acl_handle);
   };
 };
 extern struct bta_dm_acl_up bta_dm_acl_up;
-- 
GitLab