From 673c085135c3d9b5692032baca868905e9ae484c Mon Sep 17 00:00:00 2001 From: Anand S Date: Thu, 19 Sep 2024 12:24:14 +0530 Subject: [PATCH] bangkk: Bring back custom sensors HAL Change-Id: Ie6092d1a492e3f8e94ecb8e82a0ebb5b01ae829f --- device.mk | 5 +- .../bangkk/Frameworks/res/values/config.xml | 6 + sensors/.clang-format | 11 + sensors/Android.bp | 35 ++ sensors/Sensor.cpp | 361 ++++++++++++++++++ sensors/Sensor.h | 154 ++++++++ sensors/SensorsSubHal.cpp | 163 ++++++++ sensors/SensorsSubHal.h | 94 +++++ {configs/sensors => sensors}/hals.conf | 0 9 files changed, 828 insertions(+), 1 deletion(-) create mode 100644 sensors/.clang-format create mode 100644 sensors/Android.bp create mode 100644 sensors/Sensor.cpp create mode 100644 sensors/Sensor.h create mode 100644 sensors/SensorsSubHal.cpp create mode 100644 sensors/SensorsSubHal.h rename {configs/sensors => sensors}/hals.conf (100%) diff --git a/device.mk b/device.mk index c9e7513..2305a17 100644 --- a/device.mk +++ b/device.mk @@ -106,8 +106,11 @@ PRODUCT_COPY_FILES += \ frameworks/native/data/etc/com.nxp.mifare.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/com.nxp.mifare.xml # Sensors +PRODUCT_PACKAGES += \ + sensors.bangkk + PRODUCT_COPY_FILES += \ - $(LOCAL_PATH)/configs/sensors/hals.conf:$(TARGET_COPY_OUT_VENDOR)/etc/sensors/hals.conf + $(LOCAL_PATH)/sensors/hals.conf:$(TARGET_COPY_OUT_VENDOR)/etc/sensors/hals.conf # Soong namespaces PRODUCT_SOONG_NAMESPACES += $(LOCAL_PATH) diff --git a/resource-overlay/bangkk/Frameworks/res/values/config.xml b/resource-overlay/bangkk/Frameworks/res/values/config.xml index f46910c..010ef24 100644 --- a/resource-overlay/bangkk/Frameworks/res/values/config.xml +++ b/resource-overlay/bangkk/Frameworks/res/values/config.xml @@ -277,6 +277,12 @@ http://uaprof.motorola.com/phoneconfig/motov1/Profile/motov1.rdf + + org.lineageos.sensor.double_tap + + + org.lineageos.sensor.udfps + true diff --git a/sensors/.clang-format b/sensors/.clang-format new file mode 100644 index 0000000..ae4a451 --- /dev/null +++ b/sensors/.clang-format @@ -0,0 +1,11 @@ +BasedOnStyle: Google +AccessModifierOffset: -2 +AllowShortFunctionsOnASingleLine: Inline +ColumnLimit: 100 +CommentPragmas: NOLINT:.* +DerivePointerAlignment: false +IndentWidth: 4 +PointerAlignment: Left +TabWidth: 4 +UseTab: Never +PenaltyExcessCharacter: 32 diff --git a/sensors/Android.bp b/sensors/Android.bp new file mode 100644 index 0000000..208e875 --- /dev/null +++ b/sensors/Android.bp @@ -0,0 +1,35 @@ +// +// Copyright (C) 2022 The LineageOS Project +// +// SPDX-License-Identifier: Apache-2.0 +// + +cc_library_shared { + name: "sensors.bangkk", + defaults: ["hidl_defaults"], + srcs: [ + "Sensor.cpp", + "SensorsSubHal.cpp", + ], + shared_libs: [ + "android.hardware.sensors@1.0", + "android.hardware.sensors@2.0", + "android.hardware.sensors@2.0-ScopedWakelock", + "android.hardware.sensors@2.1", + "libcutils", + "libfmq", + "libhardware", + "libhidlbase", + "liblog", + "libpower", + "libutils", + ], + static_libs: [ + "android.hardware.sensors@1.0-convert", + "android.hardware.sensors@2.X-multihal", + ], + cflags: [ + "-DLOG_TAG=\"sensors.bangkk\"", + ], + vendor: true, +} diff --git a/sensors/Sensor.cpp b/sensors/Sensor.cpp new file mode 100644 index 0000000..5137862 --- /dev/null +++ b/sensors/Sensor.cpp @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2019 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. + */ + +#include "Sensor.h" + +#include +#include +#include + +#include + +static bool readBool(int fd, bool seek) { + char c; + int rc; + + if (seek) { + rc = lseek(fd, 0, SEEK_SET); + if (rc) { + ALOGE("failed to seek: %d", rc); + return false; + } + } + + rc = read(fd, &c, sizeof(c)); + if (rc != 1) { + ALOGE("failed to read bool: %d", rc); + return false; + } + + return c != '0'; +} + +namespace android { +namespace hardware { +namespace sensors { +namespace V2_1 { +namespace subhal { +namespace implementation { + +using ::android::hardware::sensors::V1_0::MetaDataEventType; +using ::android::hardware::sensors::V1_0::OperationMode; +using ::android::hardware::sensors::V1_0::Result; +using ::android::hardware::sensors::V1_0::SensorFlagBits; +using ::android::hardware::sensors::V1_0::SensorStatus; +using ::android::hardware::sensors::V2_1::Event; +using ::android::hardware::sensors::V2_1::SensorInfo; +using ::android::hardware::sensors::V2_1::SensorType; + +Sensor::Sensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : mIsEnabled(false), + mSamplingPeriodNs(0), + mLastSampleTimeNs(0), + mCallback(callback), + mMode(OperationMode::NORMAL) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.vendor = "The LineageOS Project"; + mSensorInfo.version = 1; + constexpr float kDefaultMaxDelayUs = 1000 * 1000; + mSensorInfo.maxDelay = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; + mRunThread = std::thread(startThread, this); +} + +Sensor::~Sensor() { + // Ensure that lock is unlocked before calling mRunThread.join() or a + // deadlock will occur. + { + std::unique_lock lock(mRunMutex); + mStopThread = true; + mIsEnabled = false; + mWaitCV.notify_all(); + } + mRunThread.join(); +} + +const SensorInfo& Sensor::getSensorInfo() const { + return mSensorInfo; +} + +void Sensor::batch(int32_t samplingPeriodNs) { + samplingPeriodNs = + std::clamp(samplingPeriodNs, mSensorInfo.minDelay * 1000, mSensorInfo.maxDelay * 1000); + + if (mSamplingPeriodNs != samplingPeriodNs) { + mSamplingPeriodNs = samplingPeriodNs; + // Wake up the 'run' thread to check if a new event should be generated now + mWaitCV.notify_all(); + } +} + +void Sensor::activate(bool enable) { + std::lock_guard lock(mRunMutex); + if (mIsEnabled != enable) { + mIsEnabled = enable; + mWaitCV.notify_all(); + } +} + +Result Sensor::flush() { + // Only generate a flush complete event if the sensor is enabled and if the sensor is not a + // one-shot sensor. + if (!mIsEnabled) { + return Result::BAD_VALUE; + } + + // Note: If a sensor supports batching, write all of the currently batched events for the sensor + // to the Event FMQ prior to writing the flush complete event. + Event ev; + ev.sensorHandle = mSensorInfo.sensorHandle; + ev.sensorType = SensorType::META_DATA; + ev.u.meta.what = MetaDataEventType::META_DATA_FLUSH_COMPLETE; + std::vector evs{ev}; + mCallback->postEvents(evs, isWakeUpSensor()); + + return Result::OK; +} + +void Sensor::startThread(Sensor* sensor) { + sensor->run(); +} + +void Sensor::run() { + std::unique_lock runLock(mRunMutex); + constexpr int64_t kNanosecondsInSeconds = 1000 * 1000 * 1000; + + while (!mStopThread) { + if (!mIsEnabled || mMode == OperationMode::DATA_INJECTION) { + mWaitCV.wait(runLock, [&] { + return ((mIsEnabled && mMode == OperationMode::NORMAL) || mStopThread); + }); + } else { + timespec curTime; + clock_gettime(CLOCK_REALTIME, &curTime); + int64_t now = (curTime.tv_sec * kNanosecondsInSeconds) + curTime.tv_nsec; + int64_t nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs; + + if (now >= nextSampleTime) { + mLastSampleTimeNs = now; + nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs; + mCallback->postEvents(readEvents(), isWakeUpSensor()); + } + + mWaitCV.wait_for(runLock, std::chrono::nanoseconds(nextSampleTime - now)); + } + } +} + +bool Sensor::isWakeUpSensor() { + return mSensorInfo.flags & static_cast(SensorFlagBits::WAKE_UP); +} + +std::vector Sensor::readEvents() { + std::vector events; + Event event; + event.sensorHandle = mSensorInfo.sensorHandle; + event.sensorType = mSensorInfo.type; + event.timestamp = ::android::elapsedRealtimeNano(); + event.u.vec3.x = 0; + event.u.vec3.y = 0; + event.u.vec3.z = 0; + event.u.vec3.status = SensorStatus::ACCURACY_HIGH; + events.push_back(event); + return events; +} + +void Sensor::setOperationMode(OperationMode mode) { + std::lock_guard lock(mRunMutex); + if (mMode != mode) { + mMode = mode; + mWaitCV.notify_all(); + } +} + +bool Sensor::supportsDataInjection() const { + return mSensorInfo.flags & static_cast(SensorFlagBits::DATA_INJECTION); +} + +Result Sensor::injectEvent(const Event& event) { + Result result = Result::OK; + if (event.sensorType == SensorType::ADDITIONAL_INFO) { + // When in OperationMode::NORMAL, SensorType::ADDITIONAL_INFO is used to push operation + // environment data into the device. + } else if (!supportsDataInjection()) { + result = Result::INVALID_OPERATION; + } else if (mMode == OperationMode::DATA_INJECTION) { + mCallback->postEvents(std::vector{event}, isWakeUpSensor()); + } else { + result = Result::BAD_VALUE; + } + return result; +} + +OneShotSensor::OneShotSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : Sensor(sensorHandle, callback) { + mSensorInfo.minDelay = -1; + mSensorInfo.maxDelay = 0; + mSensorInfo.flags |= SensorFlagBits::ONE_SHOT_MODE; +} + +SysfsPollingOneShotSensor::SysfsPollingOneShotSensor( + int32_t sensorHandle, ISensorsEventCallback* callback, const std::string& pollPath, + const std::string& enablePath, const std::string& name, const std::string& typeAsString, + SensorType type) + : OneShotSensor(sensorHandle, callback) { + mSensorInfo.name = name; + mSensorInfo.type = type; + mSensorInfo.typeAsString = typeAsString; + mSensorInfo.maxRange = 2048.0f; + mSensorInfo.resolution = 1.0f; + mSensorInfo.power = 0; + mSensorInfo.flags |= SensorFlagBits::WAKE_UP; + + mEnableStream.open(enablePath); + + int rc; + + rc = pipe(mWaitPipeFd); + if (rc < 0) { + mWaitPipeFd[0] = -1; + mWaitPipeFd[1] = -1; + ALOGE("failed to open wait pipe: %d", rc); + } + + mPollFd = open(pollPath.c_str(), O_RDONLY); + if (mPollFd < 0) { + ALOGE("failed to open poll fd: %d", mPollFd); + } + + if (mWaitPipeFd[0] < 0 || mWaitPipeFd[1] < 0 || mPollFd < 0) { + mStopThread = true; + return; + } + + mPolls[0] = { + .fd = mWaitPipeFd[0], + .events = POLLIN, + }; + + mPolls[1] = { + .fd = mPollFd, + .events = POLLERR | POLLPRI, + }; +} + +SysfsPollingOneShotSensor::~SysfsPollingOneShotSensor() { + interruptPoll(); +} + +void SysfsPollingOneShotSensor::writeEnable(bool enable) { + if (mEnableStream) { + mEnableStream << (enable ? '1' : '0') << std::flush; + } +} + +void SysfsPollingOneShotSensor::activate(bool enable, bool notify, bool lock) { + std::unique_lock runLock(mRunMutex, std::defer_lock); + + if (lock) { + runLock.lock(); + } + + if (mIsEnabled != enable) { + writeEnable(enable); + + mIsEnabled = enable; + + if (notify) { + interruptPoll(); + mWaitCV.notify_all(); + } + } + + if (lock) { + runLock.unlock(); + } +} + +void SysfsPollingOneShotSensor::activate(bool enable) { + activate(enable, true, true); +} + +void SysfsPollingOneShotSensor::setOperationMode(OperationMode mode) { + Sensor::setOperationMode(mode); + interruptPoll(); +} + +void SysfsPollingOneShotSensor::run() { + std::unique_lock runLock(mRunMutex); + + while (!mStopThread) { + if (!mIsEnabled || mMode == OperationMode::DATA_INJECTION) { + mWaitCV.wait(runLock, [&] { + return ((mIsEnabled && mMode == OperationMode::NORMAL) || mStopThread); + }); + } else { + // Cannot hold lock while polling. + runLock.unlock(); + int rc = poll(mPolls, 2, -1); + runLock.lock(); + + if (rc < 0) { + ALOGE("failed to poll: %d", rc); + mStopThread = true; + continue; + } + + if (mPolls[1].revents == mPolls[1].events && readBool(mPollFd, true /* seek */)) { + activate(false, false, false); + mCallback->postEvents(readEvents(), isWakeUpSensor()); + } else if (mPolls[0].revents == mPolls[0].events) { + readBool(mWaitPipeFd[0], false /* seek */); + } + } + } +} + +void SysfsPollingOneShotSensor::interruptPoll() { + if (mWaitPipeFd[1] < 0) return; + + char c = '1'; + write(mWaitPipeFd[1], &c, sizeof(c)); +} + +std::vector SysfsPollingOneShotSensor::readEvents() { + std::vector events; + Event event; + event.sensorHandle = mSensorInfo.sensorHandle; + event.sensorType = mSensorInfo.type; + event.timestamp = ::android::elapsedRealtimeNano(); + fillEventData(event); + events.push_back(event); + return events; +} + +void SysfsPollingOneShotSensor::fillEventData(Event& event) { + event.u.data[0] = 0; + event.u.data[1] = 0; +} + +} // namespace implementation +} // namespace subhal +} // namespace V2_1 +} // namespace sensors +} // namespace hardware +} // namespace android diff --git a/sensors/Sensor.h b/sensors/Sensor.h new file mode 100644 index 0000000..4bc0676 --- /dev/null +++ b/sensors/Sensor.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using ::android::hardware::sensors::V1_0::OperationMode; +using ::android::hardware::sensors::V1_0::Result; +using ::android::hardware::sensors::V2_1::Event; +using ::android::hardware::sensors::V2_1::SensorInfo; +using ::android::hardware::sensors::V2_1::SensorType; + +namespace android { +namespace hardware { +namespace sensors { +namespace V2_1 { +namespace subhal { +namespace implementation { + +class ISensorsEventCallback { + public: + virtual ~ISensorsEventCallback(){}; + virtual void postEvents(const std::vector& events, bool wakeup) = 0; +}; + +class Sensor { + public: + Sensor(int32_t sensorHandle, ISensorsEventCallback* callback); + virtual ~Sensor(); + + const SensorInfo& getSensorInfo() const; + virtual void batch(int32_t samplingPeriodNs); + virtual void activate(bool enable); + virtual Result flush(); + + virtual void setOperationMode(OperationMode mode); + bool supportsDataInjection() const; + Result injectEvent(const Event& event); + + protected: + virtual void run(); + virtual std::vector readEvents(); + static void startThread(Sensor* sensor); + + bool isWakeUpSensor(); + + bool mIsEnabled; + int64_t mSamplingPeriodNs; + int64_t mLastSampleTimeNs; + SensorInfo mSensorInfo; + + std::atomic_bool mStopThread; + std::condition_variable mWaitCV; + std::mutex mRunMutex; + std::thread mRunThread; + + ISensorsEventCallback* mCallback; + + OperationMode mMode; +}; + +class OneShotSensor : public Sensor { + public: + OneShotSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + virtual void batch(int32_t /* samplingPeriodNs */) override {} + + virtual Result flush() override { return Result::BAD_VALUE; } +}; + +class SysfsPollingOneShotSensor : public OneShotSensor { + public: + SysfsPollingOneShotSensor(int32_t sensorHandle, ISensorsEventCallback* callback, + const std::string& pollPath, const std::string& enablePath, + const std::string& name, const std::string& typeAsString, + SensorType type); + virtual ~SysfsPollingOneShotSensor() override; + + virtual void activate(bool enable) override; + virtual void activate(bool enable, bool notify, bool lock); + virtual void writeEnable(bool enable); + virtual void setOperationMode(OperationMode mode) override; + virtual std::vector readEvents() override; + virtual void fillEventData(Event& event); + + protected: + virtual void run() override; + + std::ofstream mEnableStream; + + private: + void interruptPoll(); + + struct pollfd mPolls[2]; + int mWaitPipeFd[2]; + int mPollFd; +}; + +const std::string kTsPath = "/sys/devices/platform/soc/a94000.spi/spi_master/spi0/spi0.0/touchscreen/primary/"; + +const std::string kTsDoubleTapPressedPath = kTsPath + "double_tap_pressed"; +const std::string kTsDoubleTapEnabledPath = kTsPath + "double_tap_enabled"; + +class DoubleTapSensor : public SysfsPollingOneShotSensor { + public: + DoubleTapSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : SysfsPollingOneShotSensor( + sensorHandle, callback, kTsDoubleTapPressedPath, kTsDoubleTapEnabledPath, + "Double Tap Sensor", "org.lineageos.sensor.double_tap", + static_cast(static_cast(SensorType::DEVICE_PRIVATE_BASE) + 1)) {} +}; + +const std::string kTsUdfpsPressedPath = kTsPath + "udfps_pressed"; +const std::string kTsUdfpsEnabledPath = kTsPath + "udfps_enabled"; + +class UdfpsSensor : public SysfsPollingOneShotSensor { + public: + UdfpsSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : SysfsPollingOneShotSensor( + sensorHandle, callback, kTsUdfpsPressedPath, kTsUdfpsEnabledPath, + "UDFPS Sensor", "org.lineageos.sensor.udfps", + static_cast(static_cast(SensorType::DEVICE_PRIVATE_BASE) + 2)) {} +}; + +} // namespace implementation +} // namespace subhal +} // namespace V2_1 +} // namespace sensors +} // namespace hardware +} // namespace android diff --git a/sensors/SensorsSubHal.cpp b/sensors/SensorsSubHal.cpp new file mode 100644 index 0000000..3c80bb7 --- /dev/null +++ b/sensors/SensorsSubHal.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2019 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. + */ + +#include "SensorsSubHal.h" + +#include +#include + +using ::android::hardware::sensors::V2_1::implementation::ISensorsSubHal; +using ::android::hardware::sensors::V2_1::subhal::implementation::SensorsSubHal; + +namespace android { +namespace hardware { +namespace sensors { +namespace V2_1 { +namespace subhal { +namespace implementation { + +using ::android::hardware::Void; +using ::android::hardware::sensors::V2_0::implementation::ScopedWakelock; + +SensorsSubHal::SensorsSubHal() : mCallback(nullptr), mNextHandle(1) { + AddSensor(); + AddSensor(); +} + +Return SensorsSubHal::getSensorsList_2_1(ISensors::getSensorsList_2_1_cb _hidl_cb) { + std::vector sensors; + for (const auto& sensor : mSensors) { + sensors.push_back(sensor.second->getSensorInfo()); + } + _hidl_cb(sensors); + return Void(); +} + +Return SensorsSubHal::setOperationMode(OperationMode mode) { + for (auto sensor : mSensors) { + sensor.second->setOperationMode(mode); + } + mCurrentOperationMode = mode; + return Result::OK; +} + +Return 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 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 SensorsSubHal::flush(int32_t sensorHandle) { + auto sensor = mSensors.find(sensorHandle); + if (sensor != mSensors.end()) { + return sensor->second->flush(); + } + return Result::BAD_VALUE; +} + +Return SensorsSubHal::injectSensorData_2_1(const Event& event) { + auto sensor = mSensors.find(event.sensorHandle); + if (sensor != mSensors.end()) { + return sensor->second->injectEvent(event); + } + + return Result::BAD_VALUE; +} + +Return SensorsSubHal::registerDirectChannel(const SharedMemInfo& /* mem */, + ISensors::registerDirectChannel_cb _hidl_cb) { + _hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */); + return Return(); +} + +Return SensorsSubHal::unregisterDirectChannel(int32_t /* channelHandle */) { + return Result::INVALID_OPERATION; +} + +Return SensorsSubHal::configDirectReport(int32_t /* sensorHandle */, + int32_t /* channelHandle */, RateLevel /* rate */, + ISensors::configDirectReport_cb _hidl_cb) { + _hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */); + return Return(); +} + +Return SensorsSubHal::debug(const hidl_handle& fd, const hidl_vec& 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(); + stream << "Name: " << info.name << std::endl; + stream << "Min delay: " << info.minDelay << std::endl; + stream << "Flags: " << info.flags << std::endl; + } + stream << std::endl; + + fprintf(out, "%s", stream.str().c_str()); + + fclose(out); + return Return(); +} + +Return SensorsSubHal::initialize(const sp& halProxyCallback) { + mCallback = halProxyCallback; + setOperationMode(OperationMode::NORMAL); + return Result::OK; +} + +void SensorsSubHal::postEvents(const std::vector& events, bool wakeup) { + ScopedWakelock wakelock = mCallback->createScopedWakelock(wakeup); + mCallback->postEvents(events, std::move(wakelock)); +} + +} // namespace implementation +} // namespace subhal +} // namespace V2_1 +} // namespace sensors +} // namespace hardware +} // namespace android + +ISensorsSubHal* sensorsHalGetSubHal_2_1(uint32_t* version) { + static SensorsSubHal subHal; + *version = SUB_HAL_2_1_VERSION; + return &subHal; +} diff --git a/sensors/SensorsSubHal.h b/sensors/SensorsSubHal.h new file mode 100644 index 0000000..6dccd42 --- /dev/null +++ b/sensors/SensorsSubHal.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include + +#include "Sensor.h" +#include "V2_1/SubHal.h" + +namespace android { +namespace hardware { +namespace sensors { +namespace V2_1 { +namespace subhal { +namespace implementation { + +using ::android::hardware::sensors::V1_0::OperationMode; +using ::android::hardware::sensors::V1_0::RateLevel; +using ::android::hardware::sensors::V1_0::Result; +using ::android::hardware::sensors::V1_0::SharedMemInfo; +using ::android::hardware::sensors::V2_1::Event; +using ::android::hardware::sensors::V2_1::implementation::IHalProxyCallback; +using ::android::hardware::sensors::V2_1::implementation::ISensorsSubHal; + +class SensorsSubHal : public ISensorsSubHal, public ISensorsEventCallback { + public: + SensorsSubHal(); + + Return getSensorsList_2_1(ISensors::getSensorsList_2_1_cb _hidl_cb); + Return injectSensorData_2_1(const Event& event); + Return initialize(const sp& halProxyCallback); + + virtual Return setOperationMode(OperationMode mode); + + OperationMode getOperationMode() const { return mCurrentOperationMode; } + + Return activate(int32_t sensorHandle, bool enabled); + + Return batch(int32_t sensorHandle, int64_t samplingPeriodNs, int64_t maxReportLatencyNs); + + Return flush(int32_t sensorHandle); + + Return registerDirectChannel(const SharedMemInfo& mem, + ISensors::registerDirectChannel_cb _hidl_cb); + + Return unregisterDirectChannel(int32_t channelHandle); + + Return configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate, + ISensors::configDirectReport_cb _hidl_cb); + + Return debug(const hidl_handle& fd, const hidl_vec& args); + + const std::string getName() { return "FakeSubHal"; } + + void postEvents(const std::vector& events, bool wakeup) override; + + protected: + template + void AddSensor() { + std::shared_ptr sensor = + std::make_shared(mNextHandle++ /* sensorHandle */, this /* callback */); + mSensors[sensor->getSensorInfo().sensorHandle] = sensor; + } + + std::map> mSensors; + + sp mCallback; + + private: + OperationMode mCurrentOperationMode = OperationMode::NORMAL; + + int32_t mNextHandle; +}; + +} // namespace implementation +} // namespace subhal +} // namespace V2_1 +} // namespace sensors +} // namespace hardware +} // namespace android diff --git a/configs/sensors/hals.conf b/sensors/hals.conf similarity index 100% rename from configs/sensors/hals.conf rename to sensors/hals.conf