• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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