Cosmin Tanislav | 75fd635 | 2022-02-16 22:14:58 +0200 | [diff] [blame] | 1 | /* |
| 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 Tanislav | 42258b2 | 2022-02-20 19:34:44 +0200 | [diff] [blame] | 20 | #include <log/log.h> |
Cosmin Tanislav | 75fd635 | 2022-02-16 22:14:58 +0200 | [diff] [blame] | 21 | #include <utils/SystemClock.h> |
| 22 | |
| 23 | #include <cmath> |
| 24 | |
Cosmin Tanislav | 42258b2 | 2022-02-20 19:34:44 +0200 | [diff] [blame] | 25 | static 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 Tanislav | 75fd635 | 2022-02-16 22:14:58 +0200 | [diff] [blame] | 46 | namespace android { |
| 47 | namespace hardware { |
| 48 | namespace sensors { |
| 49 | namespace V2_1 { |
| 50 | namespace subhal { |
| 51 | namespace implementation { |
| 52 | |
| 53 | using ::android::hardware::sensors::V1_0::MetaDataEventType; |
| 54 | using ::android::hardware::sensors::V1_0::OperationMode; |
| 55 | using ::android::hardware::sensors::V1_0::Result; |
| 56 | using ::android::hardware::sensors::V1_0::SensorFlagBits; |
| 57 | using ::android::hardware::sensors::V1_0::SensorStatus; |
| 58 | using ::android::hardware::sensors::V2_1::Event; |
| 59 | using ::android::hardware::sensors::V2_1::SensorInfo; |
| 60 | using ::android::hardware::sensors::V2_1::SensorType; |
| 61 | |
| 62 | Sensor::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 | |
| 80 | Sensor::~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 | |
| 92 | const SensorInfo& Sensor::getSensorInfo() const { |
| 93 | return mSensorInfo; |
| 94 | } |
| 95 | |
| 96 | void 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 | |
| 107 | void 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 | |
| 115 | Result 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 Tanislav | f92cd5b | 2022-02-17 01:08:50 +0200 | [diff] [blame] | 118 | if (!mIsEnabled) { |
Cosmin Tanislav | 75fd635 | 2022-02-16 22:14:58 +0200 | [diff] [blame] | 119 | 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 | |
| 134 | void Sensor::startThread(Sensor* sensor) { |
| 135 | sensor->run(); |
| 136 | } |
| 137 | |
| 138 | void 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 | |
| 164 | bool Sensor::isWakeUpSensor() { |
| 165 | return mSensorInfo.flags & static_cast<uint32_t>(SensorFlagBits::WAKE_UP); |
| 166 | } |
| 167 | |
| 168 | std::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 | |
| 182 | void 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 | |
| 190 | bool Sensor::supportsDataInjection() const { |
| 191 | return mSensorInfo.flags & static_cast<uint32_t>(SensorFlagBits::DATA_INJECTION); |
| 192 | } |
| 193 | |
| 194 | Result 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 Tanislav | f92cd5b | 2022-02-17 01:08:50 +0200 | [diff] [blame] | 209 | OneShotSensor::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 Tanislav | 67cf730 | 2022-03-22 19:11:43 +0200 | [diff] [blame] | 216 | SysfsPollingOneShotSensor::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 Tanislav | 64c7f10 | 2022-03-22 19:49:37 +0200 | [diff] [blame] | 219 | SensorType type, int screenX, int screenY) |
Cosmin Tanislav | 42258b2 | 2022-02-20 19:34:44 +0200 | [diff] [blame] | 220 | : OneShotSensor(sensorHandle, callback) { |
Cosmin Tanislav | 67cf730 | 2022-03-22 19:11:43 +0200 | [diff] [blame] | 221 | mSensorInfo.name = name; |
| 222 | mSensorInfo.type = type; |
| 223 | mSensorInfo.typeAsString = typeAsString; |
Cosmin Tanislav | 42258b2 | 2022-02-20 19:34:44 +0200 | [diff] [blame] | 224 | mSensorInfo.maxRange = 2048.0f; |
| 225 | mSensorInfo.resolution = 1.0f; |
| 226 | mSensorInfo.power = 0; |
| 227 | mSensorInfo.flags |= SensorFlagBits::WAKE_UP; |
Cosmin Tanislav | 64c7f10 | 2022-03-22 19:49:37 +0200 | [diff] [blame] | 228 | mScreenX = screenX; |
| 229 | mScreenY = screenY; |
Cosmin Tanislav | 42258b2 | 2022-02-20 19:34:44 +0200 | [diff] [blame] | 230 | |
| 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 | |
| 263 | SysfsPollingOneShotSensor::~SysfsPollingOneShotSensor() { |
| 264 | interruptPoll(); |
| 265 | } |
| 266 | |
Cosmin Tanislav | bf3df1a | 2022-03-22 19:26:15 +0200 | [diff] [blame] | 267 | void SysfsPollingOneShotSensor::writeEnable(bool enable) { |
| 268 | if (mEnableStream) { |
| 269 | mEnableStream << (enable ? '1' : '0') << std::flush; |
| 270 | } |
| 271 | } |
| 272 | |
Cosmin Tanislav | 8b09af1 | 2022-03-22 19:23:56 +0200 | [diff] [blame] | 273 | void 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 Tanislav | 42258b2 | 2022-02-20 19:34:44 +0200 | [diff] [blame] | 279 | |
| 280 | if (mIsEnabled != enable) { |
Cosmin Tanislav | bf3df1a | 2022-03-22 19:26:15 +0200 | [diff] [blame] | 281 | writeEnable(enable); |
Cosmin Tanislav | 8b09af1 | 2022-03-22 19:23:56 +0200 | [diff] [blame] | 282 | |
| 283 | mIsEnabled = enable; |
| 284 | |
| 285 | if (notify) { |
| 286 | interruptPoll(); |
| 287 | mWaitCV.notify_all(); |
| 288 | } |
Cosmin Tanislav | 42258b2 | 2022-02-20 19:34:44 +0200 | [diff] [blame] | 289 | } |
Cosmin Tanislav | 8b09af1 | 2022-03-22 19:23:56 +0200 | [diff] [blame] | 290 | |
| 291 | if (lock) { |
| 292 | runLock.unlock(); |
| 293 | } |
| 294 | } |
| 295 | |
| 296 | void SysfsPollingOneShotSensor::activate(bool enable) { |
| 297 | activate(enable, true, true); |
Cosmin Tanislav | 42258b2 | 2022-02-20 19:34:44 +0200 | [diff] [blame] | 298 | } |
| 299 | |
| 300 | void SysfsPollingOneShotSensor::setOperationMode(OperationMode mode) { |
| 301 | Sensor::setOperationMode(mode); |
| 302 | interruptPoll(); |
| 303 | } |
| 304 | |
| 305 | void 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 Tanislav | 8b09af1 | 2022-03-22 19:23:56 +0200 | [diff] [blame] | 326 | activate(false, false, false); |
Cosmin Tanislav | 42258b2 | 2022-02-20 19:34:44 +0200 | [diff] [blame] | 327 | mCallback->postEvents(readEvents(), isWakeUpSensor()); |
| 328 | } else if (mPolls[0].revents == mPolls[0].events) { |
| 329 | readBool(mWaitPipeFd[0], false /* seek */); |
| 330 | } |
| 331 | } |
| 332 | } |
| 333 | } |
| 334 | |
| 335 | void SysfsPollingOneShotSensor::interruptPoll() { |
| 336 | if (mWaitPipeFd[1] < 0) return; |
| 337 | |
| 338 | char c = '1'; |
| 339 | write(mWaitPipeFd[1], &c, sizeof(c)); |
| 340 | } |
| 341 | |
Cosmin Tanislav | 64c7f10 | 2022-03-22 19:49:37 +0200 | [diff] [blame] | 342 | std::vector<Event> SysfsPollingOneShotSensor::readEvents() { |
Cosmin Tanislav | 4f64716 | 2022-02-20 19:21:09 +0200 | [diff] [blame] | 343 | std::vector<Event> events; |
| 344 | Event event; |
| 345 | event.sensorHandle = mSensorInfo.sensorHandle; |
| 346 | event.sensorType = mSensorInfo.type; |
| 347 | event.timestamp = ::android::elapsedRealtimeNano(); |
Cosmin Tanislav | 64c7f10 | 2022-03-22 19:49:37 +0200 | [diff] [blame] | 348 | event.u.data[0] = mScreenX; |
| 349 | event.u.data[1] = mScreenY; |
Cosmin Tanislav | 4f64716 | 2022-02-20 19:21:09 +0200 | [diff] [blame] | 350 | events.push_back(event); |
| 351 | return events; |
| 352 | } |
| 353 | |
Cosmin Tanislav | 75fd635 | 2022-02-16 22:14:58 +0200 | [diff] [blame] | 354 | } // namespace implementation |
| 355 | } // namespace subhal |
| 356 | } // namespace V2_1 |
| 357 | } // namespace sensors |
| 358 | } // namespace hardware |
| 359 | } // namespace android |