• 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         if (mEventQueueFlag != nullptr) {
123             status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag);
124             if (status != OK) {
125                 ALOGI("Failed to delete event flag: %d", status);
126             }
127         }
128     }
129 
startReadWakeLockThread(Sensors * sensors)130     static void startReadWakeLockThread(Sensors* sensors) { sensors->readWakeLockFMQ(); }
131 
132     // Function to read the Wake Lock FMQ and release the wake lock when appropriate
readWakeLockFMQ()133     void readWakeLockFMQ() {
134         while (mReadWakeLockQueueRun.load()) {
135             constexpr int64_t kReadTimeoutNs = 500 * 1000 * 1000;  // 500 ms
136             int32_t eventsHandled = 0;
137 
138             // Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to
139             // ensure that any held wake lock is able to be released if it is held for too long.
140             mWakeLockQueue->readBlocking(
141                     &eventsHandled, 1 /* count */, 0 /* readNotification */,
142                     static_cast<uint32_t>(WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN), kReadTimeoutNs);
143             updateWakeLock(0 /* eventsWritten */, eventsHandled);
144         }
145     }
146 
147     /**
148      * Responsible for acquiring and releasing a wake lock when there are unhandled WAKE_UP events
149      */
updateWakeLock(int32_t eventsWritten,int32_t eventsHandled)150     void updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) {
151         std::lock_guard<std::mutex> lock(mWakeLockLock);
152         int32_t newVal = mOutstandingWakeUpEvents + eventsWritten - eventsHandled;
153         if (newVal < 0) {
154             mOutstandingWakeUpEvents = 0;
155         } else {
156             mOutstandingWakeUpEvents = newVal;
157         }
158 
159         if (eventsWritten > 0) {
160             // Update the time at which the last WAKE_UP event was sent
161             mAutoReleaseWakeLockTime = ::android::uptimeMillis() +
162                                        static_cast<uint32_t>(WAKE_LOCK_TIMEOUT_SECONDS) * 1000;
163         }
164 
165         if (!mHasWakeLock && mOutstandingWakeUpEvents > 0 &&
166             acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) == 0) {
167             mHasWakeLock = true;
168         } else if (mHasWakeLock) {
169             // Check if the wake lock should be released automatically if
170             // SensorTimeout::WAKE_LOCK_SECONDS has elapsed since the last WAKE_UP event was written
171             // to the Wake Lock FMQ.
172             if (::android::uptimeMillis() > mAutoReleaseWakeLockTime) {
173                 ALOGD("No events read from wake lock FMQ for %d seconds, auto releasing wake lock",
174                       WAKE_LOCK_TIMEOUT_SECONDS);
175                 mOutstandingWakeUpEvents = 0;
176             }
177 
178             if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) {
179                 mHasWakeLock = false;
180             }
181         }
182     }
183 
184   private:
185     // The Event FMQ where sensor events are written
186     std::unique_ptr<AidlMessageQueue<Event, SynchronizedReadWrite>> mEventQueue;
187     // The Wake Lock FMQ that is read to determine when the framework has handled WAKE_UP events
188     std::unique_ptr<AidlMessageQueue<int32_t, SynchronizedReadWrite>> mWakeLockQueue;
189     // Event Flag to signal to the framework when sensor events are available to be read
190     EventFlag* mEventQueueFlag;
191     // Callback for asynchronous events, such as dynamic sensor connections.
192     std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback> mCallback;
193     // A map of the available sensors.
194     std::map<int32_t, std::shared_ptr<Sensor>> mSensors;
195     // The next available sensor handle.
196     int32_t mNextHandle;
197     // Lock to protect writes to the FMQs.
198     std::mutex mWriteLock;
199     // Lock to protect acquiring and releasing the wake lock
200     std::mutex mWakeLockLock;
201     // Track the number of WAKE_UP events that have not been handled by the framework
202     uint32_t mOutstandingWakeUpEvents;
203     // A thread to read the Wake Lock FMQ
204     std::thread mWakeLockThread;
205     // Flag to indicate that the Wake Lock Thread should continue to run
206     std::atomic_bool mReadWakeLockQueueRun;
207     // Track the time when the wake lock should automatically be released
208     int64_t mAutoReleaseWakeLockTime;
209     // Flag to indicate if a wake lock has been acquired
210     bool mHasWakeLock;
211 };
212 
213 }  // namespace sensors
214 }  // namespace hardware
215 }  // namespace android
216 }  // namespace aidl
217