1 /* 2 * Copyright (C) 2017 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.h" 18 19 #include "sns_std_sensor.pb.h" 20 #include "stringl.h" 21 22 #include <cmath> 23 24 #include "chre_api/chre/sensor.h" 25 #include "chre/core/event_loop_manager.h" 26 #include "chre/core/sensor.h" 27 #include "chre/platform/assert.h" 28 #include "chre/platform/fatal_error.h" 29 #include "chre/platform/log.h" 30 #include "chre/platform/shared/platform_sensor_util.h" 31 #include "chre/platform/slpi/see/see_client.h" 32 #include "chre/platform/slpi/see/see_helper.h" 33 #include "chre/platform/system_time.h" 34 35 #ifdef CHREX_SENSOR_SUPPORT 36 #include "chre/extensions/platform/slpi/see/vendor_data_types.h" 37 #endif // CHREX_SENSOR_SUPPORT 38 39 #ifndef CHRE_SEE_NUM_TEMP_SENSORS 40 // There are usually more than one 'sensor_temperature' sensors in SEE. 41 // Define this in the variant-specific makefile to avoid missing sensors in 42 // sensor discovery. 43 #error "CHRE_SEE_NUM_TEMP_SENSORS is not defined" 44 #endif 45 46 namespace chre { 47 namespace { 48 49 //! A class that implements SeeHelperCallbackInterface. 50 class SeeHelperCallback : public SeeHelperCallbackInterface { 51 void onSamplingStatusUpdate( 52 UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>&& status) 53 override; 54 55 void onSensorDataEvent( 56 SensorType sensorType, UniquePtr<uint8_t>&& eventData) override; 57 58 void onHostWakeSuspendEvent(bool awake) override; 59 }; 60 61 //! A struct to facilitate sensor discovery 62 struct SuidAttr { 63 sns_std_suid suid; 64 SeeAttributes attr; 65 }; 66 67 //! The list of SEE platform sensor data types that CHRE intends to support. 68 //! The standardized strings are defined in sns_xxx.proto. 69 const char *kSeeDataTypes[] = { 70 "accel", 71 "gyro", 72 "mag", 73 "pressure", 74 "ambient_light", 75 "proximity", 76 "motion_detect", 77 "stationary_detect", 78 }; 79 80 /** 81 * Obtains the sensor type given the specified data type and whether the sensor 82 * is runtime-calibrated or not. 83 */ 84 SensorType getSensorTypeFromDataType(const char *dataType, bool calibrated) { 85 SensorType sensorType; 86 if (strcmp(dataType, "accel") == 0) { 87 if (calibrated) { 88 sensorType = SensorType::Accelerometer; 89 } else { 90 sensorType = SensorType::UncalibratedAccelerometer; 91 } 92 } else if (strcmp(dataType, "gyro") == 0) { 93 if (calibrated) { 94 sensorType = SensorType::Gyroscope; 95 } else { 96 sensorType = SensorType::UncalibratedGyroscope; 97 } 98 } else if (strcmp(dataType, "mag") == 0) { 99 if (calibrated) { 100 sensorType = SensorType::GeomagneticField; 101 } else { 102 sensorType = SensorType::UncalibratedGeomagneticField; 103 } 104 } else if (strcmp(dataType, "pressure") == 0) { 105 sensorType = SensorType::Pressure; 106 } else if (strcmp(dataType, "ambient_light") == 0) { 107 sensorType = SensorType::Light; 108 } else if (strcmp(dataType, "proximity") == 0) { 109 sensorType = SensorType::Proximity; 110 } else if (strcmp(dataType, "motion_detect") == 0) { 111 sensorType = SensorType::InstantMotion; 112 } else if (strcmp(dataType, "stationary_detect") == 0) { 113 sensorType = SensorType::StationaryDetect; 114 #ifdef CHREX_SENSOR_SUPPORT 115 } else if (strcmp(dataType, kVendorDataTypes[0]) == 0) { 116 sensorType = SensorType::VendorType0; 117 #endif // CHREX_SENSOR_SUPPORT 118 } else { 119 sensorType = SensorType::Unknown; 120 } 121 return sensorType; 122 } 123 124 void seeSensorDataEventFree(uint16_t eventType, void *eventData) { 125 memoryFree(eventData); 126 127 // Remove all requests if it's a one-shot sensor and only after data has been 128 // delivered to all clients. 129 SensorType sensorType = getSensorTypeForSampleEventType(eventType); 130 if (sensorTypeIsOneShot(sensorType)) { 131 EventLoopManagerSingleton::get()->getSensorRequestManager() 132 .removeAllRequests(sensorType); 133 } 134 } 135 136 /** 137 * Posts a CHRE_EVENT_SENSOR_SAMPLING_CHANGE event to the specified Nanoapp. 138 * 139 * @param instaceId The instance ID of the nanoapp with an open request. 140 * @param sensorHandle The handle of the sensor. 141 * @param status A reference of the sampling status to be posted. 142 */ 143 void postSamplingStatusEvent(uint32_t instanceId, uint32_t sensorHandle, 144 const struct chreSensorSamplingStatus& status) { 145 auto *event = memoryAlloc<struct chreSensorSamplingStatusEvent>(); 146 if (event == nullptr) { 147 LOG_OOM(); 148 } else { 149 event->sensorHandle = sensorHandle; 150 event->status = status; 151 152 EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree( 153 CHRE_EVENT_SENSOR_SAMPLING_CHANGE, event, freeEventDataCallback, 154 kSystemInstanceId, instanceId); 155 } 156 } 157 158 /** 159 * Updates the sampling status. 160 */ 161 void updateSamplingStatus( 162 const SeeHelperCallbackInterface::SamplingStatusData& update) { 163 Sensor *sensor = EventLoopManagerSingleton::get()->getSensorRequestManager() 164 .getSensor(update.sensorType); 165 struct chreSensorSamplingStatus prevStatus; 166 167 if (sensor != nullptr && !sensorTypeIsOneShot(update.sensorType) 168 && sensor->getSamplingStatus(&prevStatus)) { 169 struct chreSensorSamplingStatus newStatus = prevStatus; 170 171 if (update.enabledValid) { 172 newStatus.enabled = update.status.enabled; 173 } 174 if (update.intervalValid) { 175 newStatus.interval = update.status.interval; 176 } 177 if (update.latencyValid) { 178 newStatus.latency = update.status.latency; 179 } 180 181 if (newStatus.enabled != prevStatus.enabled 182 || newStatus.interval != prevStatus.interval 183 || newStatus.latency != prevStatus.latency) { 184 sensor->setSamplingStatus(newStatus); 185 186 // Only post to Nanoapps with an open request. 187 uint32_t sensorHandle = getSensorHandleFromSensorType(update.sensorType); 188 const DynamicVector<SensorRequest>& requests = 189 EventLoopManagerSingleton::get()->getSensorRequestManager() 190 .getRequests(update.sensorType); 191 for (const auto& req : requests) { 192 if (req.getNanoapp() != nullptr) { 193 postSamplingStatusEvent(req.getNanoapp()->getInstanceId(), 194 sensorHandle, newStatus); 195 } 196 } 197 } 198 } 199 } 200 201 void SeeHelperCallback::onSamplingStatusUpdate( 202 UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>&& status) { 203 auto callback = [](uint16_t /* type */, void *data) { 204 auto cbData = UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>( 205 static_cast<SeeHelperCallbackInterface::SamplingStatusData *>(data)); 206 updateSamplingStatus(*cbData); 207 }; 208 209 // Schedule a deferred callback to handle sensor status change in the main 210 // thread. 211 EventLoopManagerSingleton::get()->deferCallback( 212 SystemCallbackType::SensorStatusUpdate, status.release(), callback); 213 } 214 215 void SeeHelperCallback::onSensorDataEvent( 216 SensorType sensorType, UniquePtr<uint8_t>&& eventData) { 217 // Schedule a deferred callback to update on-change sensor's last event in 218 // the main thread. 219 if (sensorTypeIsOnChange(sensorType)) { 220 updateLastEvent(sensorType, eventData.get()); 221 } 222 223 uint16_t eventType = getSampleEventTypeForSensorType(sensorType); 224 EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree( 225 eventType, eventData.get(), seeSensorDataEventFree); 226 eventData.release(); 227 } 228 229 void SeeHelperCallback::onHostWakeSuspendEvent(bool awake) { 230 if (EventLoopManagerSingleton::isInitialized()) { 231 EventLoopManagerSingleton::get()->getEventLoop() 232 .getPowerControlManager().onHostWakeSuspendEvent(awake); 233 } 234 } 235 236 /** 237 * Allocates memory and specifies the memory size for an on-change sensor to 238 * store its last data event. 239 * 240 * @param sensorType The sensorType of this sensor. 241 * @param eventSize A non-null pointer to indicate the memory size allocated. 242 * @return Pointer to the memory allocated. 243 */ 244 ChreSensorData *allocateLastEvent(SensorType sensorType, size_t *eventSize) { 245 CHRE_ASSERT(eventSize); 246 247 *eventSize = 0; 248 ChreSensorData *event = nullptr; 249 if (sensorTypeIsOnChange(sensorType)) { 250 SensorSampleType sampleType = getSensorSampleTypeFromSensorType(sensorType); 251 switch (sampleType) { 252 case SensorSampleType::ThreeAxis: 253 *eventSize = sizeof(chreSensorThreeAxisData); 254 break; 255 case SensorSampleType::Float: 256 *eventSize = sizeof(chreSensorFloatData); 257 break; 258 case SensorSampleType::Byte: 259 *eventSize = sizeof(chreSensorByteData); 260 break; 261 case SensorSampleType::Occurrence: 262 *eventSize = sizeof(chreSensorOccurrenceData); 263 break; 264 default: 265 CHRE_ASSERT_LOG(false, "Unhandled sample type"); 266 break; 267 } 268 269 event = static_cast<ChreSensorData *>(memoryAlloc(*eventSize)); 270 if (event == nullptr) { 271 *eventSize = 0; 272 FATAL_ERROR("Failed to allocate last event memory for SensorType %" PRIu8, 273 static_cast<uint8_t>(sensorType)); 274 } 275 } 276 return event; 277 } 278 279 /** 280 * Constructs and initializes a sensor, and adds it to the sensor list. 281 * 282 * @param suid The SUID of the sensor as provided by SEE. 283 * @param sensorType The sensor type of the sensor. 284 * @param calibrated Whether the sensor is runtime-calibrated or not. 285 * @param attr A reference to SeeAttrbutes. 286 * @param sensor The sensor list. 287 */ 288 void addSensor(SensorType sensorType, const sns_std_suid& suid, 289 const SeeAttributes& attr, DynamicVector<Sensor> *sensors) { 290 // Concatenate vendor and name with a space in between. 291 char sensorName[kSensorNameMaxLen]; 292 strlcpy(sensorName, attr.vendor, sizeof(sensorName)); 293 strlcat(sensorName, " ", sizeof(sensorName)); 294 strlcat(sensorName, attr.name, sizeof(sensorName)); 295 296 // Override one-shot sensor's minInterval to default 297 uint64_t minInterval = sensorTypeIsOneShot(sensorType) ? 298 CHRE_SENSOR_INTERVAL_DEFAULT : static_cast<uint64_t>( 299 ceilf(Seconds(1).toRawNanoseconds() / attr.maxSampleRate)); 300 301 // Allocates memory for on-change sensor's last event. 302 size_t lastEventSize; 303 ChreSensorData *lastEvent = allocateLastEvent(sensorType, &lastEventSize); 304 305 // Constructs and initializes PlatformSensorBase. 306 Sensor sensor; 307 sensor.initBase(sensorType, minInterval, sensorName, lastEvent, 308 lastEventSize, attr.passiveRequest); 309 310 if (!sensors->push_back(std::move(sensor))) { 311 FATAL_ERROR("Failed to allocate new sensor: out of memory"); 312 } 313 314 bool prevRegistered; 315 bool registered = getSeeHelper()->registerSensor( 316 sensorType, suid, &prevRegistered); 317 if (!registered && prevRegistered) { 318 LOGW("SUID has been previously registered"); 319 } else if (!registered) { 320 FATAL_ERROR("Failed to register SUID/SensorType mapping."); 321 } 322 } 323 324 /** 325 * Compare SEE reported stream type attribute to the expected one. Some SEE 326 * sensors may support more than one stream type. 327 */ 328 bool isStreamTypeCorrect(SensorType sensorType, uint8_t streamType) { 329 bool success = true; 330 if ((sensorTypeIsContinuous(sensorType) 331 && streamType != SNS_STD_SENSOR_STREAM_TYPE_STREAMING) 332 || (sensorTypeIsOnChange(sensorType) 333 && streamType != SNS_STD_SENSOR_STREAM_TYPE_ON_CHANGE) 334 || (sensorTypeIsOneShot(sensorType) 335 && streamType != SNS_STD_SENSOR_STREAM_TYPE_SINGLE_OUTPUT)) { 336 success = false; 337 LOGW("Inconsistent sensor type %" PRIu8 " and stream type %" PRIu8, 338 static_cast<uint8_t>(sensorType), streamType); 339 } 340 return success; 341 } 342 343 /** 344 * Obtains the list of SUIDs and their attributes that support the specified 345 * data type. 346 */ 347 bool getSuidAndAttrs(const char *dataType, DynamicVector<SuidAttr> *suidAttrs, 348 uint8_t minNumSuids) { 349 DynamicVector<sns_std_suid> suids; 350 bool success = getSeeHelper()->findSuidSync(dataType, &suids, minNumSuids); 351 if (!success) { 352 LOGE("Failed to find sensor '%s'", dataType); 353 } else { 354 LOGD("Num of SUIDs found for '%s': %zu", dataType, suids.size()); 355 356 for (const auto& suid : suids) { 357 SeeAttributes attr; 358 if (!getSeeHelper()->getAttributesSync(suid, &attr)) { 359 success = false; 360 LOGE("Failed to get attributes of SUID 0x%" PRIx64 " %" PRIx64, 361 suid.suid_high, suid.suid_low); 362 } else { 363 LOGI("%s %s, hw id %" PRId64 ", max ODR %f Hz, stream type %" PRIu8 364 " passive %d", 365 attr.vendor, attr.name, attr.hwId, attr.maxSampleRate, 366 attr.streamType, attr.passiveRequest); 367 SuidAttr sensor = { 368 .suid = suid, 369 .attr = attr, 370 }; 371 if (!suidAttrs->push_back(sensor)) { 372 success = false; 373 LOG_OOM(); 374 } 375 } 376 } 377 } 378 return success; 379 } 380 381 // Check whether two sensors with the specified attrtibutes belong to the same 382 // sensor hardware module. 383 bool sensorHwMatch(const SeeAttributes& attr0, const SeeAttributes& attr1) { 384 // When HW ID is absent, it's default to 0 and won't be a factor. 385 return ((strncmp(attr0.vendor, attr1.vendor, kSeeAttrStrValLen) == 0) 386 && (strncmp(attr0.name, attr1.name, kSeeAttrStrValLen) == 0) 387 && (attr0.hwId == attr1.hwId)); 388 } 389 390 } // anonymous namespace 391 392 PlatformSensor::~PlatformSensor() { 393 if (mLastEvent != nullptr) { 394 LOGD("Releasing lastEvent: sensor %s, size %zu", 395 getSensorTypeName(getSensorType()), mLastEventSize); 396 memoryFree(mLastEvent); 397 } 398 } 399 400 void PlatformSensor::init() { 401 SeeHelperSingleton::init(); 402 403 static SeeHelperCallback seeHelperCallback; 404 if (!getSeeHelper()->init(&seeHelperCallback)) { 405 FATAL_ERROR("Failed to initialize SEE helper"); 406 } 407 } 408 409 void PlatformSensor::deinit() { 410 SeeHelperSingleton::deinit(); 411 } 412 413 bool PlatformSensor::getSensors(DynamicVector<Sensor> *sensors) { 414 CHRE_ASSERT(sensors); 415 416 DynamicVector<SuidAttr> tempSensors; 417 if (!getSuidAndAttrs("sensor_temperature", &tempSensors, 418 CHRE_SEE_NUM_TEMP_SENSORS)) { 419 FATAL_ERROR("Failed to get temperature sensor UID and attributes"); 420 } 421 422 #ifndef CHREX_SENSOR_SUPPORT 423 const char *kVendorDataTypes[] = {}; 424 #endif // CHREX_SENSOR_SUPPORT 425 constexpr size_t kNumSeeTypes = ARRAY_SIZE(kSeeDataTypes); 426 constexpr size_t kNumVendorTypes = ARRAY_SIZE(kVendorDataTypes); 427 for (size_t i = 0; i < kNumSeeTypes + kNumVendorTypes; i++) { 428 const char *dataType = (i < kNumSeeTypes) 429 ? kSeeDataTypes[i] : kVendorDataTypes[i - kNumSeeTypes]; 430 431 SensorType sensorType = getSensorTypeFromDataType( 432 dataType, false /* calibrated */); 433 if (sensorType == SensorType::Unknown) { 434 LOGE("Unknown sensor type found for '%s'", dataType); 435 continue; 436 } 437 438 DynamicVector<SuidAttr> primarySensors; 439 if (!getSuidAndAttrs(dataType, &primarySensors, 1 /* minNumSuids */)) { 440 FATAL_ERROR("Failed to get primary sensor UID and attributes"); 441 } else { 442 for (const auto& primarySensor : primarySensors) { 443 sns_std_suid suid = primarySensor.suid; 444 SeeAttributes attr = primarySensor.attr; 445 446 // Some sensors support both continuous and on-change streams. 447 // If there are more than one SUIDs that support the data type, 448 // choose the first one that has the expected stream type. 449 if (isStreamTypeCorrect(sensorType, attr.streamType)) { 450 addSensor(sensorType, suid, attr, sensors); 451 452 // Check if this sensor has a runtime-calibrated version. 453 SensorType calibratedType = getSensorTypeFromDataType( 454 dataType, true /* calibrated */); 455 if (calibratedType != sensorType) { 456 addSensor(calibratedType, suid, attr, sensors); 457 } 458 459 // Check if this sensor has a secondary temperature sensor. 460 SensorType temperatureType = getTempSensorType(sensorType); 461 if (temperatureType != SensorType::Unknown) { 462 bool tempFound = false; 463 for (const auto& tempSensor : tempSensors) { 464 sns_std_suid tempSuid = tempSensor.suid; 465 SeeAttributes tempAttr = tempSensor.attr; 466 467 if (sensorHwMatch(attr, tempAttr)) { 468 LOGD("Found matching temperature sensor type"); 469 tempFound = true; 470 addSensor(temperatureType, tempSuid, tempAttr, sensors); 471 break; 472 } 473 } 474 if (!tempFound) { 475 LOGW("Temperature sensor type %" PRIu8 " not found!", 476 static_cast<uint8_t>(temperatureType)); 477 } 478 } 479 break; 480 } 481 } 482 } 483 } 484 return true; 485 } 486 487 bool PlatformSensor::applyRequest(const SensorRequest& request) { 488 SeeSensorRequest req = { 489 .sensorType = getSensorType(), 490 .enable = (request.getMode() != SensorMode::Off), 491 .passive = sensorModeIsPassive(request.getMode()), 492 .samplingRateHz = static_cast<float>( 493 kOneSecondInNanoseconds / request.getInterval().toRawNanoseconds()), 494 // Override batch period to 0 for non-continuous sensors to ensure one 495 // sample per batch. 496 .batchPeriodUs = !sensorTypeIsContinuous(mSensorType) ? 0 497 : static_cast<uint32_t>(request.getLatency().toRawNanoseconds() 498 / kOneMicrosecondInNanoseconds), 499 }; 500 501 if (req.enable && req.passive && !mPassiveSupported) { 502 LOGD("Promoting sensor %" PRIu8 " passive request to active", 503 static_cast<uint8_t>(getSensorType())); 504 } 505 506 bool success = SeeHelperSingleton::get()->makeRequest(req); 507 508 // TODO: remove setSamplingStatus when .latency is available in status update 509 // from SEE. 510 if (success) { 511 struct chreSensorSamplingStatus status; 512 if (getSamplingStatus(&status)) { 513 514 // If passive request is not supported by this SEE sensor, it won't be 515 // dynamically enabled/disabled and its status stays the same as set here. 516 if (!mPassiveSupported) { 517 status.enabled = req.enable; 518 } 519 status.latency = req.batchPeriodUs * kOneMicrosecondInNanoseconds; 520 setSamplingStatus(status); 521 } 522 } 523 return success; 524 } 525 526 SensorType PlatformSensor::getSensorType() const { 527 return mSensorType; 528 } 529 530 uint64_t PlatformSensor::getMinInterval() const { 531 return mMinInterval; 532 } 533 534 const char *PlatformSensor::getSensorName() const { 535 return mSensorName; 536 } 537 538 PlatformSensor::PlatformSensor(PlatformSensor&& other) { 539 // Our move assignment operator doesn't assume that "this" is initialized, so 540 // we can just use that here. 541 *this = std::move(other); 542 } 543 544 PlatformSensor& PlatformSensor::operator=(PlatformSensor&& other) { 545 // Note: if this implementation is ever changed to depend on "this" containing 546 // initialized values, the move constructor implemenation must be updated. 547 mSensorType = other.mSensorType; 548 mMinInterval = other.mMinInterval; 549 memcpy(mSensorName, other.mSensorName, kSensorNameMaxLen); 550 551 mLastEvent = other.mLastEvent; 552 other.mLastEvent = nullptr; 553 554 mLastEventSize = other.mLastEventSize; 555 other.mLastEventSize = 0; 556 557 mLastEventValid = other.mLastEventValid; 558 mSamplingStatus = other.mSamplingStatus; 559 mPassiveSupported = other.mPassiveSupported; 560 561 return *this; 562 } 563 564 ChreSensorData *PlatformSensor::getLastEvent() const { 565 return mLastEventValid ? mLastEvent : nullptr; 566 } 567 568 bool PlatformSensor::getSamplingStatus( 569 struct chreSensorSamplingStatus *status) const { 570 CHRE_ASSERT(status); 571 572 memcpy(status, &mSamplingStatus, sizeof(*status)); 573 return true; 574 } 575 576 void PlatformSensorBase::initBase( 577 SensorType sensorType,uint64_t minInterval, const char *sensorName, 578 ChreSensorData *lastEvent, size_t lastEventSize, bool passiveSupported) { 579 mSensorType = sensorType; 580 mMinInterval = minInterval; 581 memcpy(mSensorName, sensorName, kSensorNameMaxLen); 582 mLastEvent = lastEvent; 583 mLastEventSize = lastEventSize; 584 585 mSamplingStatus.enabled = false; 586 mSamplingStatus.interval = CHRE_SENSOR_INTERVAL_DEFAULT; 587 mSamplingStatus.latency = CHRE_SENSOR_LATENCY_DEFAULT; 588 589 mPassiveSupported = passiveSupported; 590 } 591 592 void PlatformSensorBase::setLastEvent(const ChreSensorData *event) { 593 memcpy(mLastEvent, event, mLastEventSize); 594 mLastEventValid = true; 595 } 596 597 void PlatformSensorBase::setSamplingStatus( 598 const struct chreSensorSamplingStatus& status) { 599 mSamplingStatus = status; 600 } 601 602 } // namespace chre 603