1 /*
2 * Copyright (C) 2022 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/pal/sensor.h"
18
19 #include "chre/platform/memory.h"
20 #include "chre/util/macros.h"
21 #include "chre/util/memory.h"
22 #include "chre/util/unique_ptr.h"
23
24 #include <chrono>
25 #include <cinttypes>
26 #include <cstdint>
27 #include <future>
28 #include <thread>
29
30 /**
31 * A simulated implementation of the Sensor PAL for the linux platform.
32 */
33 namespace {
34 const struct chrePalSystemApi *gSystemApi = nullptr;
35 const struct chrePalSensorCallbacks *gCallbacks = nullptr;
36
37 struct chreSensorInfo gSensors[] = {
38 // Sensor 0 - Accelerometer.
39 {
40 .sensorName = "Test Accelerometer",
41 .sensorType = CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER,
42 .isOnChange = 0,
43 .isOneShot = 0,
44 .reportsBiasEvents = 0,
45 .supportsPassiveMode = 0,
46 .minInterval = 0,
47 .sensorIndex = CHRE_SENSOR_INDEX_DEFAULT,
48 },
49 };
50
51 //! Thread to deliver asynchronous sensor data after a CHRE request.
52 std::thread gSensor0Thread;
53 std::promise<void> gStopSensor0Thread;
54 bool gIsSensor0Enabled = false;
55
stopSensor0Thread()56 void stopSensor0Thread() {
57 if (gSensor0Thread.joinable()) {
58 gStopSensor0Thread.set_value();
59 gSensor0Thread.join();
60 }
61 }
62
chrePalSensorApiClose()63 void chrePalSensorApiClose() {
64 stopSensor0Thread();
65 }
66
chrePalSensorApiOpen(const struct chrePalSystemApi * systemApi,const struct chrePalSensorCallbacks * callbacks)67 bool chrePalSensorApiOpen(const struct chrePalSystemApi *systemApi,
68 const struct chrePalSensorCallbacks *callbacks) {
69 chrePalSensorApiClose();
70
71 if (systemApi != nullptr && callbacks != nullptr) {
72 gSystemApi = systemApi;
73 gCallbacks = callbacks;
74 return true;
75 }
76
77 return false;
78 }
79
chrePalSensorApiGetSensors(const struct chreSensorInfo ** sensors,uint32_t * arraySize)80 bool chrePalSensorApiGetSensors(const struct chreSensorInfo **sensors,
81 uint32_t *arraySize) {
82 if (sensors != nullptr) {
83 *sensors = gSensors;
84 }
85 if (arraySize != nullptr) {
86 *arraySize = ARRAY_SIZE(gSensors);
87 }
88 return true;
89 }
90
sendSensor0StatusUpdate(uint64_t intervalNs,bool enabled)91 void sendSensor0StatusUpdate(uint64_t intervalNs, bool enabled) {
92 auto status = chre::MakeUniqueZeroFill<struct chreSensorSamplingStatus>();
93 status->interval = intervalNs;
94 status->latency = 0;
95 status->enabled = enabled;
96 gCallbacks->samplingStatusUpdateCallback(0, status.release());
97 }
98
sendSensor0Events(uint64_t intervalNs)99 void sendSensor0Events(uint64_t intervalNs) {
100 std::future<void> signal = gStopSensor0Thread.get_future();
101 while (signal.wait_for(std::chrono::nanoseconds(intervalNs)) ==
102 std::future_status::timeout) {
103 auto data = chre::MakeUniqueZeroFill<struct chreSensorThreeAxisData>();
104
105 data->header.baseTimestamp = gSystemApi->getCurrentTime();
106 data->header.sensorHandle = 0;
107 data->header.readingCount = 1;
108 data->header.accuracy = CHRE_SENSOR_ACCURACY_UNRELIABLE;
109 data->header.reserved = 0;
110
111 gCallbacks->dataEventCallback(0, data.release());
112 }
113 }
114
chrePalSensorApiConfigureSensor(uint32_t sensorInfoIndex,enum chreSensorConfigureMode mode,uint64_t intervalNs,uint64_t latencyNs)115 bool chrePalSensorApiConfigureSensor(uint32_t sensorInfoIndex,
116 enum chreSensorConfigureMode mode,
117 uint64_t intervalNs, uint64_t latencyNs) {
118 UNUSED_VAR(latencyNs);
119 if (sensorInfoIndex > ARRAY_SIZE(gSensors) - 1) {
120 return false;
121 }
122
123 if (sensorInfoIndex != 0) {
124 // Only sensor 0 is supported for now.
125 return false;
126 }
127
128 if (mode == CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS) {
129 stopSensor0Thread();
130 gIsSensor0Enabled = true;
131 sendSensor0StatusUpdate(intervalNs, true /*enabled*/);
132 gStopSensor0Thread = std::promise<void>();
133 gSensor0Thread = std::thread(sendSensor0Events, intervalNs);
134 return true;
135 }
136
137 if (mode == CHRE_SENSOR_CONFIGURE_MODE_DONE) {
138 stopSensor0Thread();
139 gIsSensor0Enabled = false;
140 sendSensor0StatusUpdate(intervalNs, false /*enabled*/);
141 return true;
142 }
143
144 return false;
145 }
146
chrePalSensorApiFlush(uint32_t sensorInfoIndex,uint32_t * flushRequestId)147 bool chrePalSensorApiFlush(uint32_t sensorInfoIndex, uint32_t *flushRequestId) {
148 UNUSED_VAR(sensorInfoIndex);
149 UNUSED_VAR(flushRequestId);
150 return false;
151 }
152
chrePalSensorApiConfigureBiasEvents(uint32_t sensorInfoIndex,bool enable,uint64_t latencyNs)153 bool chrePalSensorApiConfigureBiasEvents(uint32_t sensorInfoIndex, bool enable,
154 uint64_t latencyNs) {
155 UNUSED_VAR(sensorInfoIndex);
156 UNUSED_VAR(enable);
157 UNUSED_VAR(latencyNs);
158 return false;
159 }
160
chrePalSensorApiGetThreeAxisBias(uint32_t sensorInfoIndex,struct chreSensorThreeAxisData * bias)161 bool chrePalSensorApiGetThreeAxisBias(uint32_t sensorInfoIndex,
162 struct chreSensorThreeAxisData *bias) {
163 UNUSED_VAR(sensorInfoIndex);
164 UNUSED_VAR(bias);
165 return false;
166 }
167
chrePalSensorApiReleaseSensorDataEvent(void * data)168 void chrePalSensorApiReleaseSensorDataEvent(void *data) {
169 chre::memoryFree(data);
170 }
171
chrePalSensorApiReleaseSamplingStatusEvent(struct chreSensorSamplingStatus * status)172 void chrePalSensorApiReleaseSamplingStatusEvent(
173 struct chreSensorSamplingStatus *status) {
174 chre::memoryFree(status);
175 }
176
chrePalSensorApiReleaseBiasEvent(void * bias)177 void chrePalSensorApiReleaseBiasEvent(void *bias) {
178 chre::memoryFree(bias);
179 }
180
181 } // namespace
182
chrePalSensorIsSensor0Enabled()183 bool chrePalSensorIsSensor0Enabled() {
184 return gIsSensor0Enabled;
185 }
186
chrePalSensorGetApi(uint32_t requestedApiVersion)187 const chrePalSensorApi *chrePalSensorGetApi(uint32_t requestedApiVersion) {
188 static const struct chrePalSensorApi kApi = {
189 .moduleVersion = CHRE_PAL_SENSOR_API_CURRENT_VERSION,
190 .open = chrePalSensorApiOpen,
191 .close = chrePalSensorApiClose,
192 .getSensors = chrePalSensorApiGetSensors,
193 .configureSensor = chrePalSensorApiConfigureSensor,
194 .flush = chrePalSensorApiFlush,
195 .configureBiasEvents = chrePalSensorApiConfigureBiasEvents,
196 .getThreeAxisBias = chrePalSensorApiGetThreeAxisBias,
197 .releaseSensorDataEvent = chrePalSensorApiReleaseSensorDataEvent,
198 .releaseSamplingStatusEvent = chrePalSensorApiReleaseSamplingStatusEvent,
199 .releaseBiasEvent = chrePalSensorApiReleaseBiasEvent,
200
201 };
202
203 if (!CHRE_PAL_VERSIONS_ARE_COMPATIBLE(kApi.moduleVersion,
204 requestedApiVersion)) {
205 return nullptr;
206 } else {
207 return &kApi;
208 }
209 }