Merge "Add broadcast feature supported API"
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
index e463b2d..2e4837e 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
@@ -127,7 +127,9 @@
     private int mDynamicAudioBufferSizeSupportedCodecsGroup2;
 
     private boolean mIsLePeriodicAdvertisingSyncTransferSenderSupported;
+    private boolean mIsLePeriodicAdvertisingSyncTransferRecipientSupported;
     private boolean mIsLeConnectedIsochronousStreamCentralSupported;
+    private boolean mIsLeIsochronousBroadcasterSupported;
 
     private List<BufferConstraint> mBufferConstraintList;
 
@@ -514,6 +516,13 @@
     }
 
     /**
+     * @return the mIsLePeriodicAdvertisingSyncTransferRecipientSupported
+     */
+    boolean isLePeriodicAdvertisingSyncTransferRecipientSupported() {
+        return mIsLePeriodicAdvertisingSyncTransferRecipientSupported;
+    }
+
+    /**
      * @return the mIsLeConnectedIsochronousStreamCentralSupported
      */
     boolean isLeConnectedIsochronousStreamCentralSupported() {
@@ -521,6 +530,13 @@
     }
 
     /**
+     * @return the mIsLeIsochronousBroadcasterSupported
+     */
+    boolean isLeIsochronousBroadcasterSupported() {
+        return mIsLeIsochronousBroadcasterSupported;
+    }
+
+    /**
      * @return the getLeMaximumAdvertisingDataLength
      */
     int getLeMaximumAdvertisingDataLength() {
@@ -982,6 +998,8 @@
                 ((0xFF & ((int) val[23])) << 8) + (0xFF & ((int) val[22]));
         mIsLePeriodicAdvertisingSyncTransferSenderSupported = ((0xFF & ((int) val[24])) != 0);
         mIsLeConnectedIsochronousStreamCentralSupported = ((0xFF & ((int) val[25])) != 0);
+        mIsLeIsochronousBroadcasterSupported = ((0xFF & ((int) val[26])) != 0);
+        mIsLePeriodicAdvertisingSyncTransferRecipientSupported = ((0xFF & ((int) val[27])) != 0);
 
         Log.d(TAG, "BT_PROPERTY_LOCAL_LE_FEATURES: update from BT controller"
                 + " mNumOfAdvertisementInstancesSupported = "
@@ -1005,7 +1023,11 @@
                 + " mIsLePeriodicAdvertisingSyncTransferSenderSupported = "
                 + mIsLePeriodicAdvertisingSyncTransferSenderSupported
                 + " mIsLeConnectedIsochronousStreamCentralSupported = "
-                + mIsLeConnectedIsochronousStreamCentralSupported);
+                + mIsLeConnectedIsochronousStreamCentralSupported
+                + " mIsLeIsochronousBroadcasterSupported = "
+                + mIsLeIsochronousBroadcasterSupported
+                + " mIsLePeriodicAdvertisingSyncTransferRecipientSupported = "
+                + mIsLePeriodicAdvertisingSyncTransferRecipientSupported);
         //invalidateIsOffloadedFilteringSupportedCache();
     }
 
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
index 66108af..0780ee9 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
@@ -2457,13 +2457,27 @@
         }
 
         @Override
