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:
Stan Rokita
2019-08-23 12:35:40 -07:00
parent 60b836b0e8
commit dc7a8e7898
7 changed files with 199 additions and 58 deletions

View File

@@ -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)];
}

View File

@@ -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.

View File

@@ -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(

View File

@@ -86,4 +86,4 @@ cc_test {
"libutils",
],
test_suites: ["device-tests"],
}
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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