1 /*
2 * Copyright (C) 2019 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 "request_manager.h"
18
19 #include "chre/util/flatbuffers/helpers.h"
20 #include "chre/util/macros.h"
21 #include "chre/util/nanoapp/audio.h"
22 #include "chre/util/nanoapp/callbacks.h"
23 #include "chre/util/nested_data_ptr.h"
24 #include "chre/util/unique_ptr.h"
25
26 namespace chre {
27 namespace {
28
29 //! List of all sensor types that can be interacted with from the nanoapp.
30 constexpr uint8_t kAllSensorTypes[] = {
31 CHRE_SENSOR_TYPE_ACCELEROMETER,
32 CHRE_SENSOR_TYPE_GYROSCOPE,
33 CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE,
34 CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD,
35 CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD,
36 CHRE_SENSOR_TYPE_PRESSURE,
37 CHRE_SENSOR_TYPE_LIGHT,
38 CHRE_SENSOR_TYPE_PROXIMITY,
39 CHRE_SENSOR_TYPE_STEP_DETECT,
40 CHRE_SENSOR_TYPE_STEP_COUNTER,
41 CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER,
42 CHRE_SENSOR_TYPE_ACCELEROMETER_TEMPERATURE,
43 CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE,
44 CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD_TEMPERATURE,
45 CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT,
46 CHRE_SENSOR_TYPE_STATIONARY_DETECT,
47 };
48
49 /**
50 * Retrieve the configure mode for the given sensor type.
51 *
52 * @param sensorType The type of the sensor
53 * @return The sensor configure mode for the given sensor type
54 */
getModeForSensorType(uint8_t sensorType)55 chreSensorConfigureMode getModeForSensorType(uint8_t sensorType) {
56 chreSensorConfigureMode mode;
57 switch (sensorType) {
58 case CHRE_SENSOR_TYPE_ACCELEROMETER:
59 case CHRE_SENSOR_TYPE_GYROSCOPE:
60 case CHRE_SENSOR_TYPE_UNCALIBRATED_GYROSCOPE:
61 case CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD:
62 case CHRE_SENSOR_TYPE_UNCALIBRATED_GEOMAGNETIC_FIELD:
63 case CHRE_SENSOR_TYPE_PRESSURE:
64 case CHRE_SENSOR_TYPE_LIGHT:
65 case CHRE_SENSOR_TYPE_PROXIMITY:
66 case CHRE_SENSOR_TYPE_STEP_DETECT:
67 case CHRE_SENSOR_TYPE_STEP_COUNTER:
68 case CHRE_SENSOR_TYPE_UNCALIBRATED_ACCELEROMETER:
69 case CHRE_SENSOR_TYPE_ACCELEROMETER_TEMPERATURE:
70 case CHRE_SENSOR_TYPE_GYROSCOPE_TEMPERATURE:
71 case CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD_TEMPERATURE:
72 mode = CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS;
73 break;
74 case CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT:
75 case CHRE_SENSOR_TYPE_STATIONARY_DETECT:
76 mode = CHRE_SENSOR_CONFIGURE_MODE_ONE_SHOT;
77 break;
78 default:
79 LOGE("Mode requested for unhandled sensor type %" PRIu8
80 " defaulting to continuous",
81 sensorType);
82 mode = CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS;
83 }
84 return mode;
85 }
86
87 /**
88 * Verifies a given message from the host is a valid message to the nanoapp.
89 *
90 * @param hostMessage message being delivered from the host
91 * @param verifiedMessage if verification is successful, contains the decoded
92 * message from the host. Otherwise, is uninitialized.
93 * @return true if the message was verified to be a valid.
94 */
95 template <class MessageClass>
verifyMessage(const chreMessageFromHostData & hostMessage,const MessageClass ** verifiedMessage)96 bool verifyMessage(const chreMessageFromHostData &hostMessage,
97 const MessageClass **verifiedMessage) {
98 flatbuffers::Verifier verifier(
99 static_cast<const uint8_t *>(hostMessage.message),
100 hostMessage.messageSize);
101 bool verified = verifier.VerifyBuffer<MessageClass>(nullptr);
102 if (verified) {
103 *verifiedMessage = flatbuffers::GetRoot<MessageClass>(hostMessage.message);
104 } else {
105 LOGE("Failed to verify %s message from host",
106 power_test::EnumNameMessageType(
107 static_cast<power_test::MessageType>(hostMessage.messageType)));
108 }
109 return verified;
110 }
111
112 } // namespace
113
114 using power_test::AudioRequestMessage;
115 using power_test::BreakItMessage;
116 using power_test::CellQueryMessage;
117 using power_test::GnssLocationMessage;
118 using power_test::GnssMeasurementMessage;
119 using power_test::MessageType;
120 using power_test::NanoappResponseMessage;
121 using power_test::SensorRequestMessage;
122 using power_test::TimerMessage;
123 using power_test::WifiNanSubCancelMessage;
124 using power_test::WifiNanSubMessage;
125 using power_test::WifiScanMessage;
126
sendResponseMessageToHost(bool success)127 void RequestManager::sendResponseMessageToHost(bool success) {
128 auto builder = chre::MakeUnique<chre::ChreFlatBufferBuilder>();
129 if (builder.isNull()) {
130 LOG_OOM();
131 } else {
132 builder->Finish(
133 chre::power_test::CreateNanoappResponseMessage(*builder, success));
134
135 size_t bufferCopySize = builder->GetSize();
136 void *buffer = chreHeapAlloc(bufferCopySize);
137 if (buffer == nullptr) {
138 LOG_OOM();
139 } else {
140 memcpy(buffer, builder->GetBufferPointer(), bufferCopySize);
141 if (!chreSendMessageToHostEndpoint(
142 buffer, bufferCopySize,
143 static_cast<uint32_t>(MessageType::NANOAPP_RESPONSE),
144 mLastHostEndpointId, chre::heapFreeMessageCallback)) {
145 LOGE("Failed to send response message with success %d", success);
146 }
147 }
148 }
149 }
150
requestTimer(bool enable,TimerType type,Nanoseconds delay)151 bool RequestManager::requestTimer(bool enable, TimerType type,
152 Nanoseconds delay) {
153 bool success = false;
154 if (enable) {
155 // Stop previous request if active.
156 chreTimerCancel(mTimerIds[type]);
157 mTimerIds[type] = CHRE_TIMER_INVALID;
158
159 // Set a timer for the new request.
160 NestedDataPtr<TimerType> timerType(type);
161 uint32_t timerId =
162 chreTimerSet(delay.toRawNanoseconds(), timerType, false /* oneShot */);
163 if (timerId != CHRE_TIMER_INVALID) {
164 success = true;
165 mTimerIds[type] = timerId;
166 }
167 } else {
168 success = chreTimerCancel(mTimerIds[type]);
169 mTimerIds[type] = CHRE_TIMER_INVALID;
170 }
171 LOGI("RequestTimer success %d, enable %d, type %d, delay %" PRIu64, success,
172 enable, type, delay.toRawNanoseconds());
173 return success;
174 }
175
wifiTimerCallback() const176 void RequestManager::wifiTimerCallback() const {
177 struct chreWifiScanParams params = {};
178 params.scanType = mWifiScanType;
179 params.radioChainPref = mWifiRadioChain;
180 params.channelSet = mWifiChannelSet;
181 bool success = chreWifiRequestScanAsync(¶ms, nullptr /*cookie*/);
182 LOGI("Requested WiFi - success %d, scanType %" PRIu8 " radioChain %" PRIu8
183 " channelSet %" PRIu8,
184 success, params.scanType, params.radioChainPref, params.channelSet);
185 }
186
requestGnssLocation(bool enable,uint32_t scanIntervalMillis,uint32_t minTimeToNextFixMillis) const187 bool RequestManager::requestGnssLocation(
188 bool enable, uint32_t scanIntervalMillis,
189 uint32_t minTimeToNextFixMillis) const {
190 bool success;
191 if (enable) {
192 success = chreGnssLocationSessionStartAsync(
193 scanIntervalMillis, minTimeToNextFixMillis, nullptr /* cookie */);
194 } else {
195 success = chreGnssLocationSessionStopAsync(nullptr /* cookie */);
196 }
197 LOGI("RequestGnss success %d, enable %d, scanIntervalMillis %" PRIu32
198 " minTimeToNextFixMillis %" PRIu32,
199 success, enable, scanIntervalMillis, minTimeToNextFixMillis);
200 return success;
201 }
202
requestGnssMeasurement(bool enable,uint32_t intervalMillis) const203 bool RequestManager::requestGnssMeasurement(bool enable,
204 uint32_t intervalMillis) const {
205 bool success;
206 if (enable) {
207 success = chreGnssMeasurementSessionStartAsync(intervalMillis,
208 nullptr /* cookie */);
209 } else {
210 success = chreGnssMeasurementSessionStopAsync(nullptr /* cookie */);
211 }
212 LOGI("RequestGnssMeasurement success %d, enable %d, intervalMillis %" PRIu32,
213 success, enable, intervalMillis);
214 return success;
215 }
216
cellTimerCallback() const217 void RequestManager::cellTimerCallback() const {
218 bool success = chreWwanGetCellInfoAsync(nullptr /* cookie */);
219 LOGI("Requested Cell - success %d", success);
220 }
221
requestAudio(bool enable,uint64_t bufferDurationNs) const222 bool RequestManager::requestAudio(bool enable,
223 uint64_t bufferDurationNs) const {
224 bool success;
225
226 if (enable) {
227 // Only request audio data from the first source
228 // TODO: Request audio data from all available sources (or allow configuring
229 // which source to sample from)
230 success = chreAudioConfigureSource(0 /* handle */, true /* enable */,
231 bufferDurationNs, bufferDurationNs);
232 } else {
233 success = chreAudioConfigureSource(0 /* handle */, false /* enable */,
234 0 /* bufferDuration */,
235 0 /* deliveryInterval */);
236 }
237 LOGI("RequestAudio success %d, enable %d, bufferDurationNs %" PRIu64, success,
238 enable, bufferDurationNs);
239 return success;
240 }
241
requestSensor(bool enable,uint8_t sensorType,uint64_t samplingIntervalNs,uint64_t latencyNs) const242 bool RequestManager::requestSensor(bool enable, uint8_t sensorType,
243 uint64_t samplingIntervalNs,
244 uint64_t latencyNs) const {
245 uint32_t sensorHandle;
246 bool success = chreSensorFindDefault(sensorType, &sensorHandle);
247
248 if (success) {
249 if (enable) {
250 success =
251 chreSensorConfigure(sensorHandle, getModeForSensorType(sensorType),
252 samplingIntervalNs, latencyNs);
253 } else {
254 success = chreSensorConfigureModeOnly(sensorHandle,
255 CHRE_SENSOR_CONFIGURE_MODE_DONE);
256 }
257 }
258
259 LOGI("RequestSensor success %d, enable %d, sensorType %" PRIu8
260 " samplingIntervalNs %" PRIu64 " latencyNs %" PRIu64,
261 success, enable, sensorType, samplingIntervalNs, latencyNs);
262 return success;
263 }
264
requestAllSensors(bool enable) const265 bool RequestManager::requestAllSensors(bool enable) const {
266 bool success = true;
267 uint32_t sensorHandle;
268 struct chreSensorInfo sensorInfo;
269 for (uint8_t i = 0; i < ARRAY_SIZE(kAllSensorTypes); i++) {
270 success &= chreSensorFindDefault(kAllSensorTypes[i], &sensorHandle) &&
271 chreGetSensorInfo(sensorHandle, &sensorInfo) &&
272 requestSensor(enable, kAllSensorTypes[i], sensorInfo.minInterval,
273 CHRE_SENSOR_LATENCY_ASAP);
274 }
275
276 LOGI("requestAllSensors success %d enable %d", success, enable);
277 return success;
278 }
279
requestAudioAtFastestRate(bool enable) const280 bool RequestManager::requestAudioAtFastestRate(bool enable) const {
281 struct chreAudioSource audioSource;
282 bool success = chreAudioGetSource(0 /* handle */, &audioSource);
283 if (success) {
284 LOGI("Found audio source '%s' with %" PRIu32 "Hz %s data", audioSource.name,
285 audioSource.sampleRate,
286 chre::getChreAudioFormatString(audioSource.format));
287 LOGI(" buffer duration: [%" PRIu64 "ns, %" PRIu64 "ns]",
288 audioSource.minBufferDuration, audioSource.maxBufferDuration);
289 success &= requestAudio(enable, audioSource.minBufferDuration);
290 }
291
292 LOGI("requestAudioAtFastestRate success %d enable %d", success, enable);
293 return success;
294 }
295
requestBreakIt(bool enable)296 bool RequestManager::requestBreakIt(bool enable) {
297 bool success = requestTimer(enable, TimerType::WIFI, Seconds(1));
298 success &= requestGnssLocation(enable, chre::kOneSecondInNanoseconds,
299 0 /* minTimeToNextFixMillis */);
300 success &= requestTimer(enable, TimerType::CELL, Seconds(1));
301 success &= requestAudioAtFastestRate(enable);
302 success &= requestAllSensors(enable);
303 LOGI("RequestBreakIt success %d enable %d", success, enable);
304 return success;
305 }
306
handleTimerEvent(const void * cookie) const307 void RequestManager::handleTimerEvent(const void *cookie) const {
308 if (cookie != nullptr) {
309 NestedDataPtr<TimerType> timerType(const_cast<void *>(cookie));
310 switch (timerType.data) {
311 case TimerType::WAKEUP:
312 LOGI("Received a wakeup timer event");
313 break;
314 case TimerType::WIFI:
315 wifiTimerCallback();
316 break;
317 case TimerType::CELL:
318 cellTimerCallback();
319 break;
320 default:
321 LOGE("Invalid timer type received %d", timerType.data);
322 }
323 }
324 }
325
handleNanIdResult(const struct chreWifiNanIdentifierEvent * event)326 void RequestManager::handleNanIdResult(
327 const struct chreWifiNanIdentifierEvent *event) {
328 LOGI("Received NAN ID result: ID %" PRIu32 " success %d", event->id,
329 event->result.success);
330 auto builder = chre::MakeUnique<chre::ChreFlatBufferBuilder>();
331 if (builder.isNull()) {
332 LOG_OOM();
333 } else {
334 builder->Finish(chre::power_test::CreateWifiNanSubResponseMessage(
335 *builder, event->result.success, event->id));
336
337 size_t bufferCopySize = builder->GetSize();
338 void *buffer = chreHeapAlloc(bufferCopySize);
339 if (buffer == nullptr) {
340 LOG_OOM();
341 } else {
342 memcpy(buffer, builder->GetBufferPointer(), bufferCopySize);
343 if (!chreSendMessageToHostEndpoint(
344 buffer, bufferCopySize,
345 static_cast<uint32_t>(MessageType::WIFI_NAN_SUB_RESP),
346 mLastHostEndpointId, chre::heapFreeMessageCallback)) {
347 LOGE("Failed to send message with success %d", event->result.success);
348 }
349 }
350 }
351 }
352
requestNanRanging(const struct chreWifiNanDiscoveryEvent * event)353 void RequestManager::requestNanRanging(
354 const struct chreWifiNanDiscoveryEvent *event) {
355 chreWifiNanRangingParams params = {};
356 memcpy(params.macAddress, event->publisherAddress, CHRE_WIFI_BSSID_LEN);
357 bool success = chreWifiNanRequestRangingAsync(¶ms, nullptr);
358 LOGI("Requested NAN ranging %d", success);
359 }
360
requestWifiNanSub(const WifiNanSubMessage * msg)361 bool RequestManager::requestWifiNanSub(const WifiNanSubMessage *msg) {
362 chreWifiNanSubscribeConfig config{};
363 config.subscribeType = msg->sub_type();
364 config.service = reinterpret_cast<const char *>(msg->service_name()->data());
365 if (msg->service_specific_info()) {
366 config.serviceSpecificInfo = msg->service_specific_info()->Data();
367 config.serviceSpecificInfoSize = msg->service_specific_info()->size();
368 }
369 if (msg->match_filter()) {
370 config.matchFilter = msg->match_filter()->Data();
371 config.matchFilterLength = msg->match_filter()->size();
372 }
373
374 bool success = chreWifiNanSubscribe(&config, nullptr /* cookie */);
375 LOGI("requestWifiNanSub success %d", success);
376 return success;
377 }
378
cancelWifiNanSub(uint32_t subscriptionId)379 bool RequestManager::cancelWifiNanSub(uint32_t subscriptionId) {
380 bool success = chreWifiNanSubscribeCancel(subscriptionId);
381 LOGI("cancelWifiNanSub success %d", success);
382 return success;
383 }
384
handleMessageFromHost(const chreMessageFromHostData & hostMessage)385 void RequestManager::handleMessageFromHost(
386 const chreMessageFromHostData &hostMessage) {
387 bool success = false;
388 if (hostMessage.message == nullptr) {
389 LOGE("Host message from %" PRIu16 " has empty message",
390 hostMessage.hostEndpoint);
391 } else {
392 mLastHostEndpointId = hostMessage.hostEndpoint;
393 switch (static_cast<MessageType>(hostMessage.messageType)) {
394 case MessageType::TIMER_TEST: {
395 const TimerMessage *msg;
396 if (verifyMessage<TimerMessage>(hostMessage, &msg)) {
397 success = requestTimer(msg->enable(), TimerType::WAKEUP,
398 Nanoseconds(msg->wakeup_interval_ns()));
399 }
400 break;
401 }
402 case MessageType::WIFI_SCAN_TEST: {
403 const WifiScanMessage *msg;
404 if (verifyMessage<WifiScanMessage>(hostMessage, &msg)) {
405 mWifiScanType = static_cast<uint8_t>(msg->scan_type());
406 mWifiRadioChain = static_cast<uint8_t>(msg->radio_chain());
407 mWifiChannelSet = static_cast<uint8_t>(msg->channel_set());
408 success = requestTimer(msg->enable(), TimerType::WIFI,
409 Nanoseconds(msg->scan_interval_ns()));
410 }
411 break;
412 }
413 case MessageType::GNSS_LOCATION_TEST: {
414 const GnssLocationMessage *msg;
415 if (verifyMessage<GnssLocationMessage>(hostMessage, &msg)) {
416 success =
417 requestGnssLocation(msg->enable(), msg->scan_interval_millis(),
418 msg->min_time_to_next_fix_millis());
419 }
420 break;
421 }
422 case MessageType::CELL_QUERY_TEST: {
423 const CellQueryMessage *msg;
424 if (verifyMessage<CellQueryMessage>(hostMessage, &msg)) {
425 success = requestTimer(msg->enable(), TimerType::CELL,
426 Nanoseconds(msg->query_interval_ns()));
427 }
428 break;
429 }
430 case MessageType::AUDIO_REQUEST_TEST: {
431 const AudioRequestMessage *msg;
432 if (verifyMessage<AudioRequestMessage>(hostMessage, &msg)) {
433 success = requestAudio(msg->enable(), msg->buffer_duration_ns());
434 }
435 break;
436 }
437 case MessageType::SENSOR_REQUEST_TEST: {
438 const SensorRequestMessage *msg;
439 if (verifyMessage<SensorRequestMessage>(hostMessage, &msg)) {
440 success =
441 requestSensor(msg->enable(), static_cast<uint8_t>(msg->sensor()),
442 msg->sampling_interval_ns(), msg->latency_ns());
443 }
444 break;
445 }
446 case MessageType::BREAK_IT_TEST: {
447 const BreakItMessage *msg;
448 if (verifyMessage<BreakItMessage>(hostMessage, &msg)) {
449 success = requestBreakIt(msg->enable());
450 }
451 break;
452 }
453 case MessageType::GNSS_MEASUREMENT_TEST: {
454 const GnssMeasurementMessage *msg;
455 if (verifyMessage<GnssMeasurementMessage>(hostMessage, &msg)) {
456 success =
457 requestGnssMeasurement(msg->enable(), msg->min_interval_millis());
458 }
459 break;
460 }
461 case MessageType::WIFI_NAN_SUB: {
462 const WifiNanSubMessage *msg;
463 if (verifyMessage<WifiNanSubMessage>(hostMessage, &msg)) {
464 success = requestWifiNanSub(msg);
465 }
466 break;
467 }
468 case MessageType::WIFI_NAN_SUB_CANCEL: {
469 const WifiNanSubCancelMessage *msg;
470 if (verifyMessage<WifiNanSubCancelMessage>(hostMessage, &msg)) {
471 success = cancelWifiNanSub(msg->subscription_id());
472 }
473 break;
474 }
475 default:
476 LOGE("Received unknown host message %" PRIu32, hostMessage.messageType);
477 }
478 }
479 sendResponseMessageToHost(success);
480 }
481
482 } // namespace chre
483