1 /*
2 * Copyright (C) 2016 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/core/sensor_request_manager.h"
18
19 #include "chre/core/event_loop_manager.h"
20 #include "chre/platform/fatal_error.h"
21 #include "chre_api/chre/version.h"
22 #include "chre/util/system/debug_dump.h"
23
24 namespace chre {
25 namespace {
26
isSensorRequestValid(const Sensor & sensor,const SensorRequest & sensorRequest)27 bool isSensorRequestValid(const Sensor& sensor,
28 const SensorRequest& sensorRequest) {
29 bool isRequestContinuous = sensorModeIsContinuous(
30 sensorRequest.getMode());
31 bool isRequestOneShot = sensorModeIsOneShot(sensorRequest.getMode());
32 uint64_t requestedInterval = sensorRequest.getInterval().toRawNanoseconds();
33 SensorType sensorType = sensor.getSensorType();
34
35 bool success = true;
36 if (requestedInterval < sensor.getMinInterval()) {
37 success = false;
38 LOGE("Requested interval %" PRIu64 " < sensor's minInterval %" PRIu64,
39 requestedInterval, sensor.getMinInterval());
40 } else if (isRequestContinuous) {
41 if (sensorTypeIsOneShot(sensorType)) {
42 success = false;
43 LOGE("Invalid continuous request for a one-shot sensor.");
44 }
45 } else if (isRequestOneShot) {
46 if (!sensorTypeIsOneShot(sensorType)) {
47 success = false;
48 LOGE("Invalid one-shot request for a continuous sensor.");
49 }
50 }
51 return success;
52 }
53
54 } // namespace
55
SensorRequestManager()56 SensorRequestManager::SensorRequestManager() {
57 mSensorRequests.resize(mSensorRequests.capacity());
58
59 DynamicVector<Sensor> sensors;
60 sensors.reserve(8); // Avoid some initial reallocation churn
61 if (!PlatformSensor::getSensors(&sensors)) {
62 LOGE("Failed to query the platform for sensors");
63 } else if (sensors.empty()) {
64 LOGW("Platform returned zero sensors");
65 } else {
66 for (size_t i = 0; i < sensors.size(); i++) {
67 SensorType sensorType = sensors[i].getSensorType();
68 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
69
70 if (sensorType == SensorType::Unknown) {
71 LOGE("Invalid sensor type");
72 } else if (sensors[i].getMinInterval() == 0) {
73 LOGE("Invalid sensor minInterval: %s", getSensorTypeName(sensorType));
74 } else {
75 mSensorRequests[sensorIndex].sensor = std::move(sensors[i]);
76 LOGD("Found sensor: %s", getSensorTypeName(sensorType));
77 }
78 }
79 }
80 }
81
~SensorRequestManager()82 SensorRequestManager::~SensorRequestManager() {
83 SensorRequest nullRequest = SensorRequest();
84 for (size_t i = 0; i < mSensorRequests.size(); i++) {
85 // Disable sensors that have been enabled previously.
86 if (mSensorRequests[i].sensor.has_value()) {
87 mSensorRequests[i].sensor->setRequest(nullRequest);
88 }
89 }
90 }
91
getSensorHandle(SensorType sensorType,uint32_t * sensorHandle) const92 bool SensorRequestManager::getSensorHandle(SensorType sensorType,
93 uint32_t *sensorHandle) const {
94 CHRE_ASSERT(sensorHandle);
95
96 bool sensorHandleIsValid = false;
97 if (sensorType == SensorType::Unknown) {
98 LOGW("Querying for unknown sensor type");
99 } else {
100 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
101 sensorHandleIsValid = mSensorRequests[sensorIndex].sensor.has_value();
102 if (sensorHandleIsValid) {
103 *sensorHandle = getSensorHandleFromSensorType(sensorType);
104 }
105 }
106
107 return sensorHandleIsValid;
108 }
109
setSensorRequest(Nanoapp * nanoapp,uint32_t sensorHandle,const SensorRequest & sensorRequest)110 bool SensorRequestManager::setSensorRequest(Nanoapp *nanoapp,
111 uint32_t sensorHandle, const SensorRequest& sensorRequest) {
112 CHRE_ASSERT(nanoapp);
113
114 // Validate the input to ensure that a valid handle has been provided.
115 SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
116 if (sensorType == SensorType::Unknown) {
117 LOGW("Attempting to configure an invalid sensor handle");
118 return false;
119 }
120
121 // Ensure that the runtime is aware of this sensor type.
122 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
123 SensorRequests& requests = mSensorRequests[sensorIndex];
124 if (!requests.sensor.has_value()) {
125 LOGW("Attempting to configure non-existent sensor");
126 return false;
127 }
128
129 const Sensor& sensor = requests.sensor.value();
130 if (!isSensorRequestValid(sensor, sensorRequest)) {
131 return false;
132 }
133
134 size_t requestIndex;
135 uint16_t eventType = getSampleEventTypeForSensorType(sensorType);
136 bool nanoappHasRequest = (requests.find(nanoapp, &requestIndex) != nullptr);
137
138 bool success;
139 bool requestChanged;
140 if (sensorRequest.getMode() == SensorMode::Off) {
141 if (nanoappHasRequest) {
142 // The request changes the mode to off and there was an existing request.
143 // The existing request is removed from the multiplexer. The nanoapp is
144 // unregistered from events of this type if this request was successful.
145 success = requests.remove(requestIndex, &requestChanged);
146 if (success) {
147 nanoapp->unregisterForBroadcastEvent(eventType);
148 }
149 } else {
150 // The sensor is being configured to Off, but is already Off (there is no
151 // existing request). We assign to success to be true and no other
152 // operation is required.
153 requestChanged = false;
154 success = true;
155 }
156 } else if (!nanoappHasRequest) {
157 // The request changes the mode to the enabled state and there was no
158 // existing request. The request is newly created and added to the
159 // multiplexer. The nanoapp is registered for events if this request was
160 // successful.
161 success = requests.add(sensorRequest, &requestChanged);
162 if (success) {
163 nanoapp->registerForBroadcastEvent(eventType);
164
165 // Deliver last valid event to new clients of on-change sensors
166 if (sensorTypeIsOnChange(sensor.getSensorType())
167 && sensor.getLastEvent() != nullptr) {
168 EventLoopManagerSingleton::get()->getEventLoop()
169 .postEvent(getSampleEventTypeForSensorType(sensorType),
170 sensor.getLastEvent(), nullptr, kSystemInstanceId,
171 nanoapp->getInstanceId());
172 }
173 }
174 } else {
175 // The request changes the mode to the enabled state and there was an
176 // existing request. The existing request is updated.
177 success = requests.update(requestIndex, sensorRequest, &requestChanged);
178 }
179
180 if (requestChanged) {
181 // TODO: Send an event to nanoapps to indicate the rate change.
182 }
183
184 return success;
185 }
186
getSensorInfo(uint32_t sensorHandle,const Nanoapp & nanoapp,struct chreSensorInfo * info) const187 bool SensorRequestManager::getSensorInfo(uint32_t sensorHandle,
188 const Nanoapp& nanoapp,
189 struct chreSensorInfo *info) const {
190 CHRE_ASSERT(info);
191
192 bool success = false;
193
194 // Validate the input to ensure that a valid handle has been provided.
195 SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
196 if (sensorType == SensorType::Unknown) {
197 LOGW("Attempting to access sensor with an invalid handle %" PRIu32,
198 sensorHandle);
199 } else {
200 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
201 if (!mSensorRequests[sensorIndex].sensor.has_value()) {
202 LOGW("Attempting to get sensor info for unsupported sensor handle %"
203 PRIu32, sensorHandle);
204 } else {
205 // Platform-independent properties.
206 info->sensorType = getUnsignedIntFromSensorType(sensorType);
207 info->isOnChange = sensorTypeIsOnChange(sensorType);
208 info->isOneShot = sensorTypeIsOneShot(sensorType);
209 info->unusedFlags = 0;
210
211 // Platform-specific properties.
212 const Sensor& sensor = mSensorRequests[sensorIndex].sensor.value();
213 info->sensorName = sensor.getSensorName();
214
215 // minInterval was added in CHRE API v1.1 - do not attempt to populate for
216 // nanoapps targeting v1.0 as their struct will not be large enough
217 if (nanoapp.getTargetApiVersion() >= CHRE_API_VERSION_1_1) {
218 info->minInterval = sensor.getMinInterval();
219 }
220
221 success = true;
222 }
223 }
224
225 return success;
226 }
227
removeAllRequests(SensorType sensorType)228 bool SensorRequestManager::removeAllRequests(SensorType sensorType) {
229 bool success = false;
230 if (sensorType == SensorType::Unknown) {
231 LOGW("Attempting to remove all requests of an invalid sensor type");
232 } else {
233 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
234 SensorRequests& requests = mSensorRequests[sensorIndex];
235 uint16_t eventType = getSampleEventTypeForSensorType(sensorType);
236
237 for (const SensorRequest& request : requests.multiplexer.getRequests()) {
238 Nanoapp *nanoapp = request.getNanoapp();
239 nanoapp->unregisterForBroadcastEvent(eventType);
240 }
241
242 success = requests.removeAll();
243 }
244 return success;
245 }
246
getSensor(SensorType sensorType)247 Sensor *SensorRequestManager::getSensor(SensorType sensorType) {
248 Sensor *sensorPtr = nullptr;
249 if (sensorType == SensorType::Unknown
250 || sensorType >= SensorType::SENSOR_TYPE_COUNT) {
251 LOGW("Attempting to get Sensor of an invalid SensorType %d",
252 static_cast<int>(sensorType));
253 } else {
254 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
255 if (mSensorRequests[sensorIndex].sensor.has_value()) {
256 sensorPtr = &mSensorRequests[sensorIndex].sensor.value();
257 }
258 }
259 return sensorPtr;
260 }
261
getSensorSamplingStatus(uint32_t sensorHandle,struct chreSensorSamplingStatus * status) const262 bool SensorRequestManager::getSensorSamplingStatus(
263 uint32_t sensorHandle, struct chreSensorSamplingStatus *status) const {
264 CHRE_ASSERT(status);
265
266 bool success = false;
267 SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
268 if (sensorType == SensorType::Unknown) {
269 LOGW("Attempting to access sensor with an invalid handle %" PRIu32,
270 sensorHandle);
271 } else {
272 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
273 if (mSensorRequests[sensorIndex].sensor.has_value()) {
274 success = mSensorRequests[sensorIndex].sensor->getSamplingStatus(status);
275 }
276 }
277 return success;
278 }
279
getRequests(SensorType sensorType) const280 const DynamicVector<SensorRequest>& SensorRequestManager::getRequests(
281 SensorType sensorType) const {
282 size_t sensorIndex = 0;
283 if (sensorType == SensorType::Unknown
284 || sensorType >= SensorType::SENSOR_TYPE_COUNT) {
285 LOGW("Attempting to get requests of an invalid SensorType");
286 } else {
287 sensorIndex = getSensorTypeArrayIndex(sensorType);
288 }
289 return mSensorRequests[sensorIndex].multiplexer.getRequests();
290 }
291
logStateToBuffer(char * buffer,size_t * bufferPos,size_t bufferSize) const292 bool SensorRequestManager::logStateToBuffer(char *buffer, size_t *bufferPos,
293 size_t bufferSize) const {
294 bool success = debugDumpPrint(buffer, bufferPos, bufferSize, "\nSensors:\n");
295 for (uint8_t i = 0; i < static_cast<uint8_t>(SensorType::SENSOR_TYPE_COUNT);
296 i++) {
297 SensorType sensor = static_cast<SensorType>(i);
298 if (sensor != SensorType::Unknown) {
299 for (const auto& request : getRequests(sensor)) {
300 uint32_t instanceId = (request.getNanoapp() != nullptr) ?
301 request.getNanoapp()->getInstanceId() : kInvalidInstanceId;
302 success &= debugDumpPrint(buffer, bufferPos, bufferSize, " %s: mode=%d"
303 " interval(ns)=%" PRIu64 " latency(ns)=%"
304 PRIu64 " nanoappId=%" PRIu32 "\n",
305 getSensorTypeName(sensor), request.getMode(),
306 request.getInterval().toRawNanoseconds(),
307 request.getLatency().toRawNanoseconds(),
308 instanceId);
309 }
310 }
311 }
312
313 return success;
314 }
315
find(const Nanoapp * nanoapp,size_t * index) const316 const SensorRequest *SensorRequestManager::SensorRequests::find(
317 const Nanoapp *nanoapp, size_t *index) const {
318 CHRE_ASSERT(index);
319
320 const auto& requests = multiplexer.getRequests();
321 for (size_t i = 0; i < requests.size(); i++) {
322 const SensorRequest& sensorRequest = requests[i];
323 if (sensorRequest.getNanoapp() == nanoapp) {
324 *index = i;
325 return &sensorRequest;
326 }
327 }
328
329 return nullptr;
330 }
331
add(const SensorRequest & request,bool * requestChanged)332 bool SensorRequestManager::SensorRequests::add(const SensorRequest& request,
333 bool *requestChanged) {
334 CHRE_ASSERT(requestChanged != nullptr);
335 CHRE_ASSERT(sensor.has_value());
336
337 size_t addIndex;
338 bool success = true;
339 if (!multiplexer.addRequest(request, &addIndex, requestChanged)) {
340 *requestChanged = false;
341 success = false;
342 LOG_OOM();
343 } else if (*requestChanged) {
344 success = sensor->setRequest(multiplexer.getCurrentMaximalRequest());
345 if (!success) {
346 // Remove the newly added request since the platform failed to handle it.
347 // The sensor is expected to maintain the existing request so there is no
348 // need to reset the platform to the last maximal request.
349 multiplexer.removeRequest(addIndex, requestChanged);
350
351 // This is a roll-back operation so the maximal change in the multiplexer
352 // must not have changed. The request changed state is forced to false.
353 *requestChanged = false;
354 }
355 }
356
357 return success;
358 }
359
remove(size_t removeIndex,bool * requestChanged)360 bool SensorRequestManager::SensorRequests::remove(size_t removeIndex,
361 bool *requestChanged) {
362 CHRE_ASSERT(requestChanged != nullptr);
363 CHRE_ASSERT(sensor.has_value());
364
365 bool success = true;
366 multiplexer.removeRequest(removeIndex, requestChanged);
367 if (*requestChanged) {
368 success = sensor->setRequest(multiplexer.getCurrentMaximalRequest());
369 if (!success) {
370 LOGE("SensorRequestManager failed to remove a request");
371
372 // If the platform fails to handle this request in a debug build there is
373 // likely an error in the platform. This is not strictly a programming
374 // error but it does make sense to use assert semantics when a platform
375 // fails to handle a request that it had been sent previously.
376 CHRE_ASSERT(false);
377
378 // The request to the platform to set a request when removing has failed
379 // so the request has not changed.
380 *requestChanged = false;
381 }
382 }
383
384 return success;
385 }
386
update(size_t updateIndex,const SensorRequest & request,bool * requestChanged)387 bool SensorRequestManager::SensorRequests::update(size_t updateIndex,
388 const SensorRequest& request,
389 bool *requestChanged) {
390 CHRE_ASSERT(requestChanged != nullptr);
391 CHRE_ASSERT(sensor.has_value());
392
393 bool success = true;
394 SensorRequest previousRequest = multiplexer.getRequests()[updateIndex];
395 multiplexer.updateRequest(updateIndex, request, requestChanged);
396 if (*requestChanged) {
397 success = sensor->setRequest(multiplexer.getCurrentMaximalRequest());
398 if (!success) {
399 // Roll back the request since sending it to the sensor failed. The
400 // request will roll back to the previous maximal. The sensor is
401 // expected to maintain the existing request if a request fails so there
402 // is no need to reset the platform to the last maximal request.
403 multiplexer.updateRequest(updateIndex, previousRequest, requestChanged);
404
405 // This is a roll-back operation so the maximal change in the multiplexer
406 // must not have changed. The request changed state is forced to false.
407 *requestChanged = false;
408 }
409 }
410
411 return success;
412 }
413
removeAll()414 bool SensorRequestManager::SensorRequests::removeAll() {
415 CHRE_ASSERT(sensor.has_value());
416
417 bool requestChanged;
418 multiplexer.removeAllRequests(&requestChanged);
419
420 bool success = true;
421 if (requestChanged) {
422 SensorRequest maximalRequest = multiplexer.getCurrentMaximalRequest();
423 success = sensor->setRequest(maximalRequest);
424 if (!success) {
425 LOGE("SensorRequestManager failed to remove all request");
426
427 // If the platform fails to handle this request in a debug build there is
428 // likely an error in the platform. This is not strictly a programming
429 // error but it does make sense to use assert semantics when a platform
430 // fails to handle a request that it had been sent previously.
431 CHRE_ASSERT(false);
432 }
433 }
434 return success;
435 }
436
437 } // namespace chre
438