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