blob: 9e7746245ba71b215b961f438055c26fcd1baf9e [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "chre/platform/platform_sensor_manager.h"
#include "chre/core/event_loop_manager.h"
#include "chre/util/nested_data_ptr.h"
namespace chre {
namespace {
void addSensor(refcount::reffed_ptr<usf::UsfSensor> &usfSensor,
uint8_t sensorType, DynamicVector<Sensor> *chreSensors) {
if (!chreSensors->emplace_back()) {
FATAL_ERROR("Failed to allocate new sensor");
}
// The sensor base class must be initialized before the main Sensor init()
// can be invoked as init() is allowed to invoke base class methods.
chreSensors->back().initBase(usfSensor, sensorType);
chreSensors->back().init();
const Sensor &newSensor = chreSensors->back();
LOGI("%s, type %" PRIu8 ", minInterval %" PRIu64 " handle %" PRId32,
newSensor.getSensorName(), newSensor.getSensorType(),
newSensor.getMinInterval(), newSensor.getServerHandle());
}
ReportingMode getReportingMode(Sensor &sensor) {
if (sensor.isOneShot()) {
return ReportingMode::OneShot;
} else if (sensor.isOnChange()) {
return ReportingMode::OnChange;
} else {
return ReportingMode::Continuous;
}
}
void handleMissingSensor() {
// Try rebooting if a sensor is missing, which might help recover from a
// transient failure/race condition at startup. But to avoid endless crashes,
// only do this within 45 seconds of boot time - we rely on knowledge that
// getMonotonicTime() only resets when the device reboots and not from an SSR.
#ifndef CHRE_LOG_ONLY_NO_SENSOR
if (SystemTime::getMonotonicTime() < (kDefaultUsfWaitTimeout + Seconds(15))) {
FATAL_ERROR("Missing required sensor(s)");
} else
#endif
{
LOGE("Missing required sensor(s)");
}
}
} // namespace
PlatformSensorManager::~PlatformSensorManager() {}
void PlatformSensorManager::init() {
mHelper.init(this);
}
DynamicVector<Sensor> PlatformSensorManager::getSensors() {
DynamicVector<Sensor> sensors;
usf::UsfVector<refcount::reffed_ptr<usf::UsfSensor>> sensorList;
if (mHelper.getSensorList(&sensorList)) {
for (size_t i = 0; i < sensorList.size(); i++) {
refcount::reffed_ptr<usf::UsfSensor> &sensor = sensorList[i];
addSensorsWithInfo(sensor, &sensors);
}
}
// TODO: Determine how many sensors are expected to be available through USF.
if (sensors.empty()) {
handleMissingSensor();
}
return sensors;
}
bool PlatformSensorManager::configureSensor(Sensor &sensor,
const SensorRequest &request) {
bool success = false;
if (request.getMode() == SensorMode::Off && !sensor.isSamplingIdValid()) {
// If no existing sampling ID exists and the sensor should be turned off,
// return true. This can happen when the core platform tries to remove a
// request for a one-shot sensor after it fires which automatically happens
// inside USF.
success = true;
} else if (request.getMode() == SensorMode::Off) {
usf::UsfStopSamplingReq usfReq;
usfReq.SetReqType(usf::UsfMsgReqType_STOP_SAMPLING);
usfReq.SetServerHandle(sensor.getServerHandle());
usfReq.SetSamplingId(sensor.getSamplingId());
if (mHelper.stopSampling(&usfReq)) {
sensor.setSamplingIdInvalid();
success = true;
}
} else if (sensor.isSamplingIdValid()) {
// TODO: See if a reconfigure request can be the same as reissuing a start
// request.
usf::UsfReconfigSamplingReq usfReq;
usfReq.SetReqType(usf::UsfMsgReqType_RECONFIG_SAMPLING);
usfReq.SetServerHandle(sensor.getServerHandle());
usfReq.SetSamplingId(sensor.getSamplingId());
usfReq.SetPeriodNs(request.getInterval().toRawNanoseconds());
usfReq.SetMaxLatencyNs(
sensor.isContinuous() ? request.getLatency().toRawNanoseconds() : 0);
success = mHelper.reconfigureSampling(&usfReq);
} else {
usf::UsfStartSamplingReq usfReq;
usfReq.SetReqType(usf::UsfMsgReqType_START_SAMPLING);
usfReq.SetServerHandle(sensor.getServerHandle());
// TODO(147438885): Make setting the reporting mode of a sensor optional
usfReq.SetReportingMode(PlatformSensorTypeHelpersBase::getUsfReportingMode(
getReportingMode(sensor)));
usfReq.SetPeriodNs(request.getInterval().toRawNanoseconds());
usfReq.SetMaxLatencyNs(
sensor.isContinuous() ? request.getLatency().toRawNanoseconds() : 0);
usfReq.SetPassive(sensorModeIsPassive(request.getMode()));
usf::UsfSensorTransformLevel transformLevel =
sensor.isCalibrated() ? usf::kUsfSensorTransformLevelAll
: usf::kUsfSensorTransformEnvCompensation;
usfReq.SetTransformLevel(transformLevel);
uint32_t samplingId;
if (mHelper.startSampling(&usfReq, &samplingId)) {
sensor.setSamplingId(samplingId);
success = true;
}
}
return success;
}
bool PlatformSensorManager::configureBiasEvents(const Sensor &sensor,
bool enable,
uint64_t /* latencyNs */) {
bool success = true;
if (enable) {
success = mHelper.registerForBiasUpdates(sensor.getUsfSensor());
} else {
// Unconditional success for unregistering
mHelper.unregisterForBiasUpdates(sensor.getUsfSensor());
}
return success;
}
bool PlatformSensorManager::getThreeAxisBias(
const Sensor &sensor, struct chreSensorThreeAxisData *bias) const {
bool success = sensor.reportsBiasEvents();
if (success) {
if (!mHelper.getThreeAxisBias(sensor.getUsfSensor(), bias)) {
// Set to zero bias + unknown accuracy per CHRE API requirements.
memset(bias, 0, sizeof(chreSensorThreeAxisData));
bias->header.readingCount = 1;
bias->header.accuracy = CHRE_SENSOR_ACCURACY_UNKNOWN;
}
// Overwrite sensorHandle to match the request type.
getSensorRequestManager().getSensorHandle(sensor.getSensorType(),
&bias->header.sensorHandle);
}
return success;
}
bool PlatformSensorManager::flush(const Sensor &sensor,
uint32_t *flushRequestId) {
NestedDataPtr<uint32_t> cookie(sensor.getSensorType());
return mHelper.flushAsync(sensor.getServerHandle(), cookie.dataPtr,
flushRequestId);
}
void PlatformSensorManager::releaseSamplingStatusUpdate(
struct chreSensorSamplingStatus *status) {
memoryFree(status);
}
void PlatformSensorManager::releaseSensorDataEvent(void *data) {
memoryFree(data);
}
void PlatformSensorManager::releaseBiasEvent(void *biasData) {
memoryFree(biasData);
}
void PlatformSensorManagerBase::onSamplingStatusUpdate(
uint8_t sensorType, const usf::UsfSensorSamplingEvent *update) {
uint32_t sensorHandle;
if (getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle)) {
// Memory will be freed via releaseSamplingStatusUpdate once core framework
// performs its updates.
auto statusUpdate = MakeUniqueZeroFill<struct chreSensorSamplingStatus>();
if (statusUpdate.isNull()) {
LOG_OOM();
} else {
statusUpdate->interval = update->GetPeriodNs();
statusUpdate->latency = update->GetMaxLatencyNs();
statusUpdate->enabled = update->GetActive();
getSensorRequestManager().handleSamplingStatusUpdate(
sensorHandle, statusUpdate.release());
}
}
}
bool PlatformSensorManagerBase::getSensorInfo(uint8_t sensorType,
SensorInfo *sensorInfo) {
bool success = false;
if (getSensorRequestManager().getSensorHandle(sensorType,
&sensorInfo->sensorHandle)) {
Sensor *sensor =
getSensorRequestManager().getSensor(sensorInfo->sensorHandle);
if (sensor != nullptr && sensor->isSamplingIdValid()) {
success = true;
sensorInfo->samplingId = sensor->getSamplingId();
} else {
sensorInfo->sensorHandle = 0;
}
}
return success;
}
void PlatformSensorManagerBase::onSensorDataEvent(
uint8_t sensorType, UniquePtr<uint8_t> &&eventData) {
uint32_t sensorHandle;
if (getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle)) {
Sensor *sensor = getSensorRequestManager().getSensor(sensorHandle);
// Invalidate the sampling ID for one shot sensors after they've fired since
// USF automatically removes the sampling ID from its list.
if (sensor->isOneShot()) {
sensor->setSamplingIdInvalid();
}
getSensorRequestManager().handleSensorDataEvent(sensorHandle,
eventData.release());
}
}
void PlatformSensorManagerBase::onFlushComplete(usf::UsfErr err,
uint32_t requestId,
void *cookie) {
NestedDataPtr<uint32_t> nestedSensorType;
nestedSensorType.dataPtr = cookie;
uint32_t sensorHandle;
if (getSensorRequestManager().getSensorHandle(nestedSensorType.data,
&sensorHandle)) {
getSensorRequestManager().handleFlushCompleteEvent(
sensorHandle, requestId, UsfHelper::usfErrorToChreError(err));
}
}
void PlatformSensorManagerBase::onBiasUpdate(
uint8_t sensorType, UniquePtr<struct chreSensorThreeAxisData> &&eventData) {
uint32_t sensorHandle;
if (getSensorRequestManager().getSensorHandle(sensorType, &sensorHandle)) {
eventData->header.sensorHandle = sensorHandle;
getSensorRequestManager().handleBiasEvent(sensorHandle,
eventData.release());
}
}
void PlatformSensorManagerBase::onHostWakeSuspendEvent(bool awake) {
EventLoopManagerSingleton::get()
->getEventLoop()
.getPowerControlManager()
.onHostWakeSuspendEvent(awake);
}
void PlatformSensorManagerBase::addSensorsWithInfo(
refcount::reffed_ptr<usf::UsfSensor> &usfSensor,
DynamicVector<Sensor> *chreSensors) {
uint8_t sensorType;
if (PlatformSensorTypeHelpersBase::convertUsfToChreSensorType(
usfSensor->GetType(), &sensorType)) {
// Only register for a USF sensor once. If it maps to multiple sensors,
// code down the line will handle sending multiple updates.
if (!mHelper.registerForStatusUpdates(usfSensor)) {
LOGE("Failed to register for status updates for %s",
usfSensor->GetName());
}
addSensor(usfSensor, sensorType, chreSensors);
// USF shares the same sensor type for calibrated and uncalibrated sensors
// so populate a calibrated / uncalibrated sensor for known calibrated
// sensor types
uint8_t uncalibratedType =
SensorTypeHelpers::toUncalibratedSensorType(sensorType);
if (uncalibratedType != sensorType) {
addSensor(usfSensor, uncalibratedType, chreSensors);
}
// USF shares a sensor type for both gyro and accel temp.
if (sensorType == CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE) {
addSensor(usfSensor, CHRE_SENSOR_TYPE_ACCELEROMETER_TEMPERATURE,
chreSensors);
}
}
}
} // namespace chre