• 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 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