diff --git a/sensors/aidl/default/Android.bp b/sensors/aidl/default/Android.bp index 487387d1ce..49841a456b 100644 --- a/sensors/aidl/default/Android.bp +++ b/sensors/aidl/default/Android.bp @@ -28,12 +28,15 @@ cc_library_static { vendor: true, shared_libs: [ "libbase", + "libfmq", + "libpower", "libbinder_ndk", "android.hardware.sensors-V1-ndk", ], export_include_dirs: ["include"], srcs: [ "Sensors.cpp", + "Sensor.cpp", ], visibility: [ ":__subpackages__", @@ -50,6 +53,11 @@ cc_binary { shared_libs: [ "libbase", "libbinder_ndk", + "libfmq", + "libpower", + "libcutils", + "liblog", + "libutils", "android.hardware.sensors-V1-ndk", ], static_libs: [ diff --git a/sensors/aidl/default/Sensor.cpp b/sensors/aidl/default/Sensor.cpp new file mode 100644 index 0000000000..50d8841b2a --- /dev/null +++ b/sensors/aidl/default/Sensor.cpp @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2021 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 "sensors-impl/Sensor.h" + +#include "utils/SystemClock.h" + +#include + +using ::ndk::ScopedAStatus; + +namespace aidl { +namespace android { +namespace hardware { +namespace sensors { + +static constexpr int32_t kDefaultMaxDelayUs = 10 * 1000 * 1000; + +Sensor::Sensor(ISensorsEventCallback* callback) + : mIsEnabled(false), + mSamplingPeriodNs(0), + mLastSampleTimeNs(0), + mCallback(callback), + mMode(OperationMode::NORMAL) { + mRunThread = std::thread(startThread, this); +} + +Sensor::~Sensor() { + std::unique_lock lock(mRunMutex); + mStopThread = true; + mIsEnabled = false; + mWaitCV.notify_all(); + lock.release(); + mRunThread.join(); +} + +const SensorInfo& Sensor::getSensorInfo() const { + return mSensorInfo; +} + +void Sensor::batch(int64_t samplingPeriodNs) { + if (samplingPeriodNs < mSensorInfo.minDelayUs * 1000ll) { + samplingPeriodNs = mSensorInfo.minDelayUs * 1000ll; + } else if (samplingPeriodNs > mSensorInfo.maxDelayUs * 1000ll) { + samplingPeriodNs = mSensorInfo.maxDelayUs * 1000ll; + } + + 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) { + if (mIsEnabled != enable) { + std::unique_lock lock(mRunMutex); + mIsEnabled = enable; + mWaitCV.notify_all(); + } +} + +ScopedAStatus 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 || + (mSensorInfo.flags & static_cast(SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE))) { + return ScopedAStatus::fromServiceSpecificError( + static_cast(BnSensors::ERROR_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; + EventPayload::MetaData meta = { + .what = MetaDataEventType::META_DATA_FLUSH_COMPLETE, + }; + ev.payload.set(meta); + std::vector evs{ev}; + mCallback->postEvents(evs, isWakeUpSensor()); + + return ScopedAStatus::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_BOOTTIME, &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(SensorInfo::SENSOR_FLAG_BITS_WAKE_UP); +} + +std::vector Sensor::readEvents() { + std::vector events; + Event event; + event.sensorHandle = mSensorInfo.sensorHandle; + event.sensorType = mSensorInfo.type; + event.timestamp = ::android::elapsedRealtimeNano(); + memset(&event.payload, 0, sizeof(event.payload)); + readEventPayload(event.payload); + events.push_back(event); + return events; +} + +void Sensor::setOperationMode(OperationMode mode) { + if (mMode != mode) { + std::unique_lock lock(mRunMutex); + mMode = mode; + mWaitCV.notify_all(); + } +} + +bool Sensor::supportsDataInjection() const { + return mSensorInfo.flags & static_cast(SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION); +} + +ScopedAStatus Sensor::injectEvent(const Event& event) { + if (event.sensorType == SensorType::ADDITIONAL_INFO) { + return ScopedAStatus::ok(); + // When in OperationMode::NORMAL, SensorType::ADDITIONAL_INFO is used to push operation + // environment data into the device. + } + + if (!supportsDataInjection()) { + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + } + + if (mMode == OperationMode::DATA_INJECTION) { + mCallback->postEvents(std::vector{event}, isWakeUpSensor()); + return ScopedAStatus::ok(); + } + + return ScopedAStatus::fromServiceSpecificError( + static_cast(BnSensors::ERROR_BAD_VALUE)); +} + +OnChangeSensor::OnChangeSensor(ISensorsEventCallback* callback) + : Sensor(callback), mPreviousEventSet(false) {} + +void OnChangeSensor::activate(bool enable) { + Sensor::activate(enable); + if (!enable) { + mPreviousEventSet = false; + } +} + +std::vector OnChangeSensor::readEvents() { + std::vector events = Sensor::readEvents(); + std::vector outputEvents; + + for (auto iter = events.begin(); iter != events.end(); ++iter) { + Event ev = *iter; + if (!mPreviousEventSet || + memcmp(&mPreviousEvent.payload, &ev.payload, sizeof(ev.payload)) != 0) { + outputEvents.push_back(ev); + mPreviousEvent = ev; + mPreviousEventSet = true; + } + } + return outputEvents; +} + +AccelSensor::AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Accel Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::ACCELEROMETER; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 78.4f; // +/- 8g + mSensorInfo.resolution = 1.52e-5; + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelayUs = 10 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION); +}; + +void AccelSensor::readEventPayload(EventPayload& payload) { + EventPayload::Vec3 vec3 = { + .x = 0, + .y = 0, + .z = -9.8, + .status = SensorStatus::ACCURACY_HIGH, + }; + payload.set(vec3); +} + +PressureSensor::PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Pressure Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::PRESSURE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 1100.0f; // hPa + mSensorInfo.resolution = 0.005f; // hPa + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelayUs = 100 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +void PressureSensor::readEventPayload(EventPayload& payload) { + payload.set(1013.25f); +} + +MagnetometerSensor::MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Magnetic Field Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::MAGNETIC_FIELD; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 1300.0f; + mSensorInfo.resolution = 0.01f; + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelayUs = 20 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +void MagnetometerSensor::readEventPayload(EventPayload& payload) { + EventPayload::Vec3 vec3 = { + .x = 100.0, + .y = 0, + .z = 50.0, + .status = SensorStatus::ACCURACY_HIGH, + }; + payload.set(vec3); +} + +LightSensor::LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Light Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::LIGHT; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 43000.0f; + mSensorInfo.resolution = 10.0f; + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelayUs = 200 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE); +}; + +void LightSensor::readEventPayload(EventPayload& payload) { + payload.set(80.0f); +} + +ProximitySensor::ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Proximity Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::PROXIMITY; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 5.0f; + mSensorInfo.resolution = 1.0f; + mSensorInfo.power = 0.012f; // mA + mSensorInfo.minDelayUs = 200 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE | + SensorInfo::SENSOR_FLAG_BITS_WAKE_UP); +}; + +void ProximitySensor::readEventPayload(EventPayload& payload) { + payload.set(2.5f); +} + +GyroSensor::GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Gyro Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::GYROSCOPE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 1000.0f * M_PI / 180.0f; + mSensorInfo.resolution = 1000.0f * M_PI / (180.0f * 32768.0f); + mSensorInfo.power = 0.001f; + mSensorInfo.minDelayUs = 10 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +void GyroSensor::readEventPayload(EventPayload& payload) { + EventPayload::Vec3 vec3 = { + .x = 0, + .y = 0, + .z = 0, + .status = SensorStatus::ACCURACY_HIGH, + }; + payload.set(vec3); +} + +AmbientTempSensor::AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Ambient Temp Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::AMBIENT_TEMPERATURE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 80.0f; + mSensorInfo.resolution = 0.01f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelayUs = 40 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE); +}; + +void AmbientTempSensor::readEventPayload(EventPayload& payload) { + payload.set(40.0f); +} + +RelativeHumiditySensor::RelativeHumiditySensor(int32_t sensorHandle, + ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Relative Humidity Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::RELATIVE_HUMIDITY; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 100.0f; + mSensorInfo.resolution = 0.1f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelayUs = 40 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE); +} + +void RelativeHumiditySensor::readEventPayload(EventPayload& payload) { + payload.set(50.0f); +} + +HingeAngleSensor::HingeAngleSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Hinge Angle Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::HINGE_ANGLE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 360.0f; + mSensorInfo.resolution = 1.0f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelayUs = 40 * 1000; // microseconds + mSensorInfo.maxDelayUs = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE | + SensorInfo::SENSOR_FLAG_BITS_WAKE_UP | + SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION); +} + +void HingeAngleSensor::readEventPayload(EventPayload& payload) { + payload.set(180.0f); +} + +} // namespace sensors +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/sensors/aidl/default/Sensors.cpp b/sensors/aidl/default/Sensors.cpp index 14bbbbf7f4..65dd304b2c 100644 --- a/sensors/aidl/default/Sensors.cpp +++ b/sensors/aidl/default/Sensors.cpp @@ -16,66 +16,139 @@ #include "sensors-impl/Sensors.h" +#include + using ::aidl::android::hardware::common::fmq::MQDescriptor; using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite; using ::aidl::android::hardware::sensors::Event; using ::aidl::android::hardware::sensors::ISensors; using ::aidl::android::hardware::sensors::ISensorsCallback; using ::aidl::android::hardware::sensors::SensorInfo; +using ::ndk::ScopedAStatus; namespace aidl { namespace android { namespace hardware { namespace sensors { -// TODO(b/195593357): Implement AIDL HAL -::ndk::ScopedAStatus Sensors::activate(int32_t /* in_sensorHandle */, bool /* in_enabled */) { - return ndk::ScopedAStatus::ok(); +ScopedAStatus Sensors::activate(int32_t in_sensorHandle, bool in_enabled) { + auto sensor = mSensors.find(in_sensorHandle); + if (sensor != mSensors.end()) { + sensor->second->activate(in_enabled); + return ScopedAStatus::ok(); + } + + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } -::ndk::ScopedAStatus Sensors::batch(int32_t /* in_sensorHandle */, - int64_t /* in_samplingPeriodNs */, - int64_t /* in_maxReportLatencyNs */) { - return ndk::ScopedAStatus::ok(); +ScopedAStatus Sensors::batch(int32_t in_sensorHandle, int64_t in_samplingPeriodNs, + int64_t /* in_maxReportLatencyNs */) { + auto sensor = mSensors.find(in_sensorHandle); + if (sensor != mSensors.end()) { + sensor->second->batch(in_samplingPeriodNs); + return ScopedAStatus::ok(); + } + + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } -::ndk::ScopedAStatus Sensors::configDirectReport(int32_t /* in_sensorHandle */, - int32_t /* in_channelHandle */, - ISensors::RateLevel /* in_rate */, - int32_t* /* _aidl_return */) { - return ndk::ScopedAStatus::ok(); +ScopedAStatus Sensors::configDirectReport(int32_t /* in_sensorHandle */, + int32_t /* in_channelHandle */, + ISensors::RateLevel /* in_rate */, + int32_t* _aidl_return) { + *_aidl_return = EX_UNSUPPORTED_OPERATION; + + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } -::ndk::ScopedAStatus Sensors::flush(int32_t /* in_sensorHandle */) { - return ndk::ScopedAStatus::ok(); +ScopedAStatus Sensors::flush(int32_t in_sensorHandle) { + auto sensor = mSensors.find(in_sensorHandle); + if (sensor != mSensors.end()) { + return sensor->second->flush(); + } + + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); } -::ndk::ScopedAStatus Sensors::getSensorsList(std::vector* /* _aidl_return */) { - return ndk::ScopedAStatus::ok(); +ScopedAStatus Sensors::getSensorsList(std::vector* _aidl_return) { + for (const auto& sensor : mSensors) { + _aidl_return->push_back(sensor.second->getSensorInfo()); + } + return ScopedAStatus::ok(); } -::ndk::ScopedAStatus Sensors::initialize( - const MQDescriptor& /* in_eventQueueDescriptor */, - const MQDescriptor& /* in_wakeLockDescriptor */, - const std::shared_ptr& /* in_sensorsCallback */) { - return ndk::ScopedAStatus::ok(); +ScopedAStatus Sensors::initialize( + const MQDescriptor& in_eventQueueDescriptor, + const MQDescriptor& in_wakeLockDescriptor, + const std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback>& + in_sensorsCallback) { + ScopedAStatus result = ScopedAStatus::ok(); + + mEventQueue = std::make_unique>( + in_eventQueueDescriptor, true /* resetPointers */); + + // Ensure that all sensors are disabled. + for (auto sensor : mSensors) { + sensor.second->activate(false); + } + + // Stop the Wake Lock thread if it is currently running + if (mReadWakeLockQueueRun.load()) { + mReadWakeLockQueueRun = false; + mWakeLockThread.join(); + } + + // Save a reference to the callback + mCallback = in_sensorsCallback; + + // Ensure that any existing EventFlag is properly deleted + deleteEventFlag(); + + // Create the EventFlag that is used to signal to the framework that sensor events have been + // written to the Event FMQ + if (EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag) != OK) { + result = ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + // Create the Wake Lock FMQ that is used by the framework to communicate whenever WAKE_UP + // events have been successfully read and handled by the framework. + mWakeLockQueue = std::make_unique>( + in_wakeLockDescriptor, true /* resetPointers */); + + if (!mCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) { + result = ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + // Start the thread to read events from the Wake Lock FMQ + mReadWakeLockQueueRun = true; + mWakeLockThread = std::thread(startReadWakeLockThread, this); + return result; } -::ndk::ScopedAStatus Sensors::injectSensorData(const Event& /* in_event */) { - return ndk::ScopedAStatus::ok(); +ScopedAStatus Sensors::injectSensorData(const Event& in_event) { + auto sensor = mSensors.find(in_event.sensorHandle); + if (sensor != mSensors.end()) { + return sensor->second->injectEvent(in_event); + } + return ScopedAStatus::fromServiceSpecificError(static_cast(ERROR_BAD_VALUE)); } -::ndk::ScopedAStatus Sensors::registerDirectChannel(const ISensors::SharedMemInfo& /* in_mem */, - int32_t* /* _aidl_return */) { - return ndk::ScopedAStatus::ok(); +ScopedAStatus Sensors::registerDirectChannel(const ISensors::SharedMemInfo& /* in_mem */, + int32_t* _aidl_return) { + *_aidl_return = EX_UNSUPPORTED_OPERATION; + + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } -::ndk::ScopedAStatus Sensors::setOperationMode(OperationMode /* in_mode */) { - return ndk::ScopedAStatus::ok(); +ScopedAStatus Sensors::setOperationMode(OperationMode in_mode) { + for (auto sensor : mSensors) { + sensor.second->setOperationMode(in_mode); + } + return ScopedAStatus::ok(); } -::ndk::ScopedAStatus Sensors::unregisterDirectChannel(int32_t /* in_channelHandle */) { - return ndk::ScopedAStatus::ok(); +ScopedAStatus Sensors::unregisterDirectChannel(int32_t /* in_channelHandle */) { + return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } } // namespace sensors diff --git a/sensors/aidl/default/include/sensors-impl/Sensor.h b/sensors/aidl/default/include/sensors-impl/Sensor.h new file mode 100644 index 0000000000..e6cd3e6970 --- /dev/null +++ b/sensors/aidl/default/include/sensors-impl/Sensor.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2021 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 + +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace sensors { + +class ISensorsEventCallback { + public: + using Event = ::aidl::android::hardware::sensors::Event; + + virtual ~ISensorsEventCallback(){}; + virtual void postEvents(const std::vector& events, bool wakeup) = 0; +}; + +class Sensor { + public: + using OperationMode = ::aidl::android::hardware::sensors::ISensors::OperationMode; + using Event = ::aidl::android::hardware::sensors::Event; + using EventPayload = ::aidl::android::hardware::sensors::Event::EventPayload; + using SensorInfo = ::aidl::android::hardware::sensors::SensorInfo; + using SensorType = ::aidl::android::hardware::sensors::SensorType; + using MetaDataEventType = + ::aidl::android::hardware::sensors::Event::EventPayload::MetaData::MetaDataEventType; + + Sensor(ISensorsEventCallback* callback); + virtual ~Sensor(); + + const SensorInfo& getSensorInfo() const; + void batch(int64_t samplingPeriodNs); + virtual void activate(bool enable); + ndk::ScopedAStatus flush(); + + void setOperationMode(OperationMode mode); + bool supportsDataInjection() const; + ndk::ScopedAStatus injectEvent(const Event& event); + + protected: + void run(); + virtual std::vector readEvents(); + virtual void readEventPayload(EventPayload&) = 0; + 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 OnChangeSensor : public Sensor { + public: + OnChangeSensor(ISensorsEventCallback* callback); + + virtual void activate(bool enable) override; + + protected: + virtual std::vector readEvents() override; + + protected: + Event mPreviousEvent; + bool mPreviousEventSet; +}; + +class AccelSensor : public Sensor { + public: + AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class GyroSensor : public Sensor { + public: + GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class AmbientTempSensor : public OnChangeSensor { + public: + AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class PressureSensor : public Sensor { + public: + PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class MagnetometerSensor : public Sensor { + public: + MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class LightSensor : public OnChangeSensor { + public: + LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class ProximitySensor : public OnChangeSensor { + public: + ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class RelativeHumiditySensor : public OnChangeSensor { + public: + RelativeHumiditySensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +class HingeAngleSensor : public OnChangeSensor { + public: + HingeAngleSensor(int32_t sensorHandle, ISensorsEventCallback* callback); + + protected: + virtual void readEventPayload(EventPayload& payload) override; +}; + +} // namespace sensors +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/sensors/aidl/default/include/sensors-impl/Sensors.h b/sensors/aidl/default/include/sensors-impl/Sensors.h index b6be4a5efd..e270d9682e 100644 --- a/sensors/aidl/default/include/sensors-impl/Sensors.h +++ b/sensors/aidl/default/include/sensors-impl/Sensors.h @@ -16,14 +16,52 @@ #pragma once +#include #include +#include +#include +#include +#include "Sensor.h" namespace aidl { namespace android { namespace hardware { namespace sensors { -class Sensors : public BnSensors { +using aidl::android::hardware::common::fmq::SynchronizedReadWrite; +using ::android::AidlMessageQueue; +using ::android::OK; +using ::android::status_t; +using ::android::hardware::EventFlag; + +class Sensors : public BnSensors, public ISensorsEventCallback { + static constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP"; + + public: + Sensors() + : mEventQueueFlag(nullptr), + mNextHandle(1), + mOutstandingWakeUpEvents(0), + mReadWakeLockQueueRun(false), + mAutoReleaseWakeLockTime(0), + mHasWakeLock(false) { + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + } + + virtual ~Sensors() { + deleteEventFlag(); + mReadWakeLockQueueRun = false; + mWakeLockThread.join(); + } + ::ndk::ScopedAStatus activate(int32_t in_sensorHandle, bool in_enabled) override; ::ndk::ScopedAStatus batch(int32_t in_sensorHandle, int64_t in_samplingPeriodNs, int64_t in_maxReportLatencyNs) override; @@ -52,6 +90,124 @@ class Sensors : public BnSensors { ::ndk::ScopedAStatus setOperationMode( ::aidl::android::hardware::sensors::ISensors::OperationMode in_mode) override; ::ndk::ScopedAStatus unregisterDirectChannel(int32_t in_channelHandle) override; + + void postEvents(const std::vector& events, bool wakeup) override { + std::lock_guard lock(mWriteLock); + if (mEventQueue == nullptr) { + return; + } + if (mEventQueue->write(&events.front(), events.size())) { + mEventQueueFlag->wake( + static_cast(BnSensors::EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS)); + + if (wakeup) { + // Keep track of the number of outstanding WAKE_UP events in order to properly hold + // a wake lock until the framework has secured a wake lock + updateWakeLock(events.size(), 0 /* eventsHandled */); + } + } + } + + protected: + // Add a new sensor + template + void AddSensor() { + std::shared_ptr sensor = + std::make_shared(mNextHandle++ /* sensorHandle */, this /* callback */); + mSensors[sensor->getSensorInfo().sensorHandle] = sensor; + } + + // Utility function to delete the Event Flag + void deleteEventFlag() { + if (mEventQueueFlag != nullptr) { + status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag); + if (status != OK) { + ALOGI("Failed to delete event flag: %d", status); + } + } + } + + static void startReadWakeLockThread(Sensors* sensors) { sensors->readWakeLockFMQ(); } + + // Function to read the Wake Lock FMQ and release the wake lock when appropriate + void readWakeLockFMQ() { + while (mReadWakeLockQueueRun.load()) { + constexpr int64_t kReadTimeoutNs = 500 * 1000 * 1000; // 500 ms + int32_t eventsHandled = 0; + + // Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to + // ensure that any held wake lock is able to be released if it is held for too long. + mWakeLockQueue->readBlocking( + &eventsHandled, 1 /* count */, 0 /* readNotification */, + static_cast(WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN), kReadTimeoutNs); + updateWakeLock(0 /* eventsWritten */, eventsHandled); + } + } + + /** + * Responsible for acquiring and releasing a wake lock when there are unhandled WAKE_UP events + */ + void updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) { + std::lock_guard lock(mWakeLockLock); + int32_t newVal = mOutstandingWakeUpEvents + eventsWritten - eventsHandled; + if (newVal < 0) { + mOutstandingWakeUpEvents = 0; + } else { + mOutstandingWakeUpEvents = newVal; + } + + if (eventsWritten > 0) { + // Update the time at which the last WAKE_UP event was sent + mAutoReleaseWakeLockTime = ::android::uptimeMillis() + + static_cast(WAKE_LOCK_TIMEOUT_SECONDS) * 1000; + } + + if (!mHasWakeLock && mOutstandingWakeUpEvents > 0 && + acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) == 0) { + mHasWakeLock = true; + } else if (mHasWakeLock) { + // Check if the wake lock should be released automatically if + // SensorTimeout::WAKE_LOCK_SECONDS has elapsed since the last WAKE_UP event was written + // to the Wake Lock FMQ. + if (::android::uptimeMillis() > mAutoReleaseWakeLockTime) { + ALOGD("No events read from wake lock FMQ for %d seconds, auto releasing wake lock", + WAKE_LOCK_TIMEOUT_SECONDS); + mOutstandingWakeUpEvents = 0; + } + + if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) { + mHasWakeLock = false; + } + } + } + + private: + // The Event FMQ where sensor events are written + std::unique_ptr> mEventQueue; + // The Wake Lock FMQ that is read to determine when the framework has handled WAKE_UP events + std::unique_ptr> mWakeLockQueue; + // Event Flag to signal to the framework when sensor events are available to be read + EventFlag* mEventQueueFlag; + // Callback for asynchronous events, such as dynamic sensor connections. + std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback> mCallback; + // A map of the available sensors. + std::map> mSensors; + // The next available sensor handle. + int32_t mNextHandle; + // Lock to protect writes to the FMQs. + std::mutex mWriteLock; + // Lock to protect acquiring and releasing the wake lock + std::mutex mWakeLockLock; + // Track the number of WAKE_UP events that have not been handled by the framework + uint32_t mOutstandingWakeUpEvents; + // A thread to read the Wake Lock FMQ + std::thread mWakeLockThread; + // Flag to indicate that the Wake Lock Thread should continue to run + std::atomic_bool mReadWakeLockQueueRun; + // Track the time when the wake lock should automatically be released + int64_t mAutoReleaseWakeLockTime; + // Flag to indicate if a wake lock has been acquired + bool mHasWakeLock; }; } // namespace sensors