From dc7a8e7898a443b59beb0ee22bd387b1f53a0730 Mon Sep 17 00:00:00 2001 From: Stan Rokita Date: Fri, 23 Aug 2019 12:35:40 -0700 Subject: [PATCH] MultiHal 2.0 - Get sensors list from subhals Implement SubHal constructors. The default ctor will get the SubHal object pointers from dynamic libraries. The test ctor will take a vector of SubHal objects. Implment the HalProxy getSensorsList method which will return all the sensors from the subhal objects. Create one unit test for getSensorsList as well. Bug: 136511617 Test: Flashed onto device and observed proper logs for both test subhals. Also, passed getSensorsList test. Change-Id: I6e8ca4883c50daabbd7b0955d3664f66b6cd74bf --- sensors/2.0/multihal/HalProxy.cpp | 94 ++++++++++++------- sensors/2.0/multihal/include/HalProxy.h | 24 ++++- sensors/2.0/multihal/include/SubHal.h | 1 + sensors/2.0/multihal/tests/Android.bp | 2 +- sensors/2.0/multihal/tests/HalProxy_test.cpp | 60 +++++++++++- .../tests/fake_subhal/SensorsSubHal.cpp | 53 +++++++---- .../tests/fake_subhal/SensorsSubHal.h | 23 ++++- 7 files changed, 199 insertions(+), 58 deletions(-) diff --git a/sensors/2.0/multihal/HalProxy.cpp b/sensors/2.0/multihal/HalProxy.cpp index dcdccac2be..d8bde8354c 100644 --- a/sensors/2.0/multihal/HalProxy.cpp +++ b/sensors/2.0/multihal/HalProxy.cpp @@ -70,42 +70,12 @@ class SensorsCallbackProxy : public ISensorsCallback { HalProxy::HalProxy() { const char* kMultiHalConfigFilePath = "/vendor/etc/sensors/hals.conf"; - std::ifstream subHalConfigStream(kMultiHalConfigFilePath); - if (!subHalConfigStream) { - LOG_FATAL("Failed to load subHal config file: %s", kMultiHalConfigFilePath); - } else { - std::string subHalLibraryFile; - while (subHalConfigStream >> subHalLibraryFile) { - void* handle = dlopen(subHalLibraryFile.c_str(), RTLD_NOW); - if (handle == nullptr) { - LOG_FATAL("dlopen failed for library: %s", subHalLibraryFile.c_str()); - } else { - SensorsHalGetSubHalFunc* sensorsHalGetSubHalPtr = - (SensorsHalGetSubHalFunc*)dlsym(handle, "sensorsHalGetSubHal"); - if (sensorsHalGetSubHalPtr == nullptr) { - LOG_FATAL("Failed to locate sensorsHalGetSubHal function for library: %s", - subHalLibraryFile.c_str()); - } else { - std::function sensorsHalGetSubHal = - *sensorsHalGetSubHalPtr; - uint32_t version; - ISensorsSubHal* subHal = sensorsHalGetSubHal(&version); - if (version != SUB_HAL_2_0_VERSION) { - LOG_FATAL("SubHal version was not 2.0 for library: %s", - subHalLibraryFile.c_str()); - } else { - ALOGI("Loaded SubHal from library: %s", subHalLibraryFile.c_str()); - mSubHalList.push_back(subHal); - } - } - } - } - } - // TODO: Discover sensors + initializeSubHalListFromConfigFile(kMultiHalConfigFilePath); + initializeSensorList(); } HalProxy::HalProxy(std::vector& subHalList) : mSubHalList(subHalList) { - // TODO: Perform the same steps as the empty constructor. + initializeSensorList(); } HalProxy::~HalProxy() { @@ -113,8 +83,8 @@ HalProxy::~HalProxy() { // state. } -Return HalProxy::getSensorsList(getSensorsList_cb /* _hidl_cb */) { - // TODO: Output sensors list created as part of HalProxy(). +Return HalProxy::getSensorsList(getSensorsList_cb _hidl_cb) { + _hidl_cb(mSensorList); return Void(); } @@ -217,6 +187,60 @@ Return HalProxy::onDynamicSensorsDisconnected( return Return(); } +void HalProxy::initializeSubHalListFromConfigFile(const char* configFileName) { + std::ifstream subHalConfigStream(configFileName); + if (!subHalConfigStream) { + LOG_FATAL("Failed to load subHal config file: %s", configFileName); + } else { + std::string subHalLibraryFile; + while (subHalConfigStream >> subHalLibraryFile) { + void* handle = dlopen(subHalLibraryFile.c_str(), RTLD_NOW); + if (handle == nullptr) { + LOG_FATAL("dlopen failed for library: %s", subHalLibraryFile.c_str()); + } else { + SensorsHalGetSubHalFunc* sensorsHalGetSubHalPtr = + (SensorsHalGetSubHalFunc*)dlsym(handle, "sensorsHalGetSubHal"); + if (sensorsHalGetSubHalPtr == nullptr) { + LOG_FATAL("Failed to locate sensorsHalGetSubHal function for library: %s", + subHalLibraryFile.c_str()); + } else { + std::function sensorsHalGetSubHal = + *sensorsHalGetSubHalPtr; + uint32_t version; + ISensorsSubHal* subHal = sensorsHalGetSubHal(&version); + if (version != SUB_HAL_2_0_VERSION) { + LOG_FATAL("SubHal version was not 2.0 for library: %s", + subHalLibraryFile.c_str()); + } else { + ALOGV("Loaded SubHal from library: %s", subHalLibraryFile.c_str()); + mSubHalList.push_back(subHal); + } + } + } + } + } +} + +void HalProxy::initializeSensorList() { + for (size_t subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) { + ISensorsSubHal* subHal = mSubHalList[subHalIndex]; + auto result = subHal->getSensorsList([&](const auto& list) { + for (SensorInfo sensor : list) { + if ((sensor.sensorHandle & 0xFF000000) != 0) { + ALOGE("SubHal sensorHandle's first byte was not 0"); + } else { + ALOGV("Loaded sensor: %s", sensor.name.c_str()); + sensor.sensorHandle |= (subHalIndex << 24); + mSensorList.push_back(sensor); + } + } + }); + if (!result.isOk()) { + ALOGE("getSensorsList call failed for SubHal: %s", subHal->getName().c_str()); + } + } +} + ISensorsSubHal* HalProxy::getSubHalForSensorHandle(uint32_t sensorHandle) { return mSubHalList[static_cast(sensorHandle >> 24)]; } diff --git a/sensors/2.0/multihal/include/HalProxy.h b/sensors/2.0/multihal/include/HalProxy.h index 809d07e98b..b0261c8c7d 100644 --- a/sensors/2.0/multihal/include/HalProxy.h +++ b/sensors/2.0/multihal/include/HalProxy.h @@ -39,7 +39,8 @@ using ::android::hardware::MQDescriptor; using ::android::hardware::Return; using ::android::hardware::Void; -struct HalProxy : public ISensors { +class HalProxy : public ISensors { + public: using Event = ::android::hardware::sensors::V1_0::Event; using OperationMode = ::android::hardware::sensors::V1_0::OperationMode; using RateLevel = ::android::hardware::sensors::V1_0::RateLevel; @@ -119,6 +120,27 @@ struct HalProxy : public ISensors { */ std::vector mSubHalList; + /** + * List of SensorInfo objects that contains the sensor info from subhals as + * well as the modified sensor handle for the framework. + * + * The subhal index is encoded in the first byte of the sensor handle and + * the remaining bytes are generated by the subhal. + */ + std::vector mSensorList; + + /** + * Initialize the list of SubHal objects in mSubHalList by reading from dynamic libraries + * listed in a config file. + */ + void initializeSubHalListFromConfigFile(const char* configFileName); + + /** + * Initialize the list of SensorInfo objects in mSensorList by getting sensors from each + * subhal. + */ + void initializeSensorList(); + /* * Get the subhal pointer which can be found by indexing into the mSubHalList vector * using the index from the first byte of sensorHandle. diff --git a/sensors/2.0/multihal/include/SubHal.h b/sensors/2.0/multihal/include/SubHal.h index 75e93a18b5..e84cba50f6 100644 --- a/sensors/2.0/multihal/include/SubHal.h +++ b/sensors/2.0/multihal/include/SubHal.h @@ -137,6 +137,7 @@ class IHalProxyCallback : public ISensorsCallback { * sub-HALs can continue to use the lower 3 bytes of the handle. */ class ISensorsSubHal : public ISensors { + public: // The ISensors version of initialize isn't used for multihal. Instead, sub-HALs must implement // the version below to allow communciation logic to centralized in the HalProxy Return initialize( diff --git a/sensors/2.0/multihal/tests/Android.bp b/sensors/2.0/multihal/tests/Android.bp index 13d80f7a6d..21ceb0c2d7 100644 --- a/sensors/2.0/multihal/tests/Android.bp +++ b/sensors/2.0/multihal/tests/Android.bp @@ -86,4 +86,4 @@ cc_test { "libutils", ], test_suites: ["device-tests"], -} \ No newline at end of file +} diff --git a/sensors/2.0/multihal/tests/HalProxy_test.cpp b/sensors/2.0/multihal/tests/HalProxy_test.cpp index 9edc88a424..28004d0d32 100644 --- a/sensors/2.0/multihal/tests/HalProxy_test.cpp +++ b/sensors/2.0/multihal/tests/HalProxy_test.cpp @@ -18,7 +18,14 @@ #include "HalProxy.h" #include "SensorsSubHal.h" +#include + +using ::android::hardware::sensors::V1_0::SensorInfo; +using ::android::hardware::sensors::V1_0::SensorType; using ::android::hardware::sensors::V2_0::implementation::HalProxy; +using ::android::hardware::sensors::V2_0::subhal::implementation::AllSensorsSubHal; +using ::android::hardware::sensors::V2_0::subhal::implementation::ContinuousSensorsSubHal; +using ::android::hardware::sensors::V2_0::subhal::implementation::OnChangeSensorsSubHal; using ::android::hardware::sensors::V2_0::subhal::implementation::SensorsSubHal; // TODO: Add more interesting tests such as @@ -30,10 +37,55 @@ using ::android::hardware::sensors::V2_0::subhal::implementation::SensorsSubHal; // // See https://source.android.com/compatibility/tests/development/native-func-e2e.md for more info // on how tests are set up and for information on the gtest framework itself. -TEST(HalProxyTest, ExampleTest) { - SensorsSubHal subHal; - std::vector fakeSubHals; - fakeSubHals.push_back(&subHal); +// Helper declarations follow +void testSensorsListFromProxyAndSubHal(const std::vector& proxySensorsList, + const std::vector& subHalSensorsList); + +// Tests follow +TEST(HalProxyTest, GetSensorsListOneSubHalTest) { + AllSensorsSubHal subHal; + std::vector fakeSubHals{&subHal}; HalProxy proxy(fakeSubHals); + + proxy.getSensorsList([&](const auto& proxySensorsList) { + subHal.getSensorsList([&](const auto& subHalSensorsList) { + testSensorsListFromProxyAndSubHal(proxySensorsList, subHalSensorsList); + }); + }); +} + +TEST(HalProxyTest, GetSensorsListTwoSubHalTest) { + ContinuousSensorsSubHal continuousSubHal; + OnChangeSensorsSubHal onChangeSubHal; + std::vector fakeSubHals; + fakeSubHals.push_back(&continuousSubHal); + fakeSubHals.push_back(&onChangeSubHal); + HalProxy proxy(fakeSubHals); + + std::vector proxySensorsList, combinedSubHalSensorsList; + + proxy.getSensorsList([&](const auto& list) { proxySensorsList = list; }); + continuousSubHal.getSensorsList([&](const auto& list) { + combinedSubHalSensorsList.insert(combinedSubHalSensorsList.end(), list.begin(), list.end()); + }); + onChangeSubHal.getSensorsList([&](const auto& list) { + combinedSubHalSensorsList.insert(combinedSubHalSensorsList.end(), list.begin(), list.end()); + }); + + testSensorsListFromProxyAndSubHal(proxySensorsList, combinedSubHalSensorsList); +} + +// Helper implementations follow +void testSensorsListFromProxyAndSubHal(const std::vector& proxySensorsList, + const std::vector& subHalSensorsList) { + EXPECT_EQ(proxySensorsList.size(), subHalSensorsList.size()); + + for (size_t i = 0; i < proxySensorsList.size(); i++) { + const SensorInfo& proxySensor = proxySensorsList[i]; + const SensorInfo& subHalSensor = subHalSensorsList[i]; + + EXPECT_EQ(proxySensor.type, subHalSensor.type); + EXPECT_EQ(proxySensor.sensorHandle & 0x00FFFFFF, subHalSensor.sensorHandle); + } } \ No newline at end of file diff --git a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp b/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp index 8d459824dc..fe471616c5 100644 --- a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp +++ b/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp @@ -20,7 +20,16 @@ #include ISensorsSubHal* sensorsHalGetSubHal(uint32_t* version) { +#if defined SUPPORT_CONTINUOUS_SENSORS && defined SUPPORT_ON_CHANGE_SENSORS + static ::android::hardware::sensors::V2_0::subhal::implementation::AllSensorsSubHal subHal; +#elif defined SUPPORT_CONTINUOUS_SENSORS + static ::android::hardware::sensors::V2_0::subhal::implementation::ContinuousSensorsSubHal + subHal; +#elif defined SUPPORT_ON_CHANGE_SENSORS + static ::android::hardware::sensors::V2_0::subhal::implementation::OnChangeSensorsSubHal subHal; +#else static ::android::hardware::sensors::V2_0::subhal::implementation::SensorsSubHal subHal; +#endif // defined SUPPORT_CONTINUOUS_SENSORS && defined SUPPORT_ON_CHANGE_SENSORS *version = SUB_HAL_2_0_VERSION; return &subHal; } @@ -42,22 +51,7 @@ using ::android::hardware::sensors::V2_0::SensorTimeout; using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits; using ::android::hardware::sensors::V2_0::implementation::ScopedWakelock; -SensorsSubHal::SensorsSubHal() : mCallback(nullptr), mNextHandle(1) { -#ifdef SUPPORT_CONTINUOUS_SENSORS - AddSensor(); - AddSensor(); - AddSensor(); - AddSensor(); -#endif // SUPPORT_CONTINUOUS_SENSORS - -#ifdef SUPPORT_ON_CHANGE_SENSORS - AddSensor(); - AddSensor(); - AddSensor(); - AddSensor(); - AddSensor(); -#endif // SUPPORT_ON_CHANGE_SENSORS -} +SensorsSubHal::SensorsSubHal() : mCallback(nullptr), mNextHandle(1) {} // Methods from ::android::hardware::sensors::V2_0::ISensors follow. Return SensorsSubHal::getSensorsList(getSensorsList_cb _hidl_cb) { @@ -171,6 +165,33 @@ void SensorsSubHal::postEvents(const std::vector& events, bool wakeup) { mCallback->postEvents(events, std::move(wakelock)); } +ContinuousSensorsSubHal::ContinuousSensorsSubHal() { + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); +} + +OnChangeSensorsSubHal::OnChangeSensorsSubHal() { + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); +} + +AllSensorsSubHal::AllSensorsSubHal() { + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); +} + } // namespace implementation } // namespace subhal } // namespace V2_0 diff --git a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h b/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h index 93009d5833..d94d73d536 100644 --- a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h +++ b/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h @@ -20,6 +20,8 @@ #include "Sensor.h" +#include + namespace android { namespace hardware { namespace sensors { @@ -81,7 +83,7 @@ class SensorsSubHal : public ISensorsSubHal, public ISensorsEventCallback { // Method from ISensorsEventCallback. void postEvents(const std::vector& events, bool wakeup) override; - private: + protected: template void AddSensor() { std::shared_ptr sensor = @@ -89,6 +91,7 @@ class SensorsSubHal : public ISensorsSubHal, public ISensorsEventCallback { mSensors[sensor->getSensorInfo().sensorHandle] = sensor; } + private: /** * Callback used to communicate to the HalProxy when dynamic sensors are connected / * disconnected, sensor events need to be sent to the framework, and when a wakelock should be @@ -107,6 +110,24 @@ class SensorsSubHal : public ISensorsSubHal, public ISensorsEventCallback { int32_t mNextHandle; }; +// SubHal that has continuous sensors for testing purposes. +class ContinuousSensorsSubHal : public SensorsSubHal { + public: + ContinuousSensorsSubHal(); +}; + +// SubHal that has on-change sensors for testing purposes. +class OnChangeSensorsSubHal : public SensorsSubHal { + public: + OnChangeSensorsSubHal(); +}; + +// SubHal that has both continuous and on-change sensors for testing purposes. +class AllSensorsSubHal : public SensorsSubHal { + public: + AllSensorsSubHal(); +}; + } // namespace implementation } // namespace subhal } // namespace V2_0