mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-02 06:22:53 +00:00
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
This commit is contained in:
@@ -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<SensorsHalGetSubHalFunc> 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<ISensorsSubHal*>& subHalList) : mSubHalList(subHalList) {
|
||||
// TODO: Perform the same steps as the empty constructor.
|
||||
initializeSensorList();
|
||||
}
|
||||
|
||||
HalProxy::~HalProxy() {
|
||||
@@ -113,8 +83,8 @@ HalProxy::~HalProxy() {
|
||||
// state.
|
||||
}
|
||||
|
||||
Return<void> HalProxy::getSensorsList(getSensorsList_cb /* _hidl_cb */) {
|
||||
// TODO: Output sensors list created as part of HalProxy().
|
||||
Return<void> HalProxy::getSensorsList(getSensorsList_cb _hidl_cb) {
|
||||
_hidl_cb(mSensorList);
|
||||
return Void();
|
||||
}
|
||||
|
||||
@@ -217,6 +187,60 @@ Return<void> HalProxy::onDynamicSensorsDisconnected(
|
||||
return Return<void>();
|
||||
}
|
||||
|
||||
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<SensorsHalGetSubHalFunc> 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<size_t>(sensorHandle >> 24)];
|
||||
}
|
||||
|
||||
@@ -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<ISensorsSubHal*> 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<SensorInfo> 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.
|
||||
|
||||
@@ -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<Result> initialize(
|
||||
|
||||
@@ -86,4 +86,4 @@ cc_test {
|
||||
"libutils",
|
||||
],
|
||||
test_suites: ["device-tests"],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,14 @@
|
||||
#include "HalProxy.h"
|
||||
#include "SensorsSubHal.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
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<ISensorsSubHal*> fakeSubHals;
|
||||
fakeSubHals.push_back(&subHal);
|
||||
|
||||
// Helper declarations follow
|
||||
void testSensorsListFromProxyAndSubHal(const std::vector<SensorInfo>& proxySensorsList,
|
||||
const std::vector<SensorInfo>& subHalSensorsList);
|
||||
|
||||
// Tests follow
|
||||
TEST(HalProxyTest, GetSensorsListOneSubHalTest) {
|
||||
AllSensorsSubHal subHal;
|
||||
std::vector<ISensorsSubHal*> 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<ISensorsSubHal*> fakeSubHals;
|
||||
fakeSubHals.push_back(&continuousSubHal);
|
||||
fakeSubHals.push_back(&onChangeSubHal);
|
||||
HalProxy proxy(fakeSubHals);
|
||||
|
||||
std::vector<SensorInfo> 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<SensorInfo>& proxySensorsList,
|
||||
const std::vector<SensorInfo>& 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);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,16 @@
|
||||
#include <log/log.h>
|
||||
|
||||
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<AccelSensor>();
|
||||
AddSensor<GyroSensor>();
|
||||
AddSensor<MagnetometerSensor>();
|
||||
AddSensor<PressureSensor>();
|
||||
#endif // SUPPORT_CONTINUOUS_SENSORS
|
||||
|
||||
#ifdef SUPPORT_ON_CHANGE_SENSORS
|
||||
AddSensor<AmbientTempSensor>();
|
||||
AddSensor<DeviceTempSensor>();
|
||||
AddSensor<LightSensor>();
|
||||
AddSensor<ProximitySensor>();
|
||||
AddSensor<RelativeHumiditySensor>();
|
||||
#endif // SUPPORT_ON_CHANGE_SENSORS
|
||||
}
|
||||
SensorsSubHal::SensorsSubHal() : mCallback(nullptr), mNextHandle(1) {}
|
||||
|
||||
// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
|
||||
Return<void> SensorsSubHal::getSensorsList(getSensorsList_cb _hidl_cb) {
|
||||
@@ -171,6 +165,33 @@ void SensorsSubHal::postEvents(const std::vector<Event>& events, bool wakeup) {
|
||||
mCallback->postEvents(events, std::move(wakelock));
|
||||
}
|
||||
|
||||
ContinuousSensorsSubHal::ContinuousSensorsSubHal() {
|
||||
AddSensor<AccelSensor>();
|
||||
AddSensor<GyroSensor>();
|
||||
AddSensor<MagnetometerSensor>();
|
||||
AddSensor<PressureSensor>();
|
||||
}
|
||||
|
||||
OnChangeSensorsSubHal::OnChangeSensorsSubHal() {
|
||||
AddSensor<AmbientTempSensor>();
|
||||
AddSensor<DeviceTempSensor>();
|
||||
AddSensor<LightSensor>();
|
||||
AddSensor<ProximitySensor>();
|
||||
AddSensor<RelativeHumiditySensor>();
|
||||
}
|
||||
|
||||
AllSensorsSubHal::AllSensorsSubHal() {
|
||||
AddSensor<AccelSensor>();
|
||||
AddSensor<GyroSensor>();
|
||||
AddSensor<MagnetometerSensor>();
|
||||
AddSensor<PressureSensor>();
|
||||
AddSensor<AmbientTempSensor>();
|
||||
AddSensor<DeviceTempSensor>();
|
||||
AddSensor<LightSensor>();
|
||||
AddSensor<ProximitySensor>();
|
||||
AddSensor<RelativeHumiditySensor>();
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace subhal
|
||||
} // namespace V2_0
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "Sensor.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace sensors {
|
||||
@@ -81,7 +83,7 @@ class SensorsSubHal : public ISensorsSubHal, public ISensorsEventCallback {
|
||||
// Method from ISensorsEventCallback.
|
||||
void postEvents(const std::vector<Event>& events, bool wakeup) override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
template <class SensorType>
|
||||
void AddSensor() {
|
||||
std::shared_ptr<SensorType> 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
|
||||
|
||||
Reference in New Issue
Block a user