blob: 37f0f6c644915530c63d002cebaf231a96bc85c4 [file] [log] [blame]
Andreas Huber99fdbb52016-10-10 13:22:58 -07001/*
2 * Copyright (C) 2010 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 <inttypes.h>
18#include <math.h>
19#include <stdint.h>
20#include <sys/types.h>
21
22#include <android-base/logging.h>
Andreas Huber99fdbb52016-10-10 13:22:58 -070023#include <utils/Atomic.h>
24#include <utils/Errors.h>
25#include <utils/Singleton.h>
26
27#include "SensorDevice.h"
28#include "SensorService.h"
29
Steven Morelandbc9cb442016-11-07 19:19:26 -080030#include <sensors/convert.h>
Andreas Huber99fdbb52016-10-10 13:22:58 -070031
32using android::hardware::sensors::V1_0::ISensors;
33using android::hardware::hidl_vec;
34
35using Event = android::hardware::sensors::V1_0::Event;
36using SensorInfo = android::hardware::sensors::V1_0::SensorInfo;
37using SensorType = android::hardware::sensors::V1_0::SensorType;
38using DynamicSensorInfo = android::hardware::sensors::V1_0::DynamicSensorInfo;
39using SensorInfo = android::hardware::sensors::V1_0::SensorInfo;
40using Result = android::hardware::sensors::V1_0::Result;
41
42using namespace android::hardware::sensors::V1_0::implementation;
43
44namespace android {
45// ---------------------------------------------------------------------------
46
47ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
48
49static status_t StatusFromResult(Result result) {
50 switch (result) {
51 case Result::OK:
52 return OK;
53 case Result::BAD_VALUE:
54 return BAD_VALUE;
55 case Result::PERMISSION_DENIED:
56 return PERMISSION_DENIED;
57 case Result::INVALID_OPERATION:
58 return INVALID_OPERATION;
Martijn Coenenb41a3852017-01-11 14:57:42 +010059 case Result::NO_MEMORY:
60 return NO_MEMORY;
Andreas Huber99fdbb52016-10-10 13:22:58 -070061 }
62}
63
64SensorDevice::SensorDevice() {
65 mSensors = ISensors::getService("sensors");
66
67 if (mSensors == NULL) {
68 return;
69 }
70
71 mSensors->getSensorsList(
72 [&](const auto &list) {
73 const size_t count = list.size();
74
75 mActivationCount.setCapacity(count);
76 Info model;
77 for (size_t i=0 ; i < count; i++) {
78 sensor_t sensor;
79 convertToSensor(list[i], &sensor);
80 mSensorList.push_back(sensor);
81
82 mActivationCount.add(list[i].sensorHandle, model);
83
Peng Xud08d30c2017-01-12 20:02:47 -080084 mSensors->activate(list[i].sensorHandle, 0 /* enabled */);
Andreas Huber99fdbb52016-10-10 13:22:58 -070085 }
86 });
87}
88
89void SensorDevice::handleDynamicSensorConnection(int handle, bool connected) {
90 if (connected) {
91 Info model;
92 mActivationCount.add(handle, model);
Peng Xud08d30c2017-01-12 20:02:47 -080093 mSensors->activate(handle, 0 /* enabled */);
Andreas Huber99fdbb52016-10-10 13:22:58 -070094 } else {
95 mActivationCount.removeItem(handle);
96 }
97}
98
99std::string SensorDevice::dump() const {
100 if (mSensors == NULL) return "HAL not initialized\n";
101
Andreas Huber99fdbb52016-10-10 13:22:58 -0700102 String8 result;
103 mSensors->getSensorsList([&](const auto &list) {
104 const size_t count = list.size();
105
106 result.appendFormat(
107 "Total %zu h/w sensors, %zu running:\n",
108 count,
109 mActivationCount.size());
110
111 Mutex::Autolock _l(mLock);
112 for (size_t i = 0 ; i < count ; i++) {
113 const Info& info = mActivationCount.valueFor(
114 list[i].sensorHandle);
115
116 if (info.batchParams.isEmpty()) continue;
117 result.appendFormat(
118 "0x%08x) active-count = %zu; ",
119 list[i].sensorHandle,
120 info.batchParams.size());
121
122 result.append("sampling_period(ms) = {");
123 for (size_t j = 0; j < info.batchParams.size(); j++) {
124 const BatchParams& params = info.batchParams.valueAt(j);
125 result.appendFormat(
126 "%.1f%s",
127 params.batchDelay / 1e6f,
128 j < info.batchParams.size() - 1 ? ", " : "");
129 }
130 result.appendFormat(
131 "}, selected = %.1f ms; ",
132 info.bestBatchParams.batchDelay / 1e6f);
133
134 result.append("batching_period(ms) = {");
135 for (size_t j = 0; j < info.batchParams.size(); j++) {
136 BatchParams params = info.batchParams.valueAt(j);
137
138 result.appendFormat(
139 "%.1f%s",
140 params.batchTimeout / 1e6f,
141 j < info.batchParams.size() - 1 ? ", " : "");
142 }
143
144 result.appendFormat(
145 "}, selected = %.1f ms\n",
146 info.bestBatchParams.batchTimeout / 1e6f);
147 }
148 });
149
150 return result.string();
151}
152
153ssize_t SensorDevice::getSensorList(sensor_t const** list) {
154 *list = &mSensorList[0];
155
156 return mSensorList.size();
157}
158
159status_t SensorDevice::initCheck() const {
160 return mSensors != NULL ? NO_ERROR : NO_INIT;
161}
162
163ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
164 if (mSensors == NULL) return NO_INIT;
165
166 ssize_t err;
167
168 mSensors->poll(
169 count,
170 [&](auto result,
171 const auto &events,
172 const auto &dynamicSensorsAdded) {
173 if (result == Result::OK) {
174 convertToSensorEvents(events, dynamicSensorsAdded, buffer);
175 err = (ssize_t)events.size();
176 } else {
177 err = StatusFromResult(result);
178 }
179 });
180
181 return err;
182}
183
184void SensorDevice::autoDisable(void *ident, int handle) {
185 Info& info( mActivationCount.editValueFor(handle) );
186 Mutex::Autolock _l(mLock);
187 info.removeBatchParamsForIdent(ident);
188}
189
190status_t SensorDevice::activate(void* ident, int handle, int enabled) {
191 if (mSensors == NULL) return NO_INIT;
192
193 status_t err(NO_ERROR);
194 bool actuateHardware = false;
195
196 Mutex::Autolock _l(mLock);
197 Info& info( mActivationCount.editValueFor(handle) );
198
199 ALOGD_IF(DEBUG_CONNECTIONS,
200 "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu",
201 ident, handle, enabled, info.batchParams.size());
202
203 if (enabled) {
204 ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));
205
206 if (isClientDisabledLocked(ident)) {
207 ALOGE("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d",
208 ident, handle);
209 return INVALID_OPERATION;
210 }
211
212 if (info.batchParams.indexOfKey(ident) >= 0) {
213 if (info.numActiveClients() == 1) {
214 // This is the first connection, we need to activate the underlying h/w sensor.
215 actuateHardware = true;
216 }
217 } else {
218 // Log error. Every activate call should be preceded by a batch() call.
219 ALOGE("\t >>>ERROR: activate called without batch");
220 }
221 } else {
222 ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident));
223
224 // If a connected dynamic sensor is deactivated, remove it from the
225 // dictionary.
226 auto it = mConnectedDynamicSensors.find(handle);
227 if (it != mConnectedDynamicSensors.end()) {
228 delete it->second;
229 mConnectedDynamicSensors.erase(it);
230 }
231
232 if (info.removeBatchParamsForIdent(ident) >= 0) {
233 if (info.numActiveClients() == 0) {
234 // This is the last connection, we need to de-activate the underlying h/w sensor.
235 actuateHardware = true;
236 } else {
Peng Xud08d30c2017-01-12 20:02:47 -0800237 // Call batch for this sensor with the previously calculated best effort
238 // batch_rate and timeout. One of the apps has unregistered for sensor
239 // events, and the best effort batch parameters might have changed.
240 ALOGD_IF(DEBUG_CONNECTIONS,
241 "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
242 info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
243 info.bestBatchParams.batchTimeout);
244 mSensors->batch(
245 handle,
246 info.bestBatchParams.batchDelay,
247 info.bestBatchParams.batchTimeout);
Andreas Huber99fdbb52016-10-10 13:22:58 -0700248 }
249 } else {
250 // sensor wasn't enabled for this ident
251 }
252
253 if (isClientDisabledLocked(ident)) {
254 return NO_ERROR;
255 }
256 }
257
258 if (actuateHardware) {
259 ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
260 enabled);
261 err = StatusFromResult(mSensors->activate(handle, enabled));
262 ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
263 strerror(-err));
264
265 if (err != NO_ERROR && enabled) {
266 // Failure when enabling the sensor. Clean up on failure.
267 info.removeBatchParamsForIdent(ident);
268 }
269 }
270
Andreas Huber99fdbb52016-10-10 13:22:58 -0700271 return err;
272}
273
274status_t SensorDevice::batch(
275 void* ident,
276 int handle,
277 int flags,
278 int64_t samplingPeriodNs,
279 int64_t maxBatchReportLatencyNs) {
280 if (mSensors == NULL) return NO_INIT;
281
282 if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
283 samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
284 }
285
Andreas Huber99fdbb52016-10-10 13:22:58 -0700286 ALOGD_IF(DEBUG_CONNECTIONS,
287 "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64,
288 ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
289
290 Mutex::Autolock _l(mLock);
291 Info& info(mActivationCount.editValueFor(handle));
292
293 if (info.batchParams.indexOfKey(ident) < 0) {
294 BatchParams params(flags, samplingPeriodNs, maxBatchReportLatencyNs);
295 info.batchParams.add(ident, params);
296 } else {
297 // A batch has already been called with this ident. Update the batch parameters.
298 info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
299 }
300
301 BatchParams prevBestBatchParams = info.bestBatchParams;
302 // Find the minimum of all timeouts and batch_rates for this sensor.
303 info.selectBatchParams();
304
305 ALOGD_IF(DEBUG_CONNECTIONS,
306 "\t>>> curr_period=%" PRId64 " min_period=%" PRId64
307 " curr_timeout=%" PRId64 " min_timeout=%" PRId64,
308 prevBestBatchParams.batchDelay, info.bestBatchParams.batchDelay,
309 prevBestBatchParams.batchTimeout, info.bestBatchParams.batchTimeout);
310
311 status_t err(NO_ERROR);
312 // If the min period or min timeout has changed since the last batch call, call batch.
313 if (prevBestBatchParams != info.bestBatchParams) {
Peng Xud08d30c2017-01-12 20:02:47 -0800314 ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
315 info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
316 info.bestBatchParams.batchTimeout);
317 err = StatusFromResult(
318 mSensors->batch(
319 handle,
320 info.bestBatchParams.batchDelay,
321 info.bestBatchParams.batchTimeout));
Andreas Huber99fdbb52016-10-10 13:22:58 -0700322 if (err != NO_ERROR) {
323 ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s",
324 mSensors.get(), handle,
325 info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
326 info.bestBatchParams.batchTimeout, strerror(-err));
327 info.removeBatchParamsForIdent(ident);
328 }
329 }
330 return err;
331}
332
333status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) {
334 if (mSensors == NULL) return NO_INIT;
335 if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
336 samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
337 }
338 Mutex::Autolock _l(mLock);
339 if (isClientDisabledLocked(ident)) return INVALID_OPERATION;
340 Info& info( mActivationCount.editValueFor(handle) );
341 // If the underlying sensor is NOT in continuous mode, setDelay() should return an error.
342 // Calling setDelay() in batch mode is an invalid operation.
343 if (info.bestBatchParams.batchTimeout != 0) {
344 return INVALID_OPERATION;
345 }
346 ssize_t index = info.batchParams.indexOfKey(ident);
347 if (index < 0) {
348 return BAD_INDEX;
349 }
350 BatchParams& params = info.batchParams.editValueAt(index);
351 params.batchDelay = samplingPeriodNs;
352 info.selectBatchParams();
353
354 return StatusFromResult(
Peng Xud08d30c2017-01-12 20:02:47 -0800355 mSensors->batch(handle, info.bestBatchParams.batchDelay, 0));
Andreas Huber99fdbb52016-10-10 13:22:58 -0700356}
357
358int SensorDevice::getHalDeviceVersion() const {
359 if (mSensors == NULL) return -1;
360 return SENSORS_DEVICE_API_VERSION_1_4;
361}
362
363status_t SensorDevice::flush(void* ident, int handle) {
Andreas Huber99fdbb52016-10-10 13:22:58 -0700364 if (isClientDisabled(ident)) return INVALID_OPERATION;
365 ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
366 return StatusFromResult(mSensors->flush(handle));
367}
368
369bool SensorDevice::isClientDisabled(void* ident) {
370 Mutex::Autolock _l(mLock);
371 return isClientDisabledLocked(ident);
372}
373
374bool SensorDevice::isClientDisabledLocked(void* ident) {
375 return mDisabledClients.indexOf(ident) >= 0;
376}
377
378void SensorDevice::enableAllSensors() {
379 Mutex::Autolock _l(mLock);
380 mDisabledClients.clear();
381 ALOGI("cleared mDisabledClients");
Andreas Huber99fdbb52016-10-10 13:22:58 -0700382 for (size_t i = 0; i< mActivationCount.size(); ++i) {
383 Info& info = mActivationCount.editValueAt(i);
384 if (info.batchParams.isEmpty()) continue;
385 info.selectBatchParams();
386 const int sensor_handle = mActivationCount.keyAt(i);
387 ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
388 sensor_handle);
Peng Xud08d30c2017-01-12 20:02:47 -0800389 status_t err = StatusFromResult(
390 mSensors->batch(
391 sensor_handle,
392 info.bestBatchParams.batchDelay,
393 info.bestBatchParams.batchTimeout));
394 ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
Andreas Huber99fdbb52016-10-10 13:22:58 -0700395
396 if (err == NO_ERROR) {
397 err = StatusFromResult(
398 mSensors->activate(sensor_handle, 1 /* enabled */));
399 ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
400 }
Andreas Huber99fdbb52016-10-10 13:22:58 -0700401 }
402}
403
404void SensorDevice::disableAllSensors() {
405 Mutex::Autolock _l(mLock);
406 for (size_t i = 0; i< mActivationCount.size(); ++i) {
407 const Info& info = mActivationCount.valueAt(i);
408 // Check if this sensor has been activated previously and disable it.
409 if (info.batchParams.size() > 0) {
410 const int sensor_handle = mActivationCount.keyAt(i);
411 ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
412 sensor_handle);
Peng Xud08d30c2017-01-12 20:02:47 -0800413 mSensors->activate(sensor_handle, 0 /* enabled */);
Andreas Huber99fdbb52016-10-10 13:22:58 -0700414
415 // Add all the connections that were registered for this sensor to the disabled
416 // clients list.
417 for (size_t j = 0; j < info.batchParams.size(); ++j) {
418 mDisabledClients.add(info.batchParams.keyAt(j));
419 ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
420 }
421 }
422 }
423}
424
425status_t SensorDevice::injectSensorData(
426 const sensors_event_t *injected_sensor_event) {
427 ALOGD_IF(DEBUG_CONNECTIONS,
428 "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
429 injected_sensor_event->sensor,
430 injected_sensor_event->timestamp, injected_sensor_event->data[0],
431 injected_sensor_event->data[1], injected_sensor_event->data[2],
432 injected_sensor_event->data[3], injected_sensor_event->data[4],
433 injected_sensor_event->data[5]);
434
Andreas Huber99fdbb52016-10-10 13:22:58 -0700435 Event ev;
436 convertFromSensorEvent(*injected_sensor_event, &ev);
437
438 return StatusFromResult(mSensors->injectSensorData(ev));
439}
440
441status_t SensorDevice::setMode(uint32_t mode) {
Andreas Huber99fdbb52016-10-10 13:22:58 -0700442
443 return StatusFromResult(
444 mSensors->setOperationMode(
445 static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
446}
447
448// ---------------------------------------------------------------------------
449
450int SensorDevice::Info::numActiveClients() {
451 SensorDevice& device(SensorDevice::getInstance());
452 int num = 0;
453 for (size_t i = 0; i < batchParams.size(); ++i) {
454 if (!device.isClientDisabledLocked(batchParams.keyAt(i))) {
455 ++num;
456 }
457 }
458 return num;
459}
460
461status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,
462 int64_t samplingPeriodNs,
463 int64_t maxBatchReportLatencyNs) {
464 ssize_t index = batchParams.indexOfKey(ident);
465 if (index < 0) {
466 ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%" PRId64 " timeout=%" PRId64 ") failed (%s)",
467 ident, samplingPeriodNs, maxBatchReportLatencyNs, strerror(-index));
468 return BAD_INDEX;
469 }
470 BatchParams& params = batchParams.editValueAt(index);
471 params.flags = flags;
472 params.batchDelay = samplingPeriodNs;
473 params.batchTimeout = maxBatchReportLatencyNs;
474 return NO_ERROR;
475}
476
477void SensorDevice::Info::selectBatchParams() {
478 BatchParams bestParams(0, -1, -1);
479 SensorDevice& device(SensorDevice::getInstance());
480
481 for (size_t i = 0; i < batchParams.size(); ++i) {
482 if (device.isClientDisabledLocked(batchParams.keyAt(i))) continue;
483 BatchParams params = batchParams.valueAt(i);
484 if (bestParams.batchDelay == -1 || params.batchDelay < bestParams.batchDelay) {
485 bestParams.batchDelay = params.batchDelay;
486 }
487 if (bestParams.batchTimeout == -1 || params.batchTimeout < bestParams.batchTimeout) {
488 bestParams.batchTimeout = params.batchTimeout;
489 }
490 }
491 bestBatchParams = bestParams;
492}
493
494ssize_t SensorDevice::Info::removeBatchParamsForIdent(void* ident) {
495 ssize_t idx = batchParams.removeItem(ident);
496 if (idx >= 0) {
497 selectBatchParams();
498 }
499 return idx;
500}
501
502void SensorDevice::notifyConnectionDestroyed(void* ident) {
503 Mutex::Autolock _l(mLock);
504 mDisabledClients.remove(ident);
505}
506
507void SensorDevice::convertToSensorEvent(
508 const Event &src, sensors_event_t *dst) {
509 ::android::hardware::sensors::V1_0::implementation::convertToSensorEvent(
510 src, dst);
511
Peng Xud08d30c2017-01-12 20:02:47 -0800512 if (src.sensorType == SensorType::DYNAMIC_SENSOR_META) {
Andreas Huber99fdbb52016-10-10 13:22:58 -0700513 const DynamicSensorInfo &dyn = src.u.dynamic;
514
515 dst->dynamic_sensor_meta.connected = dyn.connected;
516 dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
517 if (dyn.connected) {
518 auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
519 CHECK(it != mConnectedDynamicSensors.end());
520
521 dst->dynamic_sensor_meta.sensor = it->second;
522
523 memcpy(dst->dynamic_sensor_meta.uuid,
524 dyn.uuid.data(),
525 sizeof(dst->dynamic_sensor_meta.uuid));
526 }
527 }
528}
529
530void SensorDevice::convertToSensorEvents(
531 const hidl_vec<Event> &src,
532 const hidl_vec<SensorInfo> &dynamicSensorsAdded,
533 sensors_event_t *dst) {
534 // Allocate a sensor_t structure for each dynamic sensor added and insert
535 // it into the dictionary of connected dynamic sensors keyed by handle.
536 for (size_t i = 0; i < dynamicSensorsAdded.size(); ++i) {
537 const SensorInfo &info = dynamicSensorsAdded[i];
538
539 auto it = mConnectedDynamicSensors.find(info.sensorHandle);
540 CHECK(it == mConnectedDynamicSensors.end());
541
542 sensor_t *sensor = new sensor_t;
543 convertToSensor(info, sensor);
544
545 mConnectedDynamicSensors.insert(
546 std::make_pair(sensor->handle, sensor));
547 }
548
549 for (size_t i = 0; i < src.size(); ++i) {
550 convertToSensorEvent(src[i], &dst[i]);
551 }
552}
553
554// ---------------------------------------------------------------------------
555}; // namespace android
556