Merge "Add support for LE audio capability detection" into main
diff --git a/modules/sensors/dynamic_sensor/Android.bp b/modules/sensors/dynamic_sensor/Android.bp
index b86b1db..b6e0020 100644
--- a/modules/sensors/dynamic_sensor/Android.bp
+++ b/modules/sensors/dynamic_sensor/Android.bp
@@ -35,9 +35,17 @@
     export_include_dirs: ["."],
 
     shared_libs: [
+        "libbase",
         "libhidparser",
+        "server_configurable_flags",
     ],
 
+    static_libs: [
+        "dynamic_sensors_flags_c_lib",
+    ],
+
+    cpp_std: "c++20",
+
     target: {
         android: {
             srcs: [
@@ -53,12 +61,12 @@
                 "RingBuffer.cpp",
             ],
             shared_libs: [
-                "libbase",
                 "libcutils",
                 "liblog",
                 "libutils",
             ],
             header_libs: [
+                "libbase_headers",
                 "libhardware_headers",
                 "libstagefright_foundation_headers",
             ],
diff --git a/modules/sensors/dynamic_sensor/DynamicSensorsSubHal.cpp b/modules/sensors/dynamic_sensor/DynamicSensorsSubHal.cpp
index d5a9b3c..101b983 100644
--- a/modules/sensors/dynamic_sensor/DynamicSensorsSubHal.cpp
+++ b/modules/sensors/dynamic_sensor/DynamicSensorsSubHal.cpp
@@ -118,7 +118,7 @@
     sensors[0].sensorHandle = sensor_info.handle;
     sensors[0].name = sensor_info.name;
     sensors[0].vendor = sensor_info.vendor;
-    sensors[0].version = 1;
+    sensors[0].version = sensor_info.version;
     sensors[0].type = static_cast<SensorType>(sensor_info.type);
     sensors[0].typeAsString = sensor_info.stringType;
     sensors[0].maxRange = sensor_info.maxRange;
@@ -210,7 +210,7 @@
     sensor_list[0].sensorHandle = handle;
     sensor_list[0].name = sensor_info->name;
     sensor_list[0].vendor = sensor_info->vendor;
-    sensor_list[0].version = 1;
+    sensor_list[0].version = sensor_info->version;
     sensor_list[0].type = static_cast<SensorType>(sensor_info->type);
     sensor_list[0].typeAsString = sensor_info->stringType;
     sensor_list[0].maxRange = sensor_info->maxRange;
diff --git a/modules/sensors/dynamic_sensor/HidRawSensor.cpp b/modules/sensors/dynamic_sensor/HidRawSensor.cpp
index c90f4f1..57df74d 100644
--- a/modules/sensors/dynamic_sensor/HidRawSensor.cpp
+++ b/modules/sensors/dynamic_sensor/HidRawSensor.cpp
@@ -16,7 +16,9 @@
 #include "HidRawSensor.h"
 #include "HidSensorDef.h"
 
+#include <android-base/properties.h>
 #include <utils/Errors.h>
+#include <com_android_libhardware_dynamic_sensors_flags.h>
 #include "HidLog.h"
 
 #include <HidUtils.h>
@@ -30,15 +32,20 @@
 namespace android {
 namespace SensorHalExt {
 
+using ::android::base::GetProperty;
+
+namespace dynamic_sensors_flags = com::android::libhardware::dynamic::sensors::flags;
+
 namespace {
 const std::string CUSTOM_TYPE_PREFIX("com.google.hardware.sensor.hid_dynamic.");
+
 }
 
 HidRawSensor::HidRawSensor(
         SP(HidDevice) device, uint32_t usage, const std::vector<HidParser::ReportPacket> &packets)
-        : mReportingStateId(-1), mPowerStateId(-1), mReportIntervalId(-1), mInputReportId(-1),
-        mEnabled(false), mSamplingPeriod(1000LL*1000*1000), mBatchingPeriod(0),
-        mDevice(device), mValid(false) {
+        : mReportingStateId(-1), mPowerStateId(-1), mReportIntervalId(-1), mLeTransportId(-1),
+        mRequiresLeTransport(false), mInputReportId(-1), mEnabled(false),
+        mSamplingPeriod(1000LL*1000*1000), mBatchingPeriod(0), mDevice(device), mValid(false) {
     if (device == nullptr) {
         return;
     }
@@ -631,10 +638,35 @@
 
 bool HidRawSensor::detectAndroidHeadTrackerSensor(
         const std::string &description) {
-    if (description.find("#AndroidHeadTracker#1.") != 0) {
+    bool leAudioFlagEnabled = dynamic_sensors_flags::dynamic_sensors_le_audio();
+    LOG_I << "detectAndroidHeadTrackerSensor: " << description << LOG_ENDL;
+    if (!description.starts_with("#AndroidHeadTracker#1.")
+        && (!leAudioFlagEnabled || !description.starts_with("#AndroidHeadTracker#2."))) {
         return false;
     }
 
+    // #AndroidHeadTracker#<major version>.<minor version>#<capability>
+    // We encode the major, minor, and capabilities in the following format:
+    // 0xMMmmcccc (Major, minor, capability bits)
+    if (leAudioFlagEnabled) {
+        uint32_t majorVersion = 0, minorVersion = 0, capability = 0;
+        mFeatureInfo.version = 0;
+        int ret = sscanf(description.c_str(), "#AndroidHeadTracker#%d.%d#%d",
+                        &majorVersion, &minorVersion, &capability);
+        if (ret > 0) {
+            mRequiresLeTransport = (majorVersion == kLeAudioCapabilitiesMajorVersion);
+            mFeatureInfo.version = (majorVersion & 0xFF) << 24;
+        }
+        if (ret > 1) {
+            mFeatureInfo.version |= (minorVersion & 0xFF) << 16;
+        }
+        if (ret > 2) {
+            mFeatureInfo.version |= (capability & 0xFFFF);
+        }
+    } else {
+        mFeatureInfo.version = 1;
+    }
+
     mFeatureInfo.type = SENSOR_TYPE_HEAD_TRACKER;
     mFeatureInfo.typeString = SENSOR_STRING_TYPE_HEAD_TRACKER;
     mFeatureInfo.reportModeFlag = SENSOR_FLAG_CONTINUOUS_MODE;
@@ -904,8 +936,23 @@
         mFeatureInfo.maxDelay = std::min(static_cast<int64_t>(1000000000),
                                          mFeatureInfo.maxDelay);
     }
-    return true;
-    return (mPowerStateId >= 0 || mReportingStateId >= 0) && mReportIntervalId >= 0;
+
+    bool leTransportExpected = mRequiresLeTransport;
+    if (leTransportExpected) {
+        //VENDOR_LE_TRANSPORT
+        const HidParser::ReportItem *leTransport
+                = find(packets, VENDOR_LE_TRANSPORT, HidParser::REPORT_TYPE_FEATURE);
+        if (leTransport == nullptr) {
+            LOG_W << "Cannot find valid LE transport feature" << LOG_ENDL;
+        } else {
+            mLeTransportId = leTransport->id;
+            mLeTransportBitOffset = leTransport->bitOffset;
+            mLeTransportBitSize = leTransport->bitSize;
+        }
+    }
+
+    return (mPowerStateId >= 0 || mReportingStateId >= 0) && mReportIntervalId >= 0 &&
+           (!leTransportExpected || mLeTransportId >= 0);
 }
 
 const sensor_t* HidRawSensor::getSensor() const {
@@ -928,6 +975,51 @@
     }
 
     std::vector<uint8_t> buffer;
+    // TODO(b/298450041): Refactor the operations below in a separate function.
+    bool setLeAudioTransportOk = true;
+    if (mLeTransportId >= 0) {
+        setLeAudioTransportOk = false;
+        uint8_t id = static_cast<uint8_t>(mLeTransportId);
+        if (device->getFeature(id, &buffer)
+                && (8 * buffer.size()) >=
+                        (mLeTransportBitOffset + mLeTransportBitSize)) {
+            constexpr uint8_t kLeAclValue = 0;
+            constexpr uint8_t kLeIsoValue = 1;
+
+            // The following property, if defined, represents a comma-separated list of
+            // transport preferences for the following types: le-acl or iso-[sw|hw],
+            // which describes the priority list of transport selections used based on the
+            // capabilities reported by the HID device.
+            std::string prop = GetProperty("bluetooth.core.le.dsa_transport_preference", "");
+            std::istringstream tokenStream(prop);
+            std::string line;
+            std::vector<std::string> priorityList;
+            while (std::getline(tokenStream, line, ',')) {
+                priorityList.push_back(line);
+            }
+
+            uint16_t capability = mFeatureInfo.version & 0x0000FFFF;
+            uint8_t value;
+            if (capability == (kIsoBitMask | kAclBitMask)) {
+                if (!priorityList.empty() && priorityList[0].compare("le-acl") == 0) {
+                    value = kLeAclValue;
+                } else {
+                    value = kLeIsoValue;
+                }
+            } else {
+                value = (capability & kIsoBitMask) ? kLeIsoValue : kLeAclValue;
+            }
+            HidUtil::copyBits(&value, &(buffer[0]), buffer.size(), 0,
+                              mLeTransportBitOffset, mLeTransportBitSize);
+            setLeAudioTransportOk = device->setFeature(id, buffer);
+            if (!setLeAudioTransportOk) {
+              LOG_E << "enable: setFeature VENDOR LE TRANSPORT failed" << LOG_ENDL;
+            }
+        } else {
+            LOG_E << "enable: changing VENDOR LE TRANSPORT failed" << LOG_ENDL;
+        }
+    }
+
     bool setPowerOk = true;
     if (mPowerStateId >= 0) {
         setPowerOk = false;
@@ -939,6 +1031,9 @@
             HidUtil::copyBits(&index, &(buffer[0]), buffer.size(),
                               0, mPowerStateBitOffset, mPowerStateBitSize);
             setPowerOk = device->setFeature(id, buffer);
+            if (!setPowerOk) {
+              LOG_E << "enable: setFeature POWER STATE failed" << LOG_ENDL;
+            }
         } else {
             LOG_E << "enable: changing POWER STATE failed" << LOG_ENDL;
         }
@@ -956,12 +1051,15 @@
             HidUtil::copyBits(&index, &(buffer[0]), buffer.size(),0,
                               mReportingStateBitOffset, mReportingStateBitSize);
             setReportingOk = device->setFeature(id, buffer);
+            if (!setReportingOk) {
+              LOG_E << "enable: setFeature REPORTING STATE failed" << LOG_ENDL;
+            }
         } else {
             LOG_E << "enable: changing REPORTING STATE failed" << LOG_ENDL;
         }
     }
 
-    if (setPowerOk && setReportingOk) {
+    if (setPowerOk && setReportingOk && setLeAudioTransportOk) {
         mEnabled = enable;
         return NO_ERROR;
     } else {
@@ -1100,6 +1198,7 @@
     std::ostringstream ss;
     ss << "Feature Values " << LOG_ENDL
           << "  name: " << mFeatureInfo.name << LOG_ENDL
+          << "  version: 0x" << std::setfill('0') << std::setw(8) << std::hex << mFeatureInfo.version << LOG_ENDL
           << "  vendor: " << mFeatureInfo.vendor << LOG_ENDL
           << "  permission: " << mFeatureInfo.permission << LOG_ENDL
           << "  typeString: " << mFeatureInfo.typeString << LOG_ENDL
diff --git a/modules/sensors/dynamic_sensor/HidRawSensor.h b/modules/sensors/dynamic_sensor/HidRawSensor.h
index e4564a0..3d2d94d 100644
--- a/modules/sensors/dynamic_sensor/HidRawSensor.h
+++ b/modules/sensors/dynamic_sensor/HidRawSensor.h
@@ -200,6 +200,11 @@
     double mReportIntervalScale;
     int64_t mReportIntervalOffset;
 
+    int mLeTransportId;
+    unsigned int mLeTransportBitOffset;
+    unsigned int mLeTransportBitSize;
+    bool mRequiresLeTransport;
+
     // Input report translate table
     std::vector<ReportTranslateRecord> mTranslateTable;
     unsigned mInputReportId;
@@ -214,6 +219,20 @@
 
     WP(HidDevice) mDevice;
     bool mValid;
+
+    /**
+     * The first major version which LE audio capabilities are encoded.
+     * For this version, we expect the HID descriptor to be the following format:
+     * #AndroidHeadTracker#<major version>.<minor version>#<capability>
+     * where capability is an integer that defines where LE audio supported
+     * transports are indicated:
+     * - 1: ACL
+     * - 2: ISO
+     * - 3: ACL + ISO
+     */
+    const uint8_t kLeAudioCapabilitiesMajorVersion = 2;
+    const uint8_t kAclBitMask = 0x1;
+    const uint8_t kIsoBitMask = 0x2;
 };
 
 } // namespace SensorHalExt
diff --git a/modules/sensors/dynamic_sensor/HidSensorDef.h b/modules/sensors/dynamic_sensor/HidSensorDef.h
index 8f47a85..30c2f88 100644
--- a/modules/sensors/dynamic_sensor/HidSensorDef.h
+++ b/modules/sensors/dynamic_sensor/HidSensorDef.h
@@ -42,6 +42,7 @@
     SENSOR_MODEL = 0x200306,
     SENSOR_SERIAL_NUMBER = 0x200307,
     SENSOR_STATUS = 0x200303,
+    VENDOR_LE_TRANSPORT = 0x20F410,
 };
 } // nsmespace PropertyUsage
 
diff --git a/modules/sensors/dynamic_sensor/dynamic_sensors.aconfig b/modules/sensors/dynamic_sensor/dynamic_sensors.aconfig
index 740c9e4..dc312c0 100644
--- a/modules/sensors/dynamic_sensor/dynamic_sensors.aconfig
+++ b/modules/sensors/dynamic_sensor/dynamic_sensors.aconfig
@@ -1,7 +1,7 @@
 package: "com.android.libhardware.dynamic.sensors.flags"
 
 flag {
-  name: "sensors_dynamic_sensors_le_audio"
+  name: "dynamic_sensors_le_audio"
   namespace: "sensors"
   description: "This flag controls the enablement of LE audio support on dynamic sensors"
   bug: "298450041"