/* * Copyright (C) 2018 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. */ #ifndef ANDROID_HARDWARE_SENSORS_V2_X_SENSORS_H #define ANDROID_HARDWARE_SENSORS_V2_X_SENSORS_H #include "EventMessageQueueWrapper.h" #include "Sensor.h" #include #include #include #include #include #include #include #include #include #include namespace android { namespace hardware { namespace sensors { namespace V2_X { namespace implementation { template struct Sensors : public ISensorsInterface, public ISensorsEventCallback { using Event = ::android::hardware::sensors::V1_0::Event; using OperationMode = ::android::hardware::sensors::V1_0::OperationMode; using RateLevel = ::android::hardware::sensors::V1_0::RateLevel; using Result = ::android::hardware::sensors::V1_0::Result; using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo; using EventQueueFlagBits = ::android::hardware::sensors::V2_0::EventQueueFlagBits; using SensorTimeout = ::android::hardware::sensors::V2_0::SensorTimeout; using WakeLockQueueFlagBits = ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits; using ISensorsCallback = ::android::hardware::sensors::V2_0::ISensorsCallback; using EventMessageQueue = MessageQueue; using WakeLockMessageQueue = MessageQueue; static constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP"; Sensors() : mEventQueueFlag(nullptr), mNextHandle(1), mOutstandingWakeUpEvents(0), mReadWakeLockQueueRun(false), mAutoReleaseWakeLockTime(0), mHasWakeLock(false) { AddSensor(); AddSensor(); AddSensor(); AddSensor(); AddSensor(); AddSensor(); AddSensor(); AddSensor(); } virtual ~Sensors() { deleteEventFlag(); mReadWakeLockQueueRun = false; mWakeLockThread.join(); } // Methods from ::android::hardware::sensors::V2_0::ISensors follow. Return setOperationMode(OperationMode mode) override { for (auto sensor : mSensors) { sensor.second->setOperationMode(mode); } return Result::OK; } Return activate(int32_t sensorHandle, bool enabled) override { auto sensor = mSensors.find(sensorHandle); if (sensor != mSensors.end()) { sensor->second->activate(enabled); return Result::OK; } return Result::BAD_VALUE; } Return initialize( const ::android::hardware::MQDescriptorSync& eventQueueDescriptor, const ::android::hardware::MQDescriptorSync& wakeLockDescriptor, const sp& sensorsCallback) override { auto eventQueue = std::make_unique(eventQueueDescriptor, true /* resetPointers */); std::unique_ptr wrapper = std::make_unique(eventQueue); return initializeBase(wrapper, wakeLockDescriptor, sensorsCallback); } Return initializeBase( std::unique_ptr& eventQueue, const ::android::hardware::MQDescriptorSync& wakeLockDescriptor, const sp& sensorsCallback) { Result result = Result::OK; // Ensure that all sensors are disabled for (auto sensor : mSensors) { sensor.second->activate(false /* enable */); } // Stop the Wake Lock thread if it is currently running if (mReadWakeLockQueueRun.load()) { mReadWakeLockQueueRun = false; mWakeLockThread.join(); } // Save a reference to the callback mCallback = sensorsCallback; // Save the event queue. mEventQueue = std::move(eventQueue); // 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 = Result::BAD_VALUE; } // 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(wakeLockDescriptor, true /* resetPointers */); if (!mCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) { result = Result::BAD_VALUE; } // Start the thread to read events from the Wake Lock FMQ mReadWakeLockQueueRun = true; mWakeLockThread = std::thread(startReadWakeLockThread, this); return result; } Return batch(int32_t sensorHandle, int64_t samplingPeriodNs, int64_t /* maxReportLatencyNs */) override { auto sensor = mSensors.find(sensorHandle); if (sensor != mSensors.end()) { sensor->second->batch(samplingPeriodNs); return Result::OK; } return Result::BAD_VALUE; } Return flush(int32_t sensorHandle) override { auto sensor = mSensors.find(sensorHandle); if (sensor != mSensors.end()) { return sensor->second->flush(); } return Result::BAD_VALUE; } Return injectSensorData(const Event& event) override { auto sensor = mSensors.find(event.sensorHandle); if (sensor != mSensors.end()) { return sensor->second->injectEvent(V2_1::implementation::convertToNewEvent(event)); } return Result::BAD_VALUE; } Return registerDirectChannel(const SharedMemInfo& /* mem */, V2_0::ISensors::registerDirectChannel_cb _hidl_cb) override { _hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */); return Return(); } Return unregisterDirectChannel(int32_t /* channelHandle */) override { return Result::INVALID_OPERATION; } Return configDirectReport(int32_t /* sensorHandle */, int32_t /* channelHandle */, RateLevel /* rate */, V2_0::ISensors::configDirectReport_cb _hidl_cb) override { _hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */); return Return(); } void postEvents(const std::vector& events, bool wakeup) override { std::lock_guard lock(mWriteLock); if (mEventQueue->write(events)) { mEventQueueFlag->wake(static_cast(EventQueueFlagBits::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() { 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 uint32_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(WakeLockQueueFlagBits::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(SensorTimeout::WAKE_LOCK_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", SensorTimeout::WAKE_LOCK_SECONDS); mOutstandingWakeUpEvents = 0; } if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) { mHasWakeLock = false; } } } /** * 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. */ sp 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 implementation } // namespace V2_X } // namespace sensors } // namespace hardware } // namespace android #endif // ANDROID_HARDWARE_SENSORS_V2_X_SENSORS_H