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 "chre/platform/platform_sensor_manager.h" 18 19 #include "sns_std_sensor.pb.h" 20 #include "stringl.h" 21 22 #include <cmath> 23 24 #include "chre/core/event_loop_manager.h" 25 #include "chre/core/sensor.h" 26 #include "chre/core/sensor_type_helpers.h" 27 #include "chre/platform/log.h" 28 #include "chre/platform/slpi/power_control_util.h" 29 #include "chre/platform/system_time.h" 30 #include "chre_api/chre/sensor.h" 31 32 #ifdef CHREX_SENSOR_SUPPORT 33 #include "chre/extensions/platform/slpi/see/vendor_data_types.h" 34 #endif // CHREX_SENSOR_SUPPORT 35 36 #ifdef CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST 37 #include "see_sensors.h" 38 #endif // CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST 39 40 #ifndef CHRE_SEE_NUM_TEMP_SENSORS 41 // There are usually more than one 'sensor_temperature' sensors in SEE. 42 // Define this in the variant-specific makefile to avoid missing sensors in 43 // sensor discovery. 44 #error "CHRE_SEE_NUM_TEMP_SENSORS is not defined" 45 #endif 46 47 namespace chre { 48 namespace { 49 50 //! A struct to facilitate sensor discovery 51 struct SuidAttr { 52 sns_std_suid suid; 53 SeeAttributes attr; 54 }; 55 56 #ifndef CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST 57 58 //! The list of SEE platform sensor data types that CHRE intends to support. 59 //! The standardized strings are defined in sns_xxx.proto. 60 const char *kSeeDataTypes[] = { 61 "accel", 62 "gyro", 63 "mag", 64 "pressure", 65 "ambient_light", 66 "proximity", 67 #ifdef CHRE_SLPI_DEFAULT_BUILD 68 // Both instant motion and stationary detect share the same data type. 69 "amd", 70 "amd", 71 #else 72 "motion_detect", "stationary_detect", 73 #endif 74 }; 75 76 #endif // CHRE_VARIANT_SUPPLIES_SEE_SENSORS_LIST 77 78 #ifdef CHRE_SLPI_UIMG_ENABLED 79 #ifndef CHREX_SENSOR_SUPPORT 80 // The current implementation uses vendor sensor type 3 to remap into accel, 81 // with requests made through QMI instead of QSockets, as SEE does not support 82 // micro-image batching in QCM. 83 #error "CHRE extensions are required for micro-image SEE support" 84 #endif // CHREX_SENSOR_SUPPORT 85 86 bool isBigImageSensorType(uint8_t sensorType) { 87 return (sensorType == CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_ACCEL || 88 sensorType == CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_ACCEL || 89 sensorType == CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_GYRO || 90 sensorType == CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_MAG || 91 sensorType == CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_LIGHT); 92 } 93 94 /** 95 * Obtains the big-image sensor type given the specified data type and whether 96 * the sensor is runtime-calibrated or not. 97 */ 98 bool getBigImageSensorTypeFromDataType(const char *dataType, bool calibrated, 99 uint8_t *sensorType) { 100 bool found = true; 101 if (strcmp(dataType, "accel") == 0) { 102 if (calibrated) { 103 *sensorType = CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_ACCEL; 104 } else { 105 *sensorType = CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_ACCEL; 106 } 107 } else if (strcmp(dataType, "gyro") == 0 && !calibrated) { 108 *sensorType = CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_GYRO; 109 } else if (strcmp(dataType, "mag") == 0 && !calibrated) { 110 *sensorType = CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_UNCAL_MAG; 111 } else if (strcmp(dataType, "ambient_light") == 0 && calibrated) { 112 *sensorType = CHRE_SLPI_SENSOR_TYPE_BIG_IMAGE_LIGHT; 113 } else { 114 found = false; 115 } 116 return found; 117 } 118 119 /** 120 * Obtains the micro-image sensor type given the specified sensor type. 121 * 122 * @param sensorType The sensor type to convert from. 123 * @return The associated micro-image sensor type, or the input sensor type 124 * if not associated with one 125 */ 126 uint8_t getUimgSensorType(uint8_t sensorType) { 127 switch (sensorType) { 128 case (CHRE_SENSOR_TYPE_VENDOR_START + 3): 129 return CHRE_SENSOR_TYPE_ACCELEROMETER; 130 case (CHRE_SENSOR_TYPE_VENDOR_START + 6): 131 return CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER; 132 case (CHRE_SENSOR_TYPE_VENDOR_START + 7): 133 return CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE; 134 case (CHRE_SENSOR_TYPE_VENDOR_START + 8): 135 return CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD; 136 case (CHRE_SENSOR_TYPE_VENDOR_START + 9): 137 return CHRE_SENSOR_TYPE_LIGHT; 138 default: 139 return sensorType; 140 } 141 } 142 143 #endif // CHRE_SLPI_UIMG_ENABLED 144 145 void handleMissingSensor() { 146 // Try rebooting if a sensor is missing, which might help recover from a 147 // transient failure/race condition at startup. But to avoid endless crashes, 148 // only do this within 15 seconds of the timeout on initializing SEE - we rely 149 // on knowledge that getMonotonicTime() maps into QTimer here, and QTimer only 150 // resets when the entire system is rebooted (it continues increasing after 151 // SLPI SSR). 152 #ifndef CHRE_LOG_ONLY_NO_SENSOR 153 if (SystemTime::getMonotonicTime() < (kDefaultSeeWaitTimeout + Seconds(15))) { 154 FATAL_ERROR("Missing required sensor(s)"); 155 } else 156 #endif 157 { 158 LOGE("Missing required sensor(s)"); 159 } 160 } 161 162 /** 163 * Obtains the sensor type given the specified data type and whether the sensor 164 * is runtime-calibrated or not. 165 * 166 * @return Whether a sensor type was found for the given data type. 167 */ 168 bool getSensorTypeFromDataType(const char *dataType, bool calibrated, 169 uint8_t *sensorType) { 170 bool success = true; 171 if (strcmp(dataType, "accel") == 0) { 172 if (calibrated) { 173 *sensorType = CHRE_SENSOR_TYPE_ACCELEROMETER; 174 } else { 175 *sensorType = CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER; 176 } 177 } else if (strcmp(dataType, "gyro") == 0) { 178 if (calibrated) { 179 *sensorType = CHRE_SENSOR_TYPE_GYROSCOPE; 180 } else { 181 *sensorType = CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE; 182 } 183 } else if (strcmp(dataType, "mag") == 0) { 184 if (calibrated) { 185 *sensorType = CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD; 186 } else { 187 *sensorType = CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD; 188 } 189 } else if (strcmp(dataType, "pressure") == 0) { 190 *sensorType = CHRE_SENSOR_TYPE_PRESSURE; 191 } else if (strcmp(dataType, "ambient_light") == 0) { 192 *sensorType = CHRE_SENSOR_TYPE_LIGHT; 193 } else if (strcmp(dataType, "proximity") == 0) { 194 *sensorType = CHRE_SENSOR_TYPE_PROXIMITY; 195 } else if (strcmp(dataType, "motion_detect") == 0 || 196 strcmp(dataType, "amd") == 0) { 197 *sensorType = CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT; 198 } else if (strcmp(dataType, "stationary_detect") == 0) { 199 *sensorType = CHRE_SENSOR_TYPE_STATIONARY_DETECT; 200 } else if (strcmp(dataType, "step_detect") == 0) { 201 *sensorType = CHRE_SENSOR_TYPE_STEP_DETECT; 202 } else { 203 #ifdef CHREX_SENSOR_SUPPORT 204 success = extension::vendorSensorTypeFromDataType(dataType, calibrated, 205 sensorType); 206 } 207 #else 208 success = false; 209 } 210 #endif 211 return success; 212 } 213 214 /** 215 * Merges a status update with an existing sampling status. 216 */ 217 void mergeUpdatedStatus( 218 uint32_t sensorHandle, 219 const SeeHelperCallbackInterface::SamplingStatusData &update, 220 struct chreSensorSamplingStatus *mergedStatus) { 221 Sensor *sensor = getSensorRequestManager().getSensor(sensorHandle); 222 sensor->getSamplingStatus(mergedStatus); 223 224 if (update.enabledValid) { 225 mergedStatus->enabled = update.status.enabled; 226 } 227 if (update.intervalValid) { 228 mergedStatus->interval = update.status.interval; 229 } 230 if (update.latencyValid) { 231 mergedStatus->latency = update.status.latency; 232 } 233 } 234 235 /** 236 * Helper function to post a bias event given the bias data. 237 * 238 * @param sensorType The sensor type to post the event for. 239 * @param bias The bias data. 240 */ 241 void postSensorBiasEvent(uint8_t sensorType, 242 const chreSensorThreeAxisData &bias) { 243 uint16_t eventType; 244 if (SensorTypeHelpers::getBiasEventType(sensorType, &eventType)) { 245 auto *event = memoryAlloc<struct chreSensorThreeAxisData>(); 246 if (event == nullptr) { 247 LOG_OOM(); 248 } else { 249 *event = bias; 250 getSensorRequestManager().getSensorHandle(sensorType, 251 &event->header.sensorHandle); 252 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie( 253 eventType, event, freeEventDataCallback); 254 } 255 } 256 } 257 258 /** 259 * Compares the given status updates and returns true if they are the same. 260 * 261 * A simple memcmp cannot be done because if a given field is not valid, then 262 * the field may be different across updates, but doesn't indicate the update 263 * is different. 264 */ 265 bool isSameStatusUpdate( 266 const SeeHelperCallbackInterface::SamplingStatusData &status1, 267 const SeeHelperCallbackInterface::SamplingStatusData &status2) { 268 bool sameStatus = status1.enabledValid == status2.enabledValid; 269 if (sameStatus && status1.enabledValid) { 270 sameStatus &= status1.status.enabled == status2.status.enabled; 271 } 272 // Only check interval / latency fields if both status updates say the sensor 273 // is enabled since CHRE doesn't care what the fields are set to if the sensor 274 // is disabled. 275 if (sameStatus && status1.status.enabled) { 276 sameStatus &= status1.intervalValid == status2.intervalValid; 277 if (sameStatus && status1.intervalValid) { 278 sameStatus &= status1.status.interval == status2.status.interval; 279 } 280 sameStatus &= status1.latencyValid == status2.latencyValid; 281 if (sameStatus && status1.latencyValid) { 282 sameStatus &= status1.status.latency == status2.status.latency; 283 } 284 } 285 return sameStatus; 286 } 287 288 /** 289 * Constructs and initializes a sensor, and adds it to the sensor list. 290 * 291 * @param seeHelper SeeHelper instance to register sensor with 292 * @param sensorType The sensor type of the sensor. 293 * @param suid The SUID of the sensor as provided by SEE. 294 * @param attr A reference to SeeAttrbutes. 295 * @param sensors The sensor list. 296 */ 297 void addSensor(SeeHelper &seeHelper, uint8_t sensorType, 298 const sns_std_suid &suid, const SeeAttributes &attr, 299 DynamicVector<Sensor> *sensors) { 300 // Concatenate vendor and name with a space in between. 301 char sensorName[kSensorNameMaxLen]; 302 strlcpy(sensorName, attr.vendor, sizeof(sensorName)); 303 strlcat(sensorName, " ", sizeof(sensorName)); 304 strlcat(sensorName, attr.name, sizeof(sensorName)); 305 306 // Some sensors have a max sample rate of 0 which makes ceilf return infinity 307 // for on-change or continuous sensors when that's not the correct 308 // minInterval. 309 float maxSampleRate = (attr.maxSampleRate == 0.0f) ? 10 : attr.maxSampleRate; 310 311 // Override one-shot sensor's minInterval to default 312 uint64_t minInterval = 313 SensorTypeHelpers::isOneShot(sensorType) 314 ? CHRE_SENSOR_INTERVAL_DEFAULT 315 : static_cast<uint64_t>( 316 ceilf(Seconds(1).toRawNanoseconds() / maxSampleRate)); 317 318 if (!sensors->emplace_back()) { 319 FATAL_ERROR("Failed to allocate new sensor: out of memory"); 320 } 321 322 // The sensor base class must be initialized before the main Sensor init() 323 // can be invoked as init() is allowed to invoke base class methods. 324 sensors->back().initBase(sensorType, minInterval, sensorName, 325 attr.passiveRequest); 326 sensors->back().init(); 327 328 // Resample big image sensors to reduce system load during sw flush. 329 #ifdef CHRE_SLPI_UIMG_ENABLED 330 bool resample = isBigImageSensorType(sensorType); 331 #else 332 bool resample = false; 333 #endif 334 bool prevRegistered; 335 bool registered = 336 seeHelper.registerSensor(sensorType, suid, resample, &prevRegistered); 337 if (!registered && prevRegistered) { 338 LOGW("SUID has been previously registered"); 339 } else if (!registered) { 340 FATAL_ERROR("Failed to register SUID/SensorType mapping."); 341 } 342 } 343 344 /** 345 * Compare SEE reported stream type attribute to the expected one. Some SEE 346 * sensors may support more than one stream type. 347 */ 348 bool isStreamTypeCorrect(uint8_t sensorType, uint8_t streamType) { 349 bool success = true; 350 if ((SensorTypeHelpers::isContinuous(sensorType) && 351 streamType != SNS_STD_SENSOR_STREAM_TYPE_STREAMING) || 352 (SensorTypeHelpers::isOnChange(sensorType) && 353 streamType != SNS_STD_SENSOR_STREAM_TYPE_ON_CHANGE) 354 // The default SLPI build exposes instant motion / stationary sensors as 355 // on-change, but CHRE uses them as one-shot 356 #ifndef CHRE_SLPI_DEFAULT_BUILD 357 || (SensorTypeHelpers::isOneShot(sensorType) && 358 streamType != SNS_STD_SENSOR_STREAM_TYPE_SINGLE_OUTPUT) 359 #endif 360 ) { 361 success = false; 362 LOGW("Inconsistent sensor type %" PRIu8 " and stream type %" PRIu8, 363 static_cast<uint8_t>(sensorType), streamType); 364 } 365 return success; 366 } 367 368 /** 369 * Obtains the list of SUIDs and their attributes that support the specified 370 * data type. 371 */ 372 bool getSuidAndAttrs(SeeHelper &seeHelper, const char *dataType, 373 DynamicVector<SuidAttr> *suidAttrs, uint8_t minNumSuids) { 374 DynamicVector<sns_std_suid> suids; 375 bool success = seeHelper.findSuidSync(dataType, &suids, minNumSuids); 376 if (!success) { 377 LOGE("Failed to find sensor '%s'", dataType); 378 } else { 379 LOGD("Num of SUIDs found for '%s': %zu", dataType, suids.size()); 380 381 for (const auto &suid : suids) { 382 SeeAttributes attr; 383 if (!seeHelper.getAttributesSync(suid, &attr)) { 384 success = false; 385 LOGE("Failed to get attributes of SUID 0x%" PRIx64 " %" PRIx64, 386 suid.suid_high, suid.suid_low); 387 } else { 388 LOGI("%s %s, hw id %" PRId64 ", max ODR %f Hz, stream type %" PRIu8 389 " passive %d", 390 attr.vendor, attr.name, attr.hwId, attr.maxSampleRate, 391 attr.streamType, attr.passiveRequest); 392 SuidAttr sensor = { 393 .suid = suid, 394 .attr = attr, 395 }; 396 if (!suidAttrs->push_back(sensor)) { 397 success = false; 398 LOG_OOM(); 399 } 400 } 401 } 402 } 403 return success; 404 } 405 406 #ifndef CHRE_SLPI_DEFAULT_BUILD 407 //! Check whether two sensors with the specified attrtibutes belong to the same 408 //! sensor hardware module. 409 bool sensorHwMatch(const SeeAttributes &attr0, const SeeAttributes &attr1) { 410 // When HW ID is absent, its default to 0 and won't be a factor. 411 return ((strncmp(attr0.vendor, attr1.vendor, kSeeAttrStrValLen) == 0) && 412 (strncmp(attr0.name, attr1.name, kSeeAttrStrValLen) == 0) && 413 (attr0.hwId == attr1.hwId)); 414 } 415 #endif 416 417 /** 418 * Looks up SUID(s) associated with a given sensor data type string and sensor 419 * type enum, registers them with SeeHelper, and adds a Sensor instance to the 420 * supplied vector for use in CHRE. When given an uncalibrated sensor type, will 421 * also look for and add the calibrated sensor type. 422 * 423 * @param seeHelper SeeHelper instance to use for lookup/registration 424 * @param temperatureSensors List of previously discovered temperature sensor 425 * info to use for adding temp sensors associated with this sensor type 426 * @param dataType SEE data type string 427 * @param sensorType CHRE sensor type associated with dataType 428 * @param skipAdditionalTypes if true, don't attempt to add 429 * calibrated/temperature sensor types associated with this sensorType 430 * @param sensors Vector to append found sensor(s) to 431 */ 432 void findAndAddSensorsForType(SeeHelper &seeHelper, 433 const DynamicVector<SuidAttr> &temperatureSensors, 434 const char *dataType, uint8_t sensorType, 435 bool skipAdditionalTypes, 436 DynamicVector<Sensor> *sensors) { 437 DynamicVector<SuidAttr> primarySensors; 438 if (!getSuidAndAttrs(seeHelper, dataType, &primarySensors, 439 1 /* minNumSuids */)) { 440 handleMissingSensor(); 441 } 442 443 for (const auto &primarySensor : primarySensors) { 444 sns_std_suid suid = primarySensor.suid; 445 SeeAttributes attr = primarySensor.attr; 446 447 // Some sensors support both continuous and on-change streams. 448 // If there are more than one SUIDs that support the data type, 449 // choose the first one that has the expected stream type. 450 if (isStreamTypeCorrect(sensorType, attr.streamType)) { 451 addSensor(seeHelper, sensorType, suid, attr, sensors); 452 453 if (!skipAdditionalTypes) { 454 // Check if this sensor has a runtime-calibrated version. 455 uint8_t calibratedType; 456 if (getSensorTypeFromDataType(dataType, true /* calibrated */, 457 &calibratedType) && 458 calibratedType != sensorType) { 459 addSensor(seeHelper, calibratedType, suid, attr, sensors); 460 } 461 462 // Check if this sensor has a secondary temperature sensor. 463 uint8_t temperatureType = 464 PlatformSensorTypeHelpers::getTempSensorType(sensorType); 465 if (temperatureType != CHRE_SENSOR_TYPE_INVALID) { 466 bool tempFound = false; 467 for (const auto &tempSensor : temperatureSensors) { 468 sns_std_suid tempSuid = tempSensor.suid; 469 SeeAttributes tempAttr = tempSensor.attr; 470 471 #ifdef CHRE_SLPI_DEFAULT_BUILD 472 // The default build exposes a single temp sensor to be used for 473 // all temperature sensors that doesn't have the same attributes 474 // as the primarySensor. 475 if (true) { 476 #else 477 if (sensorHwMatch(attr, tempAttr)) { 478 #endif 479 LOGD("Found matching temperature sensor type"); 480 tempFound = true; 481 addSensor(seeHelper, temperatureType, tempSuid, tempAttr, 482 sensors); 483 break; 484 } 485 } 486 if (!tempFound) { 487 LOGW("Temperature sensor type %" PRIu8 " not found!", 488 static_cast<uint8_t>(temperatureType)); 489 } 490 } 491 } 492 break; 493 } 494 } 495 } 496 497 } // namespace 498 499 PlatformSensorManager::~PlatformSensorManager() {} 500 501 void PlatformSensorManager::init() { 502 if (!mSeeHelper.init(this)) { 503 FATAL_ERROR("Failed to initialize SEE helper"); 504 } 505 506 #ifdef CHRE_SLPI_UIMG_ENABLED 507 if (!mBigImageSeeHelper.init(this, kDefaultSeeWaitTimeout, 508 true /* skipDefaultSensorInit */)) { 509 FATAL_ERROR("Failed to init bimg SEE helper"); 510 } 511 #endif // CHRE_SLPI_UIMG_ENABLED 512 } 513 514 SeeHelper &PlatformSensorManagerBase::getSeeHelperForSensorType( 515 uint8_t sensorType) { 516 #ifdef CHRE_SLPI_UIMG_ENABLED 517 if (isBigImageSensorType(sensorType)) { 518 slpiForceBigImage(); 519 return mBigImageSeeHelper; 520 } else 521 #endif 522 { 523 return mSeeHelper; 524 } 525 } 526 527 #ifdef CHRE_SLPI_UIMG_ENABLED 528 void PlatformSensorManagerBase::getBigImageSensors( 529 DynamicVector<Sensor> *sensors) { 530 CHRE_ASSERT(sensors); 531 532 // Currently, just adding calibrated accel, uncal accel/gyro/mag and als as 533 // they are the ones we know that big image nanoapps will need at a different 534 // batching rate compared to uimg. 535 const char *kBigImageDataTypes[] = { 536 "accel", 537 "gyro", 538 "mag", 539 "ambient_light", 540 }; 541 542 DynamicVector<SuidAttr> nullTemperatureSensorList; 543 544 for (size_t i = 0; i < ARRAY_SIZE(kBigImageDataTypes); i++) { 545 const char *dataType = kBigImageDataTypes[i]; 546 // Loop through potential cal/uncal sensors. 547 for (size_t j = 0; j < 2; j++) { 548 uint8_t sensorType; 549 if (getBigImageSensorTypeFromDataType(dataType, (j == 0) /* calibrated */, 550 &sensorType)) { 551 findAndAddSensorsForType(mBigImageSeeHelper, nullTemperatureSensorList, 552 dataType, sensorType, 553 true /* skipAdditionalTypes */, sensors); 554 } 555 } 556 } 557 } 558 #endif // CHRE_SLPI_UIMG_ENABLED 559 560 DynamicVector<Sensor> PlatformSensorManager::getSensors() { 561 DynamicVector<Sensor> sensors; 562 DynamicVector<SuidAttr> tempSensors; 563 if (!getSuidAndAttrs(mSeeHelper, "sensor_temperature", &tempSensors, 564 CHRE_SEE_NUM_TEMP_SENSORS)) { 565 handleMissingSensor(); 566 } 567 568 #ifndef CHREX_SENSOR_SUPPORT 569 const char *kVendorDataTypes[] = {}; 570 #endif // CHREX_SENSOR_SUPPORT 571 constexpr size_t kNumSeeTypes = ARRAY_SIZE(kSeeDataTypes); 572 constexpr size_t kNumVendorTypes = ARRAY_SIZE(kVendorDataTypes); 573 for (size_t i = 0; i < kNumSeeTypes + kNumVendorTypes; i++) { 574 const char *dataType = (i < kNumSeeTypes) 575 ? kSeeDataTypes[i] 576 : kVendorDataTypes[i - kNumSeeTypes]; 577 578 uint8_t sensorType; 579 if (!getSensorTypeFromDataType(dataType, false /* calibrated */, 580 &sensorType)) { 581 LOGE("Unknown sensor type found for '%s'", dataType); 582 continue; 583 } 584 585 bool skipAdditionalTypes = false; 586 587 #ifdef CHRE_SLPI_DEFAULT_BUILD 588 // Stationary and motion detect share the same dataType on the default build 589 if (sensorType == CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT && 590 i == kNumSeeTypes - 1) { 591 sensorType = CHRE_SENSOR_TYPE_STATIONARY_DETECT; 592 // Skip additional types or InstantMotion will be added to the sensor list 593 // twice. 594 skipAdditionalTypes = true; 595 } 596 #endif 597 598 findAndAddSensorsForType(mSeeHelper, tempSensors, dataType, sensorType, 599 skipAdditionalTypes, &sensors); 600 } 601 602 #ifdef CHRE_SLPI_UIMG_ENABLED 603 getBigImageSensors(&sensors); 604 #endif 605 606 return sensors; 607 } 608 609 bool PlatformSensorManager::configureSensor(Sensor &sensor, 610 const SensorRequest &request) { 611 SeeSensorRequest req = { 612 .sensorType = sensor.getSensorType(), 613 .enable = (request.getMode() != SensorMode::Off), 614 .passive = sensorModeIsPassive(request.getMode()), 615 .samplingRateHz = static_cast<float>( 616 kOneSecondInNanoseconds / request.getInterval().toRawNanoseconds()), 617 // Override batch period to 0 for micro-image non-continuous sensors to 618 // ensure one sample per batch so that nanoapps do not miss state changes. 619 .batchPeriodUs = 620 #ifdef CHRE_SLPI_UIMG_ENABLED 621 (!sensor.isContinuous() && 622 !isBigImageSensorType(sensor.getSensorType())) 623 ? 0 624 : 625 #endif 626 static_cast<uint32_t>(request.getLatency().toRawNanoseconds() / 627 kOneMicrosecondInNanoseconds), 628 }; 629 630 SeeHelper &seeHelper = getSeeHelperForSensorType(sensor.getSensorType()); 631 bool wasInUImage = slpiInUImage(); 632 633 bool success = true; 634 635 // TODO(b/150144912): Merge the two implementations to avoid having separate 636 // code paths. 637 #ifdef CHRE_SLPI_DEFAULT_BUILD 638 // Calibration updates are not enabled automatically in the default build. 639 SeeCalHelper *calHelper = seeHelper.getCalHelper(); 640 641 const sns_std_suid *suid = 642 calHelper->getCalSuidFromSensorType(sensor.getSensorType()); 643 bool wereCalUpdatesEnabled = false; 644 if (suid != nullptr) { 645 wereCalUpdatesEnabled = calHelper->areCalUpdatesEnabled(*suid); 646 success = calHelper->configureCalUpdates(*suid, req.enable, seeHelper); 647 } 648 #endif 649 650 if (success) { 651 success = seeHelper.makeRequest(req); 652 } 653 654 #ifdef CHRE_SLPI_DEFAULT_BUILD 655 // If any part of the configuration process failed, reset our subscription 656 // for calibration updates to its previous value to attempt to restore state. 657 if (suid != nullptr && !success) { 658 bool areCalUpdatesEnabled = calHelper->areCalUpdatesEnabled(*suid); 659 if (areCalUpdatesEnabled != wereCalUpdatesEnabled) { 660 calHelper->configureCalUpdates(*suid, wereCalUpdatesEnabled, seeHelper); 661 } 662 } 663 #endif 664 665 // If we dropped into micro-image during that blocking call to SEE, go back 666 // to big image. This won't happen if the calling nanoapp is a big image one, 667 // but other code paths currently assume that we will only transition from big 668 // image to micro-image from CHRE's perspective while it's waiting for an 669 // event to arrive in its empty queue. 670 // TODO: transition back to big image only when needed, at the point of 671 // invoking a nanoapp's free event/message callback 672 if (!wasInUImage && slpiInUImage()) { 673 LOGD("Restoring big image operating mode"); 674 slpiForceBigImage(); 675 } 676 677 if (success) { 678 // TODO: remove setSamplingStatus when .latency is available in status 679 // update from SEE. 680 struct chreSensorSamplingStatus status; 681 if (sensor.getSamplingStatus(&status)) { 682 // If passive request is not supported by this SEE sensor, it won't be 683 // dynamically enabled/disabled and its status stays the same as set here. 684 if (!sensor.supportsPassiveMode()) { 685 status.enabled = req.enable; 686 } 687 status.latency = req.batchPeriodUs * kOneMicrosecondInNanoseconds; 688 sensor.setSamplingStatus(status); 689 } 690 } 691 return success; 692 } 693 694 bool PlatformSensorManager::configureBiasEvents(const Sensor & /* sensor */, 695 bool /* enable */, 696 uint64_t /* latencyNs */) { 697 // TODO: Allow enabling / disabling bias events rather than enabling all 698 // bias sensors at init. 699 return true; 700 } 701 702 bool PlatformSensorManager::getThreeAxisBias( 703 const Sensor &sensor, struct chreSensorThreeAxisData *bias) const { 704 uint8_t sensorType = sensor.getSensorType(); 705 SeeCalHelper *calHelper = 706 getSeeHelperForSensorType(sensorType).getCalHelper(); 707 708 bool success = sensor.reportsBiasEvents(); 709 if (success) { 710 // We use the runtime-calibrated sensor type here, per documentation 711 // of SeeCalHelper::getBias(), but overwrite the sensorHandle to that of 712 // the current sensor, because the calibration data itself is equivalent 713 // for both calibrated/uncalibrated sensor types. 714 #ifdef CHRE_SLPI_UIMG_ENABLED 715 // Use the uimg runtime-calibrated sensor type to get the calibration 716 // bias, since SeeCalHelper is unaware of the bimg/uimg differentiation. 717 uint8_t calSensorType = PlatformSensorTypeHelpers::toCalibratedSensorType( 718 getUimgSensorType(sensorType)); 719 #else 720 uint8_t calSensorType = 721 PlatformSensorTypeHelpers::toCalibratedSensorType(sensorType); 722 #endif 723 if (!calHelper->getBias(calSensorType, bias)) { 724 // Set to zero bias + unknown accuracy per CHRE API requirements. 725 memset(bias, 0, sizeof(chreSensorThreeAxisData)); 726 bias->header.readingCount = 1; 727 bias->header.accuracy = CHRE_SENSOR_ACCURACY_UNKNOWN; 728 } 729 730 // Overwrite sensorHandle to match the request type. 731 getSensorRequestManager().getSensorHandle(sensorType, 732 &bias->header.sensorHandle); 733 } 734 735 return success; 736 } 737 738 bool PlatformSensorManager::flush(const Sensor &sensor, 739 uint32_t *flushRequestId) { 740 uint8_t sensorType = sensor.getSensorType(); 741 return getSeeHelperForSensorType(sensorType).flush(sensorType); 742 } 743 744 void PlatformSensorManager::releaseSamplingStatusUpdate( 745 struct chreSensorSamplingStatus *status) { 746 memoryFree(status); 747 } 748 749 void PlatformSensorManager::releaseSensorDataEvent(void *data) { 750 memoryFree(data); 751 } 752 753 void PlatformSensorManager::releaseBiasEvent(void *biasData) { 754 memoryFree(biasData); 755 } 756 757 void PlatformSensorManagerBase::onSamplingStatusUpdate( 758 UniquePtr<SeeHelperCallbackInterface::SamplingStatusData> &&status) { 759 uint32_t sensorHandle; 760 getSensorRequestManager().getSensorHandle(status->sensorType, &sensorHandle); 761 Sensor *sensor = getSensorRequestManager().getSensor(sensorHandle); 762 763 // TODO: Once the latency field is actually filled in by SEE, modify this 764 // logic to avoid reacting if the latency and interval of the sensor are 765 // updated separately, but contain the same info as before. 766 if (sensor != nullptr) { 767 // Ignore the enabled flag from status update if this is not a passive mode 768 // supported sensor because this may cause the sampling status in CHRE to 769 // go out of sync with reality 770 if (!sensor->supportsPassiveMode()) { 771 status->status.enabled = 772 sensor->mLastReceivedSamplingStatus.status.enabled; 773 status->enabledValid = sensor->mLastReceivedSamplingStatus.enabledValid; 774 } 775 if (!isSameStatusUpdate(sensor->mLastReceivedSamplingStatus, 776 *status.get())) { 777 sensor->mLastReceivedSamplingStatus = *status.get(); 778 779 auto callback = [](uint16_t /* type */, void *data) { 780 auto cbData = UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>( 781 static_cast<SeeHelperCallbackInterface::SamplingStatusData *>( 782 data)); 783 784 uint32_t sensorHandle; 785 getSensorRequestManager().getSensorHandle(cbData->sensorType, 786 &sensorHandle); 787 788 // Memory will be freed after core framework performs its updates. 789 struct chreSensorSamplingStatus *status = 790 memoryAlloc<struct chreSensorSamplingStatus>(); 791 mergeUpdatedStatus(sensorHandle, *cbData.get(), status); 792 793 getSensorRequestManager().handleSamplingStatusUpdate(sensorHandle, 794 status); 795 }; 796 // Schedule a deferred callback to handle sensor status change in the main 797 // thread. 798 EventLoopManagerSingleton::get()->deferCallback( 799 SystemCallbackType::SensorStatusUpdate, status.release(), callback); 800 } 801 } 802 } 803 804 void PlatformSensorManagerBase::onSensorDataEvent( 805 uint8_t sensorType, UniquePtr<uint8_t> &&eventData) { 806 uint32_t sensorHandle; 807 getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle); 808 auto *header = 809 reinterpret_cast<struct chreSensorDataHeader *>(eventData.get()); 810 header->sensorHandle = sensorHandle; 811 812 getSensorRequestManager().handleSensorDataEvent(sensorHandle, 813 eventData.release()); 814 } 815 816 void PlatformSensorManagerBase::onHostWakeSuspendEvent(bool awake) { 817 // Host wake events are sent as soon as SEE is up so verify the event loop is 818 // up before attempting to post the event to avoid a crash. 819 if (EventLoopManagerSingleton::isInitialized()) { 820 EventLoopManagerSingleton::get() 821 ->getEventLoop() 822 .getPowerControlManager() 823 .onHostWakeSuspendEvent(awake); 824 } 825 } 826 827 void PlatformSensorManagerBase::onSensorBiasEvent( 828 uint8_t sensorType, UniquePtr<struct chreSensorThreeAxisData> &&biasData) { 829 uint32_t sensorHandle; 830 if (getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle)) { 831 biasData->header.sensorHandle = sensorHandle; 832 Sensor *sensor = getSensorRequestManager().getSensor(sensorHandle); 833 if (!sensor->reportsBiasEvents()) { 834 LOGE("Received bias event for unsupported sensor type %" PRIu8, 835 sensorType); 836 } else { 837 // Posts newly allocated event for the uncalibrated type 838 postSensorBiasEvent( 839 PlatformSensorTypeHelpers::toUncalibratedSensorType(sensorType), 840 *biasData); 841 842 getSensorRequestManager().handleBiasEvent(sensorHandle, 843 biasData.release()); 844 } 845 } 846 } 847 848 void PlatformSensorManagerBase::onFlushCompleteEvent(uint8_t sensorType) { 849 // Flush complete events are sent after any batch delivery so verify the 850 // event loop is up before attempting to post the event to avoid a crash. 851 if (EventLoopManagerSingleton::isInitialized()) { 852 // TODO: Have SEE pass flush request IDs through the flush complete event 853 uint32_t sensorHandle; 854 getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle); 855 getSensorRequestManager().handleFlushCompleteEvent( 856 sensorHandle, UINT32_MAX, /* invalid flush request ID */ 857 CHRE_ERROR_NONE); 858 } 859 } 860 861 } // namespace chre 862