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