-        public int isLePeriodicAdvertisingSyncTransferSenderSupported() {
+        public int isLeAudioBroadcastSourceSupported() {
             AdapterService service = getService();
             if (service == null) {
                 return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
             }
 
-            if (service.mAdapterProperties.isLePeriodicAdvertisingSyncTransferSenderSupported()) {
+            if (service.isLeAudioBroadcastSourceSupported()) {
+                return BluetoothStatusCodes.SUCCESS;
+            }
+
+            return BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED;
+        }
+
+        @Override
+        public int isLeAudioBroadcastAssistantSupported() {
+            AdapterService service = getService();
+            if (service == null) {
+                return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+            }
+
+            if (service.isLeAudioBroadcastAssistantSupported()) {
                 return BluetoothStatusCodes.SUCCESS;
             }
 
@@ -3474,18 +3488,35 @@
         return mAdapterProperties.isLePeriodicAdvertisingSupported();
     }
 
+    /**
+     * Check if the LE audio broadcast source feature is supported.
+     *
+     * @return true, if the LE audio broadcast source is supported
+     */
+    public boolean isLeAudioBroadcastSourceSupported() {
+        //TODO: check the profile support status as well after we have the implementation
+        return mAdapterProperties.isLePeriodicAdvertisingSupported()
+                && mAdapterProperties.isLeExtendedAdvertisingSupported()
+                && mAdapterProperties.isLeIsochronousBroadcasterSupported();
+    }
+
+    /**
+     * Check if the LE audio broadcast assistant feature is supported.
+     *
+     * @return true, if the LE audio broadcast assistant is supported
+     */
+    public boolean isLeAudioBroadcastAssistantSupported() {
+        //TODO: check the profile support status as well after we have the implementation
+        return mAdapterProperties.isLePeriodicAdvertisingSupported()
+            && mAdapterProperties.isLeExtendedAdvertisingSupported()
+            && (mAdapterProperties.isLePeriodicAdvertisingSyncTransferSenderSupported()
+                || mAdapterProperties.isLePeriodicAdvertisingSyncTransferRecipientSupported());
+    }
+
     public int getLeMaximumAdvertisingDataLength() {
         return mAdapterProperties.getLeMaximumAdvertisingDataLength();
     }
 
-    public boolean isLePeriodicAdvertisingSyncTransferSenderSupported() {
-        return mAdapterProperties.isLePeriodicAdvertisingSyncTransferSenderSupported();
-    }
-
-    public boolean isLeConnectedIsochronousStreamCentralSupported() {
-        return mAdapterProperties.isLeConnectedIsochronousStreamCentralSupported();
-    }
-
     /**
      * Get the maximum number of connected audio devices.
      *
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java
index f94ee85..b70d268 100644
--- a/framework/java/android/bluetooth/BluetoothAdapter.java
+++ b/framework/java/android/bluetooth/BluetoothAdapter.java
@@ -2325,28 +2325,54 @@
     }
 
     /**
-     * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Periodic Advertising Sync Transfer Sender
-     * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the
-     * feature is not supported or an error code
+     * Returns {@link BluetoothStatusCodes#SUCCESS} if the LE audio broadcast source
+     * feature is supported, {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the
+     * feature is not supported, or an error code.
      *
-     * @return whether the chipset supports the LE Periodic Advertising Sync Transfer Sender feature
+     * @return whether the LE audio broadcast source is supported
      */
     @RequiresNoPermission
-    public @LeFeatureReturnValues int isLePeriodicAdvertisingSyncTransferSenderSupported() {
-        if (!getLeAccess()) {
-            return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+    public @LeFeatureReturnValues int isLeAudioBroadcastSourceSupported() {
+      if (!getLeAccess()) {
+        return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+      }
+      try {
+        mServiceLock.readLock().lock();
+        if (mService != null) {
+          return mService.isLeAudioBroadcastSourceSupported();
         }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.isLePeriodicAdvertisingSyncTransferSenderSupported();
-            }
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        } finally {
-            mServiceLock.readLock().unlock();
+      } catch (RemoteException e) {
+        e.rethrowFromSystemServer();
+      } finally {
+        mServiceLock.readLock().unlock();
+      }
+
+      return BluetoothStatusCodes.ERROR_UNKNOWN;
+    }
+
+    /**
+     * Returns {@link BluetoothStatusCodes#SUCCESS} if the LE audio broadcast assistant
+     * feature is supported, {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the
+     * feature is not supported, or an error code.
+     *
+     * @return whether the LE audio broadcast assistent is supported
+     */
+    @RequiresNoPermission
+    public @LeFeatureReturnValues int isLeAudioBroadcastAssistantSupported() {
+      if (!getLeAccess()) {
+        return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+      }
+      try {
+        mServiceLock.readLock().lock();
+        if (mService != null) {
+          return mService.isLeAudioBroadcastAssistantSupported();
         }
-        return BluetoothStatusCodes.ERROR_UNKNOWN;
+      } catch (RemoteException e) {
+        e.rethrowFromSystemServer();
+      } finally {
+        mServiceLock.readLock().unlock();
+      }
+      return BluetoothStatusCodes.ERROR_UNKNOWN;
     }
 
     /**
diff --git a/system/binder/android/bluetooth/IBluetooth.aidl b/system/binder/android/bluetooth/IBluetooth.aidl
index 956159e..97e2c59 100644
--- a/system/binder/android/bluetooth/IBluetooth.aidl
+++ b/system/binder/android/bluetooth/IBluetooth.aidl
@@ -198,7 +198,9 @@
     @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission")
     int isLeAudioSupported();
     @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission")
-    int isLePeriodicAdvertisingSyncTransferSenderSupported();
+    int isLeAudioBroadcastSourceSupported();
+    @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission")
+    int isLeAudioBroadcastAssistantSupported();
     @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission")
     int getLeMaximumAdvertisingDataLength();
 
diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc
index 28336dc..87dd06b 100644
--- a/system/btif/src/btif_core.cc
+++ b/system/btif/src/btif_core.cc
@@ -622,6 +622,11 @@
         controller->supports_ble_periodic_advertising_sync_transfer_sender();
     local_le_features.le_connected_isochronous_stream_central_supported =
         controller->supports_ble_connected_isochronous_stream_central();
+    local_le_features.le_isochronous_broadcast_supported =
+        controller->supports_ble_isochronous_broadcaster();
+    local_le_features
+        .le_periodic_advertising_sync_transfer_recipient_supported =
+        controller->supports_ble_periodic_advertising_sync_transfer_recipient();
     memcpy(prop.val, &local_le_features, prop.len);
   } else if (prop.type == BT_PROPERTY_DYNAMIC_AUDIO_BUFFER) {
     tBTM_BLE_VSC_CB cmn_vsc_cb;
diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h
index 45321db..c174d91 100644
--- a/system/include/hardware/bluetooth.h
+++ b/system/include/hardware/bluetooth.h
@@ -207,6 +207,8 @@
   uint32_t dynamic_audio_buffer_supported;
   bool le_periodic_advertising_sync_transfer_sender_supported;
   bool le_connected_isochronous_stream_central_supported;
+  bool le_isochronous_broadcast_supported;
+  bool le_periodic_advertising_sync_transfer_recipient_supported;
 } bt_local_le_features_t;
 
 /* Stored the default/maximum/minimum buffer time for dynamic audio buffer.