blob: d4df5d35f20184402a7a9832100380fb291f12be [file] [log] [blame]
/*
* 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 <chrono>
#include <cinttypes>
#include <cstdint>
/**
* 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,
.minInterval = 0,
.sensorIndex = CHRE_SENSOR_INDEX_DEFAULT,
},
};
//! Task to deliver asynchronous sensor data after a CHRE request.
std::optional<uint32_t> gSensor0TaskId;
bool gIsSensor0Enabled = false;
void stopSensor0Task() {
if (gSensor0TaskId.has_value()) {
TaskManagerSingleton::get()->cancelTask(gSensor0TaskId.value());
}
}
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<struct chreSensorSamplingStatus>();
status->interval = intervalNs;
status->latency = 0;
status->enabled = enabled;
gCallbacks->samplingStatusUpdateCallback(0, status.release());
}
void sendSensor0Events() {
auto data = chre::MakeUniqueZeroFill<struct chreSensorThreeAxisData>();
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::duration_cast<std::chrono::milliseconds>(
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;
}
}