1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <aidl/android/hardware/common/fmq/SynchronizedReadWrite.h> 20 #include <aidl/android/hardware/sensors/BnSensors.h> 21 #include <fmq/AidlMessageQueue.h> 22 #include <hardware_legacy/power.h> 23 #include <map> 24 #include "Sensor.h" 25 26 namespace aidl { 27 namespace android { 28 namespace hardware { 29 namespace sensors { 30 31 using aidl::android::hardware::common::fmq::SynchronizedReadWrite; 32 using ::android::AidlMessageQueue; 33 using ::android::OK; 34 using ::android::status_t; 35 using ::android::hardware::EventFlag; 36 37 class Sensors : public BnSensors, public ISensorsEventCallback { 38 static constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP"; 39 40 public: Sensors()41 Sensors() 42 : mEventQueueFlag(nullptr), 43 mNextHandle(1), 44 mOutstandingWakeUpEvents(0), 45 mReadWakeLockQueueRun(false), 46 mAutoReleaseWakeLockTime(0), 47 mHasWakeLock(false) { 48 AddSensor<AccelSensor>(); 49 AddSensor<GyroSensor>(); 50 AddSensor<AmbientTempSensor>(); 51 AddSensor<PressureSensor>(); 52 AddSensor<MagnetometerSensor>(); 53 AddSensor<LightSensor>(); 54 AddSensor<ProximitySensor>(); 55 AddSensor<RelativeHumiditySensor>(); 56 AddSensor<HingeAngleSensor>(); 57 } 58 ~Sensors()59 virtual ~Sensors() { 60 deleteEventFlag(); 61 mReadWakeLockQueueRun = false; 62 mWakeLockThread.join(); 63 } 64 65 ::ndk::ScopedAStatus activate(int32_t in_sensorHandle, bool in_enabled) override; 66 ::ndk::ScopedAStatus batch(int32_t in_sensorHandle, int64_t in_samplingPeriodNs, 67 int64_t in_maxReportLatencyNs) override; 68 ::ndk::ScopedAStatus configDirectReport( 69 int32_t in_sensorHandle, int32_t in_channelHandle, 70 ::aidl::android::hardware::sensors::ISensors::RateLevel in_rate, 71 int32_t* _aidl_return) override; 72 ::ndk::ScopedAStatus flush(int32_t in_sensorHandle) override; 73 ::ndk::ScopedAStatus getSensorsList( 74 std::vector<::aidl::android::hardware::sensors::SensorInfo>* _aidl_return) override; 75 ::ndk::ScopedAStatus initialize( 76 const ::aidl::android::hardware::common::fmq::MQDescriptor< 77 ::aidl::android::hardware::sensors::Event, 78 ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>& 79 in_eventQueueDescriptor, 80 const ::aidl::android::hardware::common::fmq::MQDescriptor< 81 int32_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>& 82 in_wakeLockDescriptor, 83 const std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback>& 84 in_sensorsCallback) override; 85 ::ndk::ScopedAStatus injectSensorData( 86 const ::aidl::android::hardware::sensors::Event& in_event) override; 87 ::ndk::ScopedAStatus registerDirectChannel( 88 const ::aidl::android::hardware::sensors::ISensors::SharedMemInfo& in_mem, 89 int32_t* _aidl_return) override; 90 ::ndk::ScopedAStatus setOperationMode( 91 ::aidl::android::hardware::sensors::ISensors::OperationMode in_mode) override; 92 ::ndk::ScopedAStatus unregisterDirectChannel(int32_t in_channelHandle) override; 93 postEvents(const std::vector<Event> & events,bool wakeup)94 void postEvents(const std::vector<Event>& events, bool wakeup) override { 95 std::lock_guard<std::mutex> lock(mWriteLock); 96 if (mEventQueue == nullptr) { 97 return; 98 } 99 if (mEventQueue->write(&events.front(), events.size())) { 100 mEventQueueFlag->wake( 101 static_cast<uint32_t>(BnSensors::EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS)); 102 103 if (wakeup) { 104 // Keep track of the number of outstanding WAKE_UP events in order to properly hold 105 // a wake lock until the framework has secured a wake lock 106 updateWakeLock(events.size(), 0 /* eventsHandled */); 107 } 108 } 109 } 110 111 protected: 112 // Add a new sensor 113 template <class SensorType> AddSensor()114 void AddSensor() { 115 std::shared_ptr<SensorType> sensor = 116 std::make_shared<SensorType>(mNextHandle++ /* sensorHandle */, this /* callback */); 117 mSensors[sensor->getSensorInfo().sensorHandle] = sensor; 118 } 119 120 // Utility function to delete the Event Flag deleteEventFlag()121 void deleteEventFlag() { 122 // Hold the lock to ensure we don't delete the flag while it's being used in postEvents() 123 std::lock_guard<std::mutex> lock(mWriteLock); 124 if (mEventQueueFlag != nullptr) { 125 status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag); 126 if (status != OK) { 127 ALOGI("Failed to delete event flag: %d", status); 128 } 129 } 130 } 131 startReadWakeLockThread(Sensors * sensors)132 static void startReadWakeLockThread(Sensors* sensors) { sensors->readWakeLockFMQ(); } 133 134 // Function to read the Wake Lock FMQ and release the wake lock when appropriate readWakeLockFMQ()135 void readWakeLockFMQ() { 136 while (mReadWakeLockQueueRun.load()) { 137 constexpr int64_t kReadTimeoutNs = 500 * 1000 * 1000; // 500 ms 138 int32_t eventsHandled = 0; 139 140 // Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to 141 // ensure that any held wake lock is able to be released if it is held for too long. 142 mWakeLockQueue->readBlocking( 143 &eventsHandled, 1 /* count */, 0 /* readNotification */, 144 static_cast<uint32_t>(WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN), kReadTimeoutNs); 145 updateWakeLock(0 /* eventsWritten */, eventsHandled); 146 } 147 } 148 149 /** 150 * Responsible for acquiring and releasing a wake lock when there are unhandled WAKE_UP events 151 */ updateWakeLock(int32_t eventsWritten,int32_t eventsHandled)152 void updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) { 153 std::lock_guard<std::mutex> lock(mWakeLockLock); 154 int32_t newVal = mOutstandingWakeUpEvents + eventsWritten - eventsHandled; 155 if (newVal < 0) { 156 mOutstandingWakeUpEvents = 0; 157 } else { 158 mOutstandingWakeUpEvents = newVal; 159 } 160 161 if (eventsWritten > 0) { 162 // Update the time at which the last WAKE_UP event was sent 163 mAutoReleaseWakeLockTime = ::android::uptimeMillis() + 164 static_cast<uint32_t>(WAKE_LOCK_TIMEOUT_SECONDS) * 1000; 165 } 166 167 if (!mHasWakeLock && mOutstandingWakeUpEvents > 0 && 168 acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) == 0) { 169 mHasWakeLock = true; 170 } else if (mHasWakeLock) { 171 // Check if the wake lock should be released automatically if 172 // SensorTimeout::WAKE_LOCK_SECONDS has elapsed since the last WAKE_UP event was written 173 // to the Wake Lock FMQ. 174 if (::android::uptimeMillis() > mAutoReleaseWakeLockTime) { 175 ALOGD("No events read from wake lock FMQ for %d seconds, auto releasing wake lock", 176 WAKE_LOCK_TIMEOUT_SECONDS); 177 mOutstandingWakeUpEvents = 0; 178 } 179 180 if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) { 181 mHasWakeLock = false; 182 } 183 } 184 } 185 186 private: 187 // The Event FMQ where sensor events are written 188 std::unique_ptr<AidlMessageQueue<Event, SynchronizedReadWrite>> mEventQueue; 189 // The Wake Lock FMQ that is read to determine when the framework has handled WAKE_UP events 190 std::unique_ptr<AidlMessageQueue<int32_t, SynchronizedReadWrite>> mWakeLockQueue; 191 // Event Flag to signal to the framework when sensor events are available to be read 192 EventFlag* mEventQueueFlag; 193 // Callback for asynchronous events, such as dynamic sensor connections. 194 std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback> mCallback; 195 // A map of the available sensors. 196 std::map<int32_t, std::shared_ptr<Sensor>> mSensors; 197 // The next available sensor handle. 198 int32_t mNextHandle; 199 // Lock to protect writes to the FMQs. 200 std::mutex mWriteLock; 201 // Lock to protect acquiring and releasing the wake lock 202 std::mutex mWakeLockLock; 203 // Track the number of WAKE_UP events that have not been handled by the framework 204 uint32_t mOutstandingWakeUpEvents; 205 // A thread to read the Wake Lock FMQ 206 std::thread mWakeLockThread; 207 // Flag to indicate that the Wake Lock Thread should continue to run 208 std::atomic_bool mReadWakeLockQueueRun; 209 // Track the time when the wake lock should automatically be released 210 int64_t mAutoReleaseWakeLockTime; 211 // Flag to indicate if a wake lock has been acquired 212 bool mHasWakeLock; 213 }; 214 215 } // namespace sensors 216 } // namespace hardware 217 } // namespace android 218 } // namespace aidl 219