blob: 6436046a3d05340347670ea1add8eb798198910c [file] [log] [blame]
Cosmin Tanislav75fd6352022-02-16 22:14:58 +02001/*
2 * Copyright (C) 2019 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#include "Sensor.h"
18
19#include <hardware/sensors.h>
Cosmin Tanislav42258b22022-02-20 19:34:44 +020020#include <log/log.h>
Cosmin Tanislav75fd6352022-02-16 22:14:58 +020021#include <utils/SystemClock.h>
22
23#include <cmath>
24
Cosmin Tanislav42258b22022-02-20 19:34:44 +020025static bool readBool(int fd, bool seek) {
26 char c;
27 int rc;
28
29 if (seek) {
30 rc = lseek(fd, 0, SEEK_SET);
31 if (rc) {
32 ALOGE("failed to seek: %d", rc);
33 return false;
34 }
35 }
36
37 rc = read(fd, &c, sizeof(c));
38 if (rc != 1) {
39 ALOGE("failed to read bool: %d", rc);
40 return false;
41 }
42
43 return c != '0';
44}
45
Cosmin Tanislav75fd6352022-02-16 22:14:58 +020046namespace android {
47namespace hardware {
48namespace sensors {
49namespace V2_1 {
50namespace subhal {
51namespace implementation {
52
53using ::android::hardware::sensors::V1_0::MetaDataEventType;
54using ::android::hardware::sensors::V1_0::OperationMode;
55using ::android::hardware::sensors::V1_0::Result;
56using ::android::hardware::sensors::V1_0::SensorFlagBits;
57using ::android::hardware::sensors::V1_0::SensorStatus;
58using ::android::hardware::sensors::V2_1::Event;
59using ::android::hardware::sensors::V2_1::SensorInfo;
60using ::android::hardware::sensors::V2_1::SensorType;
61
62Sensor::Sensor(int32_t sensorHandle, ISensorsEventCallback* callback)
63 : mIsEnabled(false),
64 mSamplingPeriodNs(0),
65 mLastSampleTimeNs(0),
66 mCallback(callback),
67 mMode(OperationMode::NORMAL) {
68 mSensorInfo.sensorHandle = sensorHandle;
69 mSensorInfo.vendor = "The LineageOS Project";
70 mSensorInfo.version = 1;
71 constexpr float kDefaultMaxDelayUs = 1000 * 1000;
72 mSensorInfo.maxDelay = kDefaultMaxDelayUs;
73 mSensorInfo.fifoReservedEventCount = 0;
74 mSensorInfo.fifoMaxEventCount = 0;
75 mSensorInfo.requiredPermission = "";
76 mSensorInfo.flags = 0;
77 mRunThread = std::thread(startThread, this);
78}
79
80Sensor::~Sensor() {
81 // Ensure that lock is unlocked before calling mRunThread.join() or a
82 // deadlock will occur.
83 {
84 std::unique_lock<std::mutex> lock(mRunMutex);
85 mStopThread = true;
86 mIsEnabled = false;
87 mWaitCV.notify_all();
88 }
89 mRunThread.join();
90}
91
92const SensorInfo& Sensor::getSensorInfo() const {
93 return mSensorInfo;
94}
95
96void Sensor::batch(int32_t samplingPeriodNs) {
97 samplingPeriodNs =
98 std::clamp(samplingPeriodNs, mSensorInfo.minDelay * 1000, mSensorInfo.maxDelay * 1000);
99
100 if (mSamplingPeriodNs != samplingPeriodNs) {
101 mSamplingPeriodNs = samplingPeriodNs;
102 // Wake up the 'run' thread to check if a new event should be generated now
103 mWaitCV.notify_all();
104 }
105}
106
107void Sensor::activate(bool enable) {
108 if (mIsEnabled != enable) {
109 std::unique_lock<std::mutex> lock(mRunMutex);
110 mIsEnabled = enable;
111 mWaitCV.notify_all();
112 }
113}
114
115Result Sensor::flush() {
116 // Only generate a flush complete event if the sensor is enabled and if the sensor is not a
117 // one-shot sensor.
Cosmin Tanislavf92cd5b2022-02-17 01:08:50 +0200118 if (!mIsEnabled) {
Cosmin Tanislav75fd6352022-02-16 22:14:58 +0200119 return Result::BAD_VALUE;
120 }
121
122 // Note: If a sensor supports batching, write all of the currently batched events for the sensor
123 // to the Event FMQ prior to writing the flush complete event.
124 Event ev;
125 ev.sensorHandle = mSensorInfo.sensorHandle;
126 ev.sensorType = SensorType::META_DATA;
127 ev.u.meta.what = MetaDataEventType::META_DATA_FLUSH_COMPLETE;
128 std::vector<Event> evs{ev};
129 mCallback->postEvents(evs, isWakeUpSensor());
130
131 return Result::OK;
132}
133
134void Sensor::startThread(Sensor* sensor) {
135 sensor->run();
136}
137
138void Sensor::run() {
139 std::unique_lock<std::mutex> runLock(mRunMutex);
140 constexpr int64_t kNanosecondsInSeconds = 1000 * 1000 * 1000;
141
142 while (!mStopThread) {
143 if (!mIsEnabled || mMode == OperationMode::DATA_INJECTION) {
144 mWaitCV.wait(runLock, [&] {
145 return ((mIsEnabled && mMode == OperationMode::NORMAL) || mStopThread);
146 });
147 } else {
148 timespec curTime;
149 clock_gettime(CLOCK_REALTIME, &curTime);
150 int64_t now = (curTime.tv_sec * kNanosecondsInSeconds) + curTime.tv_nsec;
151 int64_t nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs;
152
153 if (now >= nextSampleTime) {
154 mLastSampleTimeNs = now;
155 nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs;
156 mCallback->postEvents(readEvents(), isWakeUpSensor());
157 }
158
159 mWaitCV.wait_for(runLock, std::chrono::nanoseconds(nextSampleTime - now));
160 }
161 }
162}
163
164bool Sensor::isWakeUpSensor() {
165 return mSensorInfo.flags & static_cast<uint32_t>(SensorFlagBits::WAKE_UP);
166}
167
168std::vector<Event> Sensor::readEvents() {
169 std::vector<Event> events;
170 Event event;
171 event.sensorHandle = mSensorInfo.sensorHandle;
172 event.sensorType = mSensorInfo.type;
173 event.timestamp = ::android::elapsedRealtimeNano();
174 event.u.vec3.x = 0;
175 event.u.vec3.y = 0;
176 event.u.vec3.z = 0;
177 event.u.vec3.status = SensorStatus::ACCURACY_HIGH;
178 events.push_back(event);
179 return events;
180}
181
182void Sensor::setOperationMode(OperationMode mode) {
183 if (mMode != mode) {
184 std::unique_lock<std::mutex> lock(mRunMutex);
185 mMode = mode;
186 mWaitCV.notify_all();
187 }
188}
189
190bool Sensor::supportsDataInjection() const {
191 return mSensorInfo.flags & static_cast<uint32_t>(SensorFlagBits::DATA_INJECTION);
192}
193
194Result Sensor::injectEvent(const Event& event) {
195 Result result = Result::OK;
196 if (event.sensorType == SensorType::ADDITIONAL_INFO) {
197 // When in OperationMode::NORMAL, SensorType::ADDITIONAL_INFO is used to push operation
198 // environment data into the device.
199 } else if (!supportsDataInjection()) {
200 result = Result::INVALID_OPERATION;
201 } else if (mMode == OperationMode::DATA_INJECTION) {
202 mCallback->postEvents(std::vector<Event>{event}, isWakeUpSensor());
203 } else {
204 result = Result::BAD_VALUE;
205 }
206 return result;
207}
208
Cosmin Tanislavf92cd5b2022-02-17 01:08:50 +0200209OneShotSensor::OneShotSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
210 : Sensor(sensorHandle, callback) {
211 mSensorInfo.minDelay = -1;
212 mSensorInfo.maxDelay = 0;
213 mSensorInfo.flags |= SensorFlagBits::ONE_SHOT_MODE;
214}
215
Cosmin Tanislav67cf7302022-03-22 19:11:43 +0200216SysfsPollingOneShotSensor::SysfsPollingOneShotSensor(
217 int32_t sensorHandle, ISensorsEventCallback* callback, const std::string& pollPath,
218 const std::string& enablePath, const std::string& name, const std::string& typeAsString,
Cosmin Tanislav64c7f102022-03-22 19:49:37 +0200219 SensorType type, int screenX, int screenY)
Cosmin Tanislav42258b22022-02-20 19:34:44 +0200220 : OneShotSensor(sensorHandle, callback) {
Cosmin Tanislav67cf7302022-03-22 19:11:43 +0200221 mSensorInfo.name = name;
222 mSensorInfo.type = type;
223 mSensorInfo.typeAsString = typeAsString;
Cosmin Tanislav42258b22022-02-20 19:34:44 +0200224 mSensorInfo.maxRange = 2048.0f;
225 mSensorInfo.resolution = 1.0f;
226 mSensorInfo.power = 0;
227 mSensorInfo.flags |= SensorFlagBits::WAKE_UP;
Cosmin Tanislav64c7f102022-03-22 19:49:37 +0200228 mScreenX = screenX;
229 mScreenY = screenY;
Cosmin Tanislav42258b22022-02-20 19:34:44 +0200230
231 mEnableStream.open(enablePath);
232
233 int rc;
234
235 rc = pipe(mWaitPipeFd);
236 if (rc < 0) {
237 mWaitPipeFd[0] = -1;
238 mWaitPipeFd[1] = -1;
239 ALOGE("failed to open wait pipe: %d", rc);
240 }
241
242 mPollFd = open(pollPath.c_str(), O_RDONLY);
243 if (mPollFd < 0) {
244 ALOGE("failed to open poll fd: %d", mPollFd);
245 }
246
247 if (mWaitPipeFd[0] < 0 || mWaitPipeFd[1] < 0 || mPollFd < 0) {
248 mStopThread = true;
249 return;
250 }
251
252 mPolls[0] = {
253 .fd = mWaitPipeFd[0],
254 .events = POLLIN,
255 };
256
257 mPolls[1] = {
258 .fd = mPollFd,
259 .events = POLLERR | POLLPRI,
260 };
261}
262
263SysfsPollingOneShotSensor::~SysfsPollingOneShotSensor() {
264 interruptPoll();
265}
266
Cosmin Tanislavbf3df1a2022-03-22 19:26:15 +0200267void SysfsPollingOneShotSensor::writeEnable(bool enable) {
268 if (mEnableStream) {
269 mEnableStream << (enable ? '1' : '0') << std::flush;
270 }
271}
272
Cosmin Tanislav8b09af12022-03-22 19:23:56 +0200273void SysfsPollingOneShotSensor::activate(bool enable, bool notify, bool lock) {
274 std::unique_lock<std::mutex> runLock(mRunMutex, std::defer_lock);
275
276 if (lock) {
277 runLock.lock();
278 }
Cosmin Tanislav42258b22022-02-20 19:34:44 +0200279
280 if (mIsEnabled != enable) {
Cosmin Tanislavbf3df1a2022-03-22 19:26:15 +0200281 writeEnable(enable);
Cosmin Tanislav8b09af12022-03-22 19:23:56 +0200282
283 mIsEnabled = enable;
284
285 if (notify) {
286 interruptPoll();
287 mWaitCV.notify_all();
288 }
Cosmin Tanislav42258b22022-02-20 19:34:44 +0200289 }
Cosmin Tanislav8b09af12022-03-22 19:23:56 +0200290
291 if (lock) {
292 runLock.unlock();
293 }
294}
295
296void SysfsPollingOneShotSensor::activate(bool enable) {
297 activate(enable, true, true);
Cosmin Tanislav42258b22022-02-20 19:34:44 +0200298}
299
300void SysfsPollingOneShotSensor::setOperationMode(OperationMode mode) {
301 Sensor::setOperationMode(mode);
302 interruptPoll();
303}
304
305void SysfsPollingOneShotSensor::run() {
306 std::unique_lock<std::mutex> runLock(mRunMutex);
307
308 while (!mStopThread) {
309 if (!mIsEnabled || mMode == OperationMode::DATA_INJECTION) {
310 mWaitCV.wait(runLock, [&] {
311 return ((mIsEnabled && mMode == OperationMode::NORMAL) || mStopThread);
312 });
313 } else {
314 // Cannot hold lock while polling.
315 runLock.unlock();
316 int rc = poll(mPolls, 2, -1);
317 runLock.lock();
318
319 if (rc < 0) {
320 ALOGE("failed to poll: %d", rc);
321 mStopThread = true;
322 continue;
323 }
324
325 if (mPolls[1].revents == mPolls[1].events && readBool(mPollFd, true /* seek */)) {
Cosmin Tanislav8b09af12022-03-22 19:23:56 +0200326 activate(false, false, false);
Cosmin Tanislav42258b22022-02-20 19:34:44 +0200327 mCallback->postEvents(readEvents(), isWakeUpSensor());
328 } else if (mPolls[0].revents == mPolls[0].events) {
329 readBool(mWaitPipeFd[0], false /* seek */);
330 }
331 }
332 }
333}
334
335void SysfsPollingOneShotSensor::interruptPoll() {
336 if (mWaitPipeFd[1] < 0) return;
337
338 char c = '1';
339 write(mWaitPipeFd[1], &c, sizeof(c));
340}
341
Cosmin Tanislav64c7f102022-03-22 19:49:37 +0200342std::vector<Event> SysfsPollingOneShotSensor::readEvents() {
Cosmin Tanislav4f647162022-02-20 19:21:09 +0200343 std::vector<Event> events;
344 Event event;
345 event.sensorHandle = mSensorInfo.sensorHandle;
346 event.sensorType = mSensorInfo.type;
347 event.timestamp = ::android::elapsedRealtimeNano();
Cosmin Tanislav64c7f102022-03-22 19:49:37 +0200348 event.u.data[0] = mScreenX;
349 event.u.data[1] = mScreenY;
Cosmin Tanislav4f647162022-02-20 19:21:09 +0200350 events.push_back(event);
351 return events;
352}
353
Cosmin Tanislav75fd6352022-02-16 22:14:58 +0200354} // namespace implementation
355} // namespace subhal
356} // namespace V2_1
357} // namespace sensors
358} // namespace hardware
359} // namespace android