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