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
23 namespace chre {
24 namespace {
25
isSensorRequestValid(const Sensor & sensor,const SensorRequest & sensorRequest)26 bool isSensorRequestValid(const Sensor& sensor,
27 const SensorRequest& sensorRequest) {
28 bool isRequestContinuous = sensorModeIsContinuous(
29 sensorRequest.getMode());
30 bool isRequestOneShot = sensorModeIsOneShot(sensorRequest.getMode());
31 uint64_t requestedInterval = sensorRequest.getInterval().toRawNanoseconds();
32 uint64_t requestedLatency = sensorRequest.getLatency().toRawNanoseconds();
33 SensorType sensorType = sensor.getSensorType();
34
35 bool success = true;
36 if (isRequestContinuous) {
37 if (sensorTypeIsOneShot(sensorType)) {
38 success = false;
39 LOGE("Invalid continuous request for a one-shot sensor.");
40 } else if (requestedInterval < sensor.getMinInterval()) {
41 success = false;
42 LOGE("Invalid requested interval %" PRIu64 " for a continuous sensor"
43 " with minInterval %" PRIu64,
44 requestedInterval, sensor.getMinInterval());
45 }
46 } else if (isRequestOneShot) {
47 if (!sensorTypeIsOneShot(sensorType)) {
48 success = false;
49 LOGE("Invalid one-shot request for a continuous sensor.");
50 } else if (requestedInterval != CHRE_SENSOR_INTERVAL_DEFAULT ||
51 requestedLatency != CHRE_SENSOR_LATENCY_DEFAULT) {
52 success = false;
53 LOGE("Invalid interval and/or latency for a one-shot request.");
54 }
55 }
56 return success;
57 }
58
59 } // namespace
60
SensorRequestManager()61 SensorRequestManager::SensorRequestManager() {
62 mSensorRequests.resize(mSensorRequests.capacity());
63
64 DynamicVector<PlatformSensor> platformSensors;
65 if (!PlatformSensor::getSensors(&platformSensors)) {
66 LOGE("Failed to query the platform for sensors");
67 return;
68 }
69
70 if (platformSensors.empty()) {
71 LOGW("Platform returned zero sensors");
72 }
73
74 for (size_t i = 0; i < platformSensors.size(); i++) {
75 SensorType sensorType = platformSensors[i].getSensorType();
76 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
77 LOGD("Found sensor: %s", getSensorTypeName(sensorType));
78
79 mSensorRequests[sensorIndex].sensor =
80 Sensor(std::move(platformSensors[i]));
81 }
82 }
83
~SensorRequestManager()84 SensorRequestManager::~SensorRequestManager() {
85 SensorRequest nullRequest = SensorRequest();
86 for (size_t i = 0; i < mSensorRequests.size(); i++) {
87 // Disable sensors that have been enabled previously.
88 Sensor& sensor = mSensorRequests[i].sensor;
89 sensor.setRequest(nullRequest);
90 }
91 }
92
getSensorHandle(SensorType sensorType,uint32_t * sensorHandle) const93 bool SensorRequestManager::getSensorHandle(SensorType sensorType,
94 uint32_t *sensorHandle) const {
95 CHRE_ASSERT(sensorHandle);
96
97 bool sensorHandleIsValid = false;
98 if (sensorType == SensorType::Unknown) {
99 LOGW("Querying for unknown sensor type");
100 } else {
101 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
102 sensorHandleIsValid = mSensorRequests[sensorIndex].sensor.isValid();
103 if (sensorHandleIsValid) {
104 *sensorHandle = getSensorHandleFromSensorType(sensorType);
105 }
106 }
107
108 return sensorHandleIsValid;
109 }
110
setSensorRequest(Nanoapp * nanoapp,uint32_t sensorHandle,const SensorRequest & sensorRequest)111 bool SensorRequestManager::setSensorRequest(Nanoapp *nanoapp,
112 uint32_t sensorHandle, const SensorRequest& sensorRequest) {
113 CHRE_ASSERT(nanoapp);
114
115 // Validate the input to ensure that a valid handle has been provided.
116 SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
117 if (sensorType == SensorType::Unknown) {
118 LOGW("Attempting to configure an invalid handle");
119 return false;
120 }
121
122 // Ensure that the runtime is aware of this sensor type.
123 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
124 SensorRequests& requests = mSensorRequests[sensorIndex];
125 const Sensor& sensor = requests.sensor;
126
127 if (!sensor.isValid()) {
128 LOGW("Attempting to configure non-existent sensor");
129 return false;
130 } else 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()->postEvent(
169 getSampleEventTypeForSensorType(sensorType), sensor.getLastEvent(),
170 nullptr, kSystemInstanceId, nanoapp->getInstanceId());
171 }
172 }
173 } else {
174 // The request changes the mode to the enabled state and there was an
175 // existing request. The existing request is updated.
176 success = requests.update(requestIndex, sensorRequest, &requestChanged);
177 }
178
179 if (requestChanged) {
180 // TODO: Send an event to nanoapps to indicate the rate change.
181 }
182
183 return success;
184 }
185
getSensorInfo(uint32_t sensorHandle,const Nanoapp * nanoapp,struct chreSensorInfo * info) const186 bool SensorRequestManager::getSensorInfo(uint32_t sensorHandle,
187 const Nanoapp *nanoapp,
188 struct chreSensorInfo *info) const {
189 CHRE_ASSERT(nanoapp);
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 success = true;
201
202 // Platform-independent properties.
203 info->sensorType = getUnsignedIntFromSensorType(sensorType);
204 info->isOnChange = sensorTypeIsOnChange(sensorType);
205 info->isOneShot = sensorTypeIsOneShot(sensorType);
206 info->unusedFlags = 0;
207
208 // Platform-specific properties.
209 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
210 const Sensor& sensor = mSensorRequests[sensorIndex].sensor;
211 info->sensorName = sensor.getSensorName();
212
213 // minInterval was added in CHRE API 1.1.
214 if (nanoapp->getTargetApiVersion() >= CHRE_API_VERSION_1_1) {
215 info->minInterval = info->isOneShot ? CHRE_SENSOR_INTERVAL_DEFAULT :
216 sensor.getMinInterval();
217 }
218 }
219 return success;
220 }
221
removeAllRequests(SensorType sensorType)222 bool SensorRequestManager::removeAllRequests(SensorType sensorType) {
223 bool success = false;
224 if (sensorType == SensorType::Unknown) {
225 LOGW("Attempting to remove all requests of an invalid sensor type");
226 } else {
227 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
228 SensorRequests& requests = mSensorRequests[sensorIndex];
229 uint16_t eventType = getSampleEventTypeForSensorType(sensorType);
230
231 for (const SensorRequest& request : requests.multiplexer.getRequests()) {
232 Nanoapp *nanoapp = request.getNanoapp();
233 nanoapp->unregisterForBroadcastEvent(eventType);
234 }
235
236 success = requests.removeAll();
237 }
238 return success;
239 }
240
getSensor(SensorType sensorType)241 Sensor *SensorRequestManager::getSensor(SensorType sensorType) {
242 Sensor *sensorPtr = nullptr;
243 if (sensorType == SensorType::Unknown) {
244 LOGW("Attempting to get Sensor of an invalid SensorType");
245 } else {
246 size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
247 sensorPtr = &mSensorRequests[sensorIndex].sensor;
248 }
249 return sensorPtr;
250 }
251
find(const Nanoapp * nanoapp,size_t * index) const252 const SensorRequest *SensorRequestManager::SensorRequests::find(
253 const Nanoapp *nanoapp, size_t *index) const {
254 CHRE_ASSERT(index);
255
256 const auto& requests = multiplexer.getRequests();
257 for (size_t i = 0; i < requests.size(); i++) {
258 const SensorRequest& sensorRequest = requests[i];
259 if (sensorRequest.getNanoapp() == nanoapp) {
260 *index = i;
261 return &sensorRequest;
262 }
263 }
264
265 return nullptr;
266 }
267
add(const SensorRequest & request,bool * requestChanged)268 bool SensorRequestManager::SensorRequests::add(const SensorRequest& request,
269 bool *requestChanged) {
270 CHRE_ASSERT(requestChanged != nullptr);
271
272 size_t addIndex;
273 bool success = true;
274 if (!multiplexer.addRequest(request, &addIndex, requestChanged)) {
275 *requestChanged = false;
276 success = false;
277 LOG_OOM();
278 } else if (*requestChanged) {
279 success = sensor.setRequest(multiplexer.getCurrentMaximalRequest());
280 if (!success) {
281 // Remove the newly added request since the platform failed to handle it.
282 // The sensor is expected to maintain the existing request so there is no
283 // need to reset the platform to the last maximal request.
284 multiplexer.removeRequest(addIndex, requestChanged);
285
286 // This is a roll-back operation so the maximal change in the multiplexer
287 // must not have changed. The request changed state is forced to false.
288 *requestChanged = false;
289 }
290 }
291
292 return success;
293 }
294
remove(size_t removeIndex,bool * requestChanged)295 bool SensorRequestManager::SensorRequests::remove(size_t removeIndex,
296 bool *requestChanged) {
297 CHRE_ASSERT(requestChanged != nullptr);
298
299 bool success = true;
300 multiplexer.removeRequest(removeIndex, requestChanged);
301 if (*requestChanged) {
302 success = sensor.setRequest(multiplexer.getCurrentMaximalRequest());
303 if (!success) {
304 LOGE("SensorRequestManager failed to remove a request");
305
306 // If the platform fails to handle this request in a debug build there is
307 // likely an error in the platform. This is not strictly a programming
308 // error but it does make sense to use assert semantics when a platform
309 // fails to handle a request that it had been sent previously.
310 CHRE_ASSERT(false);
311
312 // The request to the platform to set a request when removing has failed
313 // so the request has not changed.
314 *requestChanged = false;
315 }
316 }
317
318 return success;
319 }
320
update(size_t updateIndex,const SensorRequest & request,bool * requestChanged)321 bool SensorRequestManager::SensorRequests::update(size_t updateIndex,
322 const SensorRequest& request,
323 bool *requestChanged) {
324 CHRE_ASSERT(requestChanged != nullptr);
325
326 bool success = true;
327 SensorRequest previousRequest = multiplexer.getRequests()[updateIndex];
328 multiplexer.updateRequest(updateIndex, request, requestChanged);
329 if (*requestChanged) {
330 success = sensor.setRequest(multiplexer.getCurrentMaximalRequest());
331 if (!success) {
332 // Roll back the request since sending it to the sensor failed. The
333 // request will roll back to the previous maximal. The sensor is
334 // expected to maintain the existing request if a request fails so there
335 // is no need to reset the platform to the last maximal request.
336 multiplexer.updateRequest(updateIndex, previousRequest, requestChanged);
337
338 // This is a roll-back operation so the maximal change in the multiplexer
339 // must not have changed. The request changed state is forced to false.
340 *requestChanged = false;
341 }
342 }
343
344 return success;
345 }
346
removeAll()347 bool SensorRequestManager::SensorRequests::removeAll() {
348 bool requestChanged;
349 multiplexer.removeAllRequests(&requestChanged);
350
351 bool success = true;
352 if (requestChanged) {
353 SensorRequest maximalRequest = multiplexer.getCurrentMaximalRequest();
354 success = sensor.setRequest(maximalRequest);
355 if (!success) {
356 LOGE("SensorRequestManager failed to remove all request");
357
358 // If the platform fails to handle this request in a debug build there is
359 // likely an error in the platform. This is not strictly a programming
360 // error but it does make sense to use assert semantics when a platform
361 // fails to handle a request that it had been sent previously.
362 CHRE_ASSERT(false);
363 }
364 }
365 return success;
366 }
367
368 } // namespace chre
369