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