blob: 4a615af25b81cb13f8a1f4ff6bc622c7c3b986b5 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "GoogleIIOSensorSubHal"
#include "SensorsSubHal.h"
#include <android/hardware/sensors/2.0/types.h>
#include <log/log.h>
ISensorsSubHal* sensorsHalGetSubHal(uint32_t* version) {
static ::android::hardware::sensors::V2_0::subhal::implementation::SensorsSubHal subHal;
*version = SUB_HAL_2_0_VERSION;
return &subHal;
}
namespace android {
namespace hardware {
namespace sensors {
namespace V2_0 {
namespace subhal {
namespace implementation {
using ::android::hardware::Void;
using ::android::hardware::sensors::V1_0::Event;
using ::android::hardware::sensors::V1_0::RateLevel;
using ::android::hardware::sensors::V1_0::SharedMemInfo;
using ::android::hardware::sensors::V2_0::SensorTimeout;
using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
using ::android::hardware::sensors::V2_0::implementation::ScopedWakelock;
using ::sensor::hal::configuration::V1_0::Sensor;
using ::sensor::hal::configuration::V1_0::SensorHalConfiguration;
#define SENSOR_XML_CONFIG_FILE_NAME "sensor_hal_configuration.xml"
static const char* gSensorConfigLocationList[] = {"/odm/etc/sensors/", "/vendor/etc/sensors/"};
static const int gSensorConfigLocationListSize =
(sizeof(gSensorConfigLocationList) / sizeof(gSensorConfigLocationList[0]));
#define MODULE_NAME "android.hardware.sensors@2.0-Google-IIO-Subhal"
static std::optional<std::vector<Sensor>> readSensorsConfigFromXml() {
for (int i = 0; i < gSensorConfigLocationListSize; i++) {
const auto sensor_config_file =
std::string(gSensorConfigLocationList[i]) + SENSOR_XML_CONFIG_FILE_NAME;
auto sensorConfig = ::sensor::hal::configuration::V1_0::read(sensor_config_file.c_str());
if (sensorConfig) {
auto modulesList = sensorConfig->getFirstModules()->get_module();
for (auto module : modulesList) {
if (module.getHalName().compare(MODULE_NAME) == 0) {
return module.getFirstSensors()->getSensor();
}
}
}
}
ALOGI("Could not find the sensors configuration for module %s", MODULE_NAME);
return std::nullopt;
}
static std::optional<std::vector<Configuration>> getSensorConfiguration(
const std::vector<Sensor>& sensor_list, const std::string& name, SensorType type) {
for (auto sensor : sensor_list) {
if ((name.compare(sensor.getName()) == 0) && (type == (SensorType)sensor.getType())) {
return sensor.getConfiguration();
}
}
ALOGI("Could not find the sensor configuration for %s ", name.c_str());
return std::nullopt;
}
static bool isSensorSupported(iio_device_data* sensor) {
#define SENSOR_SUPPORTED(SENSOR_NAME, SENSOR_TYPE) \
{ .name = SENSOR_NAME, .type = SENSOR_TYPE, }
static const std::vector<sensors_supported_hal> supported_sensors = {
SENSOR_SUPPORTED("scmi.iio.accel", SensorType::ACCELEROMETER),
SENSOR_SUPPORTED("scmi.iio.gyro", SensorType::GYROSCOPE),
};
#undef SENSOR_SUPPORTED
if (!sensor) return false;
auto iter = std::find_if(
supported_sensors.begin(), supported_sensors.end(),
[&sensor](const auto& candidate) -> bool { return candidate.name == sensor->name; });
if (iter == supported_sensors.end()) return false;
sensor->type = iter->type;
return true;
}
SensorsSubHal::SensorsSubHal() : mCallback(nullptr), mNextHandle(1) {
int err;
std::vector<iio_device_data> iio_devices;
const auto sensors_config_list = readSensorsConfigFromXml();
err = load_iio_devices(DEFAULT_IIO_DIR, &iio_devices, isSensorSupported);
if (err == 0) {
for (auto& iio_device : iio_devices) {
err = scan_elements(iio_device.sysfspath, &iio_device);
if (err == 0) {
err = enable_sensor(iio_device.sysfspath, false);
if (err == 0) {
std::optional<std::vector<Configuration>> sensor_configuration = std::nullopt;
if (sensors_config_list)
sensor_configuration = getSensorConfiguration(
*sensors_config_list, iio_device.name, iio_device.type);
if (iio_device.channelInfo.size() == NUM_OF_CHANNEL_SUPPORTED) {
AddSensor(iio_device, sensor_configuration);
} else {
ALOGE("SensorsSubHal(): Unexpected number of channels for sensor %s",
iio_device.sysfspath.c_str());
}
} else {
ALOGE("SensorsSubHal(): Error in enabling_sensor %s to %d error code %d",
iio_device.sysfspath.c_str(), false, err);
}
} else {
ALOGE("SensorsSubHal(): Error in scanning channels for IIO device %s error code %d",
iio_device.sysfspath.c_str(), err);
}
}
} else {
ALOGE("SensorsSubHal: load_iio_devices returned error %d", err);
}
}
// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
Return<void> SensorsSubHal::getSensorsList(getSensorsList_cb _hidl_cb) {
std::vector<SensorInfo> sensors;
for (const auto& sensor : mSensors) {
SensorInfo sensorInfo = sensor.second->getSensorInfo();
sensorInfo.flags &= ~static_cast<uint32_t>(V1_0::SensorFlagBits::MASK_DIRECT_CHANNEL);
sensorInfo.flags &= ~static_cast<uint32_t>(V1_0::SensorFlagBits::MASK_DIRECT_REPORT);
sensors.push_back(sensorInfo);
}
_hidl_cb(sensors);
return Void();
}
Return<Result> SensorsSubHal::setOperationMode(OperationMode mode) {
for (auto& sensor : mSensors) {
sensor.second->setOperationMode(mode);
}
mCurrentOperationMode = mode;
return Result::OK;
}
Return<Result> SensorsSubHal::activate(int32_t sensorHandle, bool enabled) {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
sensor->second->activate(enabled);
return Result::OK;
}
return Result::BAD_VALUE;
}
Return<Result> SensorsSubHal::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
int64_t /* maxReportLatencyNs */) {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
sensor->second->batch(samplingPeriodNs);
return Result::OK;
}
return Result::BAD_VALUE;
}
Return<Result> SensorsSubHal::flush(int32_t sensorHandle) {
auto sensor = mSensors.find(sensorHandle);
if (sensor != mSensors.end()) {
return sensor->second->flush();
}
return Result::BAD_VALUE;
}
Return<Result> SensorsSubHal::injectSensorData(const Event& /* event */) {
return Result::INVALID_OPERATION;
}
Return<void> SensorsSubHal::registerDirectChannel(const SharedMemInfo& /* mem */,
registerDirectChannel_cb _hidl_cb) {
_hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */);
return Return<void>();
}
Return<Result> SensorsSubHal::unregisterDirectChannel(int32_t /* channelHandle */) {
return Result::INVALID_OPERATION;
}
Return<void> SensorsSubHal::configDirectReport(int32_t /* sensorHandle */,
int32_t /* channelHandle */, RateLevel /* rate */,
configDirectReport_cb _hidl_cb) {
_hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */);
return Return<void>();
}
Return<void> SensorsSubHal::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) {
if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
ALOGE("%s: missing fd for writing", __FUNCTION__);
return Void();
}
FILE* out = fdopen(dup(fd->data[0]), "w");
if (args.size() != 0) {
fprintf(out,
"Note: sub-HAL %s currently does not support args. Input arguments are "
"ignored.\n",
getName().c_str());
}
std::ostringstream stream;
stream << "Available sensors:" << std::endl;
for (auto& sensor : mSensors) {
SensorInfo info = sensor.second->getSensorInfo();
HWSensorBase* hwSensor = static_cast<HWSensorBase*>(sensor.second.get());
stream << "Name: " << info.name << std::endl;
stream << "handle: " << info.sensorHandle << std::endl;
stream << "resolution: " << info.resolution << " minDelay: " << info.minDelay
<< " maxDelay:" << info.maxDelay << std::endl;
stream << "iio path" << hwSensor->mIioData.sysfspath << std::endl;
}
stream << std::endl;
fprintf(out, "%s", stream.str().c_str());
fclose(out);
return Return<void>();
}
Return<Result> SensorsSubHal::initialize(const sp<IHalProxyCallback>& halProxyCallback) {
mCallback = halProxyCallback;
setOperationMode(OperationMode::NORMAL);
return Result::OK;
}
void SensorsSubHal::postEvents(const std::vector<Event>& events, bool wakeup) {
ScopedWakelock wakelock = mCallback->createScopedWakelock(wakeup);
mCallback->postEvents(events, std::move(wakelock));
}
void SensorsSubHal::AddSensor(const struct iio_device_data& iio_data,
const std::optional<std::vector<Configuration>>& config) {
HWSensorBase* sensor = HWSensorBase::buildSensor(mNextHandle++ /* sensorHandle */,
this /* callback */, iio_data, config);
if (sensor != nullptr)
mSensors[sensor->getSensorInfo().sensorHandle] = std::unique_ptr<SensorBase>(sensor);
else
ALOGE("Unable to add sensor %s as buildSensor returned null", iio_data.name.c_str());
}
} // namespace implementation
} // namespace subhal
} // namespace V2_0
} // namespace sensors
} // namespace hardware
} // namespace android