• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <android-base/thread_annotations.h>
27 
28 namespace aidl {
29 namespace android {
30 namespace hardware {
31 namespace sensors {
32 
33 using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
34 using ::android::AidlMessageQueue;
35 using ::android::OK;
36 using ::android::status_t;
37 using ::android::hardware::EventFlag;
38 
39 class Sensors : public BnSensors, public ISensorsEventCallback {
40     static constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP";
41 
42   public:
Sensors()43     Sensors()
44         : mEventQueueFlag(nullptr),
45           mNextHandle(1),
46           mOutstandingWakeUpEvents(0),
47           mReadWakeLockQueueRun(false),
48           mAutoReleaseWakeLockTime(0),
49           mHasWakeLock(false) {
50         AddSensor<AccelSensor>();
51         AddSensor<GyroSensor>();
52         AddSensor<AmbientTempSensor>();
53         AddSensor<PressureSensor>();
54         AddSensor<MagnetometerSensor>();
55         AddSensor<LightSensor>();
56         AddSensor<ProximitySensor>();
57         AddSensor<RelativeHumiditySensor>();
58         AddSensor<HingeAngleSensor>();
59     }
60 
~Sensors()61     virtual ~Sensors() {
62         deleteEventFlag();
63         mReadWakeLockQueueRun = false;
64         mWakeLockThread.join();
65     }
66 
67     ::ndk::ScopedAStatus activate(int32_t in_sensorHandle, bool in_enabled) override;
68     ::ndk::ScopedAStatus batch(int32_t in_sensorHandle, int64_t in_samplingPeriodNs,
69                                int64_t in_maxReportLatencyNs) override;
70     ::ndk::ScopedAStatus configDirectReport(
71             int32_t in_sensorHandle, int32_t in_channelHandle,
72             ::aidl::android::hardware::sensors::ISensors::RateLevel in_rate,
73             int32_t* _aidl_return) override;
74     ::ndk::ScopedAStatus flush(int32_t in_sensorHandle) override;
75     ::ndk::ScopedAStatus getSensorsList(
76             std::vector<::aidl::android::hardware::sensors::SensorInfo>* _aidl_return) override;
77     ::ndk::ScopedAStatus initialize(
78             const ::aidl::android::hardware::common::fmq::MQDescriptor<
79                     ::aidl::android::hardware::sensors::Event,
80                     ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>&
81                     in_eventQueueDescriptor,
82             const ::aidl::android::hardware::common::fmq::MQDescriptor<
83                     int32_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>&
84                     in_wakeLockDescriptor,
85             const std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback>&
86                     in_sensorsCallback) override;
87     ::ndk::ScopedAStatus injectSensorData(
88             const ::aidl::android::hardware::sensors::Event& in_event) override;
89     ::ndk::ScopedAStatus registerDirectChannel(
90             const ::aidl::android::hardware::sensors::ISensors::SharedMemInfo& in_mem,
91             int32_t* _aidl_return) override;
92     ::ndk::ScopedAStatus setOperationMode(
93             ::aidl::android::hardware::sensors::ISensors::OperationMode in_mode) override;
94     ::ndk::ScopedAStatus unregisterDirectChannel(int32_t in_channelHandle) override;
95 
postEvents(const std::vector<Event> & events,bool wakeup)96     void postEvents(const std::vector<Event>& events, bool wakeup) override {
97         std::lock_guard<std::mutex> lock(mWriteLock);
98         if (mEventQueue == nullptr) {
99             return;
100         }
101         if (mEventQueue->write(&events.front(), events.size())) {
102             if (mEventQueueFlag == nullptr) {
103                 // Don't take the wake lock if we can't wake the receiver to avoid holding it
104                 // indefinitely.
105                 return;
106             }
107             mEventQueueFlag->wake(
108                     static_cast<uint32_t>(BnSensors::EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS));
109             if (wakeup) {
110                 // Keep track of the number of outstanding WAKE_UP events in order to properly hold
111                 // a wake lock until the framework has secured a wake lock
112                 updateWakeLock(events.size(), 0 /* eventsHandled */);
113             }
114         }
115     }
116 
117   protected:
118     // Add a new sensor
119     template <class SensorType>
AddSensor()120     void AddSensor() {
121         std::shared_ptr<SensorType> sensor =
122                 std::make_shared<SensorType>(mNextHandle++ /* sensorHandle */, this /* callback */);
123         mSensors[sensor->getSensorInfo().sensorHandle] = sensor;
124     }
125 
126     // Utility function to delete the Event Flag
deleteEventFlag()127     void deleteEventFlag() {
128         // Hold the lock to ensure we don't delete the flag while it's being used in postEvents()
129         std::lock_guard<std::mutex> lock(mWriteLock);
130         deleteEventFlagLocked();
131     }
132 
133     // Expects mWriteLock to be locked prior to invocation
deleteEventFlagLocked()134     void deleteEventFlagLocked() {
135         if (mEventQueueFlag != nullptr) {
136             status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag);
137             if (status != OK) {
138                 ALOGI("Failed to delete event flag: %d", status);
139             }
140         }
141     }
142 
startReadWakeLockThread(Sensors * sensors)143     static void startReadWakeLockThread(Sensors* sensors) { sensors->readWakeLockFMQ(); }
144 
145     // Function to read the Wake Lock FMQ and release the wake lock when appropriate
readWakeLockFMQ()146     void readWakeLockFMQ() {
147         while (mReadWakeLockQueueRun.load()) {
148             constexpr int64_t kReadTimeoutNs = 500 * 1000 * 1000;  // 500 ms
149             int32_t eventsHandled = 0;
150 
151             // Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to
152             // ensure that any held wake lock is able to be released if it is held for too long.
153             mWakeLockQueue->readBlocking(
154                     &eventsHandled, 1 /* count */, 0 /* readNotification */,
155                     static_cast<uint32_t>(WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN), kReadTimeoutNs);
156             updateWakeLock(0 /* eventsWritten */, eventsHandled);
157         }
158     }
159 
160     /**
161      * Responsible for acquiring and releasing a wake lock when there are unhandled WAKE_UP events
162      */
updateWakeLock(int32_t eventsWritten,int32_t eventsHandled)163     void updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) {
164         std::lock_guard<std::mutex> lock(mWakeLockLock);
165         int32_t newVal = mOutstandingWakeUpEvents + eventsWritten - eventsHandled;
166         if (newVal < 0) {
167             mOutstandingWakeUpEvents = 0;
168         } else {
169             mOutstandingWakeUpEvents = newVal;
170         }
171 
172         if (eventsWritten > 0) {
173             // Update the time at which the last WAKE_UP event was sent
174             mAutoReleaseWakeLockTime = ::android::uptimeMillis() +
175                                        static_cast<uint32_t>(WAKE_LOCK_TIMEOUT_SECONDS) * 1000;
176         }
177 
178         if (!mHasWakeLock && mOutstandingWakeUpEvents > 0 &&
179             acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) == 0) {
180             mHasWakeLock = true;
181         } else if (mHasWakeLock) {
182             // Check if the wake lock should be released automatically if
183             // SensorTimeout::WAKE_LOCK_SECONDS has elapsed since the last WAKE_UP event was written
184             // to the Wake Lock FMQ.
185             if (::android::uptimeMillis() > mAutoReleaseWakeLockTime) {
186                 ALOGD("No events read from wake lock FMQ for %d seconds, auto releasing wake lock",
187                       WAKE_LOCK_TIMEOUT_SECONDS);
188                 mOutstandingWakeUpEvents = 0;
189             }
190 
191             if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) {
192                 mHasWakeLock = false;
193             }
194         }
195     }
196 
197   private:
198     // The Event FMQ where sensor events are written
199     std::unique_ptr<AidlMessageQueue<Event, SynchronizedReadWrite>> mEventQueue;
200     // The Wake Lock FMQ that is read to determine when the framework has handled WAKE_UP events
201     std::unique_ptr<AidlMessageQueue<int32_t, SynchronizedReadWrite>> mWakeLockQueue;
202     // Event Flag to signal to the framework when sensor events are available to be read
203     EventFlag* mEventQueueFlag GUARDED_BY(mWriteLock);
204     // Callback for asynchronous events, such as dynamic sensor connections.
205     std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback> mCallback;
206     // A map of the available sensors.
207     std::map<int32_t, std::shared_ptr<Sensor>> mSensors;
208     // The next available sensor handle.
209     int32_t mNextHandle;
210     // Lock to protect writes to the FMQs.
211     std::mutex mWriteLock;
212     // Lock to protect acquiring and releasing the wake lock
213     std::mutex mWakeLockLock;
214     // Track the number of WAKE_UP events that have not been handled by the framework
215     uint32_t mOutstandingWakeUpEvents;
216     // A thread to read the Wake Lock FMQ
217     std::thread mWakeLockThread;
218     // Flag to indicate that the Wake Lock Thread should continue to run
219     std::atomic_bool mReadWakeLockQueueRun;
220     // Track the time when the wake lock should automatically be released
221     int64_t mAutoReleaseWakeLockTime;
222     // Flag to indicate if a wake lock has been acquired
223     bool mHasWakeLock;
224 };
225 
226 }  // namespace sensors
227 }  // namespace hardware
228 }  // namespace android
229 }  // namespace aidl
230