xref: /aosp_15_r20/system/chre/apps/power_test/common/request_manager.cc (revision 84e339476a462649f82315436d70fd732297a399)
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(&params, 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(&params, 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