/* * Copyright (C) 2022 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/pal/sensor.h" #include "chre/platform/linux/task_util/task_manager.h" #include "chre/platform/memory.h" #include "chre/util/macros.h" #include "chre/util/memory.h" #include "chre/util/unique_ptr.h" #include #include #include /** * A simulated implementation of the Sensor PAL for the linux platform. */ namespace { using ::chre::TaskManagerSingleton; const struct chrePalSystemApi *gSystemApi = nullptr; const struct chrePalSensorCallbacks *gCallbacks = nullptr; struct chreSensorInfo gSensors[] = { // Sensor 0 - Accelerometer. { .sensorName = "Test Accelerometer", .sensorType = CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER, .isOnChange = 0, .isOneShot = 0, .reportsBiasEvents = 0, .supportsPassiveMode = 0, .unusedFlags = 0, .minInterval = 0, .sensorIndex = CHRE_SENSOR_INDEX_DEFAULT, }, }; //! Task to deliver asynchronous sensor data after a CHRE request. std::optional gSensor0TaskId; bool gIsSensor0Enabled = false; void stopSensor0Task() { if (gSensor0TaskId.has_value()) { TaskManagerSingleton::get()->cancelTask(gSensor0TaskId.value()); gSensor0TaskId.reset(); } } void chrePalSensorApiClose() { stopSensor0Task(); } bool chrePalSensorApiOpen(const struct chrePalSystemApi *systemApi, const struct chrePalSensorCallbacks *callbacks) { chrePalSensorApiClose(); bool success = false; if (systemApi != nullptr && callbacks != nullptr) { gSystemApi = systemApi; gCallbacks = callbacks; success = true; } return success; } bool chrePalSensorApiGetSensors(const struct chreSensorInfo **sensors, uint32_t *arraySize) { if (sensors != nullptr) { *sensors = gSensors; } if (arraySize != nullptr) { *arraySize = ARRAY_SIZE(gSensors); } return true; } void sendSensor0StatusUpdate(uint64_t intervalNs, bool enabled) { auto status = chre::MakeUniqueZeroFill(); status->interval = intervalNs; status->latency = 0; status->enabled = enabled; gCallbacks->samplingStatusUpdateCallback(0, status.release()); } void sendSensor0Events() { auto data = chre::MakeUniqueZeroFill(); data->header.baseTimestamp = gSystemApi->getCurrentTime(); data->header.sensorHandle = 0; data->header.readingCount = 1; data->header.accuracy = CHRE_SENSOR_ACCURACY_UNRELIABLE; data->header.reserved = 0; gCallbacks->dataEventCallback(0, data.release()); } bool chrePalSensorApiConfigureSensor(uint32_t sensorInfoIndex, enum chreSensorConfigureMode mode, uint64_t intervalNs, uint64_t latencyNs) { UNUSED_VAR(latencyNs); if (sensorInfoIndex > ARRAY_SIZE(gSensors) - 1) { return false; } if (sensorInfoIndex != 0) { // Only sensor 0 is supported for now. return false; } if (mode == CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS) { stopSensor0Task(); gIsSensor0Enabled = true; sendSensor0StatusUpdate(intervalNs, true /*enabled*/); gSensor0TaskId = TaskManagerSingleton::get()->addTask( sendSensor0Events, std::chrono::nanoseconds(intervalNs)); return gSensor0TaskId.has_value(); } if (mode == CHRE_SENSOR_CONFIGURE_MODE_DONE) { stopSensor0Task(); gIsSensor0Enabled = false; sendSensor0StatusUpdate(intervalNs, false /*enabled*/); return true; } return false; } bool chrePalSensorApiFlush(uint32_t sensorInfoIndex, uint32_t *flushRequestId) { UNUSED_VAR(sensorInfoIndex); UNUSED_VAR(flushRequestId); return false; } bool chrePalSensorApiConfigureBiasEvents(uint32_t sensorInfoIndex, bool enable, uint64_t latencyNs) { UNUSED_VAR(sensorInfoIndex); UNUSED_VAR(enable); UNUSED_VAR(latencyNs); return false; } bool chrePalSensorApiGetThreeAxisBias(uint32_t sensorInfoIndex, struct chreSensorThreeAxisData *bias) { UNUSED_VAR(sensorInfoIndex); UNUSED_VAR(bias); return false; } void chrePalSensorApiReleaseSensorDataEvent(void *data) { chre::memoryFree(data); } void chrePalSensorApiReleaseSamplingStatusEvent( struct chreSensorSamplingStatus *status) { chre::memoryFree(status); } void chrePalSensorApiReleaseBiasEvent(void *bias) { chre::memoryFree(bias); } } // namespace bool chrePalSensorIsSensor0Enabled() { return gIsSensor0Enabled; } const chrePalSensorApi *chrePalSensorGetApi(uint32_t requestedApiVersion) { static const struct chrePalSensorApi kApi = { .moduleVersion = CHRE_PAL_SENSOR_API_CURRENT_VERSION, .open = chrePalSensorApiOpen, .close = chrePalSensorApiClose, .getSensors = chrePalSensorApiGetSensors, .configureSensor = chrePalSensorApiConfigureSensor, .flush = chrePalSensorApiFlush, .configureBiasEvents = chrePalSensorApiConfigureBiasEvents, .getThreeAxisBias = chrePalSensorApiGetThreeAxisBias, .releaseSensorDataEvent = chrePalSensorApiReleaseSensorDataEvent, .releaseSamplingStatusEvent = chrePalSensorApiReleaseSamplingStatusEvent, .releaseBiasEvent = chrePalSensorApiReleaseBiasEvent, }; if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(kApi.moduleVersion, requestedApiVersion)) { return nullptr; } else { return &kApi; } }