Implement Direct Channel Tests

Implements Direct Channel tests for Sensors HAL 2.0. The tests verify
that the interface has been implemented correctly and that expected
values are returned. These tests are not intended to verify that the
rate at which sensor events are generated is correct.

Also, correctly return -1 as the channel handle if direct report is
not supported.

Bug: 115969174
Test: Tests pass against default implementation
Change-Id: I31b3211268701665757b03d5ee4ba2316f461282
diff --git a/sensors/2.0/default/Sensors.cpp b/sensors/2.0/default/Sensors.cpp
index 4346ee1..75030e0 100644
--- a/sensors/2.0/default/Sensors.cpp
+++ b/sensors/2.0/default/Sensors.cpp
@@ -133,7 +133,7 @@
 
 Return<void> Sensors::registerDirectChannel(const SharedMemInfo& /* mem */,
                                             registerDirectChannel_cb _hidl_cb) {
-    _hidl_cb(Result::INVALID_OPERATION, 0 /* channelHandle */);
+    _hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */);
     return Return<void>();
 }
 
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index cc78af3..ac020ad 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -18,6 +18,7 @@
 
 #include "SensorsHidlEnvironmentV2_0.h"
 #include "sensors-vts-utils/SensorsHidlTestBase.h"
+#include "sensors-vts-utils/SensorsTestSharedMemory.h"
 
 #include <android/hardware/sensors/2.0/ISensors.h>
 #include <android/hardware/sensors/2.0/types.h>
@@ -26,6 +27,7 @@
 
 #include <cinttypes>
 #include <condition_variable>
+#include <cstring>
 #include <map>
 #include <vector>
 
@@ -34,7 +36,9 @@
 using ::android::hardware::Void;
 using ::android::hardware::sensors::V1_0::MetaDataEventType;
 using ::android::hardware::sensors::V1_0::OperationMode;
+using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
 using ::android::hardware::sensors::V1_0::SensorStatus;
+using ::android::hardware::sensors::V1_0::SharedMemType;
 using ::android::hardware::sensors::V1_0::Vec3;
 
 class EventCallback : public IEventCallback {
@@ -166,6 +170,15 @@
     std::vector<SensorInfo> getOneShotSensors();
     std::vector<SensorInfo> getInjectEventSensors();
     int32_t getInvalidSensorHandle();
+    void verifyDirectChannel(SharedMemType memType);
+    void verifyRegisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
+                                     std::shared_ptr<SensorsTestSharedMemory> mem,
+                                     int32_t* directChannelHandle);
+    void verifyConfigure(const SensorInfo& sensor, SharedMemType memType,
+                         int32_t directChannelHandle);
+    void verifyUnregisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
+                                       int32_t directChannelHandle);
+    void checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, RateLevel rateLevel);
 };
 
 Return<Result> SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) {
@@ -808,6 +821,128 @@
     getEnvironment()->unregisterCallback();
 }
 
+void SensorsHidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle,
+                                     RateLevel rateLevel) {
+    configDirectReport(sensor.sensorHandle, directChannelHandle, rateLevel,
+                       [&](Result result, int32_t reportToken) {
+                           if (isDirectReportRateSupported(sensor, rateLevel)) {
+                               ASSERT_EQ(result, Result::OK);
+                               ASSERT_GT(reportToken, 0);
+                           } else {
+                               ASSERT_EQ(result, Result::BAD_VALUE);
+                           }
+                       });
+}
+
+void SensorsHidlTest::verifyRegisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
+                                                  std::shared_ptr<SensorsTestSharedMemory> mem,
+                                                  int32_t* directChannelHandle) {
+    char* buffer = mem->getBuffer();
+    memset(buffer, 0xff, mem->getSize());
+
+    registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) {
+        if (isDirectChannelTypeSupported(sensor, memType)) {
+            ASSERT_EQ(result, Result::OK);
+            ASSERT_GT(channelHandle, 0);
+
+            // Verify that the memory has been zeroed
+            for (size_t i = 0; i < mem->getSize(); i++) {
+                ASSERT_EQ(buffer[i], 0x00);
+            }
+        } else {
+            ASSERT_EQ(result, Result::INVALID_OPERATION);
+            ASSERT_EQ(channelHandle, -1);
+        }
+        *directChannelHandle = channelHandle;
+    });
+}
+
+void SensorsHidlTest::verifyConfigure(const SensorInfo& sensor, SharedMemType memType,
+                                      int32_t directChannelHandle) {
+    if (isDirectChannelTypeSupported(sensor, memType)) {
+        // Verify that each rate level is properly supported
+        checkRateLevel(sensor, directChannelHandle, RateLevel::NORMAL);
+        checkRateLevel(sensor, directChannelHandle, RateLevel::FAST);
+        checkRateLevel(sensor, directChannelHandle, RateLevel::VERY_FAST);
+        checkRateLevel(sensor, directChannelHandle, RateLevel::STOP);
+
+        // Verify that a sensor handle of -1 is only acceptable when using RateLevel::STOP
+        configDirectReport(
+            -1 /* sensorHandle */, directChannelHandle, RateLevel::NORMAL,
+            [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::BAD_VALUE); });
+        configDirectReport(
+            -1 /* sensorHandle */, directChannelHandle, RateLevel::STOP,
+            [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); });
+    } else {
+        // Direct channel is not supported for this SharedMemType
+        configDirectReport(sensor.sensorHandle, directChannelHandle, RateLevel::NORMAL,
+                           [](Result result, int32_t /* reportToken */) {
+                               ASSERT_EQ(result, Result::INVALID_OPERATION);
+                           });
+    }
+}
+
+void SensorsHidlTest::verifyUnregisterDirectChannel(const SensorInfo& sensor, SharedMemType memType,
+                                                    int32_t directChannelHandle) {
+    Result result = unregisterDirectChannel(directChannelHandle);
+    if (isDirectChannelTypeSupported(sensor, memType)) {
+        ASSERT_EQ(result, Result::OK);
+    } else {
+        ASSERT_EQ(result, Result::INVALID_OPERATION);
+    }
+}
+
+void SensorsHidlTest::verifyDirectChannel(SharedMemType memType) {
+    constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
+    constexpr size_t kNumEvents = 1;
+    constexpr size_t kMemSize = kNumEvents * kEventSize;
+
+    std::shared_ptr<SensorsTestSharedMemory> mem(
+        SensorsTestSharedMemory::create(memType, kMemSize));
+    ASSERT_NE(mem, nullptr);
+
+    for (const SensorInfo& sensor : getSensorsList()) {
+        int32_t directChannelHandle = 0;
+        verifyRegisterDirectChannel(sensor, memType, mem, &directChannelHandle);
+        verifyConfigure(sensor, memType, directChannelHandle);
+        verifyUnregisterDirectChannel(sensor, memType, directChannelHandle);
+    }
+}
+
+TEST_F(SensorsHidlTest, DirectChannelAshmem) {
+    verifyDirectChannel(SharedMemType::ASHMEM);
+}
+
+TEST_F(SensorsHidlTest, DirectChannelGralloc) {
+    verifyDirectChannel(SharedMemType::GRALLOC);
+}
+
+TEST_F(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) {
+    for (const SensorInfo& sensor : getSensorsList()) {
+        if (isDirectChannelTypeSupported(sensor, SharedMemType::ASHMEM) ||
+            isDirectChannelTypeSupported(sensor, SharedMemType::GRALLOC)) {
+            // Find a supported rate level
+            RateLevel rate = RateLevel::STOP;
+            if (isDirectReportRateSupported(sensor, RateLevel::NORMAL)) {
+                rate = RateLevel::NORMAL;
+            } else if (isDirectReportRateSupported(sensor, RateLevel::FAST)) {
+                rate = RateLevel::FAST;
+            } else if (isDirectReportRateSupported(sensor, RateLevel::VERY_FAST)) {
+                rate = RateLevel::VERY_FAST;
+            }
+
+            // Ensure that at least one rate level is supported
+            ASSERT_NE(rate, RateLevel::STOP);
+
+            // Verify that an invalid channel handle produces a BAD_VALUE result
+            configDirectReport(sensor.sensorHandle, -1, rate,
+                               [](Result result, int32_t /* reportToken */) {
+                                   ASSERT_EQ(result, Result::BAD_VALUE);
+                               });
+        }
+    }
+}
+
 int main(int argc, char** argv) {
     ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV2_0::Instance());
     ::testing::InitGoogleTest(&argc, argv);
diff --git a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
index 5096498..819e297 100644
--- a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
+++ b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
@@ -35,6 +35,10 @@
     return mBuffer;
 }
 
+size_t SensorsTestSharedMemory::getSize() const {
+    return mSize;
+}
+
 std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const {
     constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
     constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD);
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
index 055b8e7..002f42c 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
@@ -33,6 +33,7 @@
     static SensorsTestSharedMemory* create(SharedMemType type, size_t size);
     SharedMemInfo getSharedMemInfo() const;
     char* getBuffer() const;
+    size_t getSize() const;
     std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const;
     virtual ~SensorsTestSharedMemory();