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 <chre.h>
18 #include <cinttypes>
19 
20 #include "chre/util/flatbuffers/helpers.h"
21 #include "chre/util/nanoapp/callbacks.h"
22 #include "chre/util/unique_ptr.h"
23 #include "common.h"
24 #include "generated/chre_power_test_generated.h"
25 #include "request_manager.h"
26 
27 #ifdef CHRE_NANOAPP_INTERNAL
28 namespace chre {
29 namespace {
30 #endif  // CHRE_NANOAPP_INTERNAL
31 
32 using chre::power_test::MessageType;
33 
34 /**
35  * Responds to a host request indicating whether the request was successfully
36  * executed.
37  *
38  * @param success whether the nanoapp successfully fullfilled a request
39  * @param hostEndpoint the host endpoint that sent the request to the nanoapp
40  */
sendResponseMessageToHost(bool success,uint16_t hostEndpoint)41 void sendResponseMessageToHost(bool success, uint16_t hostEndpoint) {
42   auto builder = chre::MakeUnique<chre::ChreFlatBufferBuilder>();
43   if (builder.isNull()) {
44     LOG_OOM();
45   } else {
46     builder->Finish(
47         chre::power_test::CreateNanoappResponseMessage(*builder, success));
48 
49     // TODO: Modify this logic to remove the buffer copy now that the latest
50     // version of flatbuffers allows releasing the underlying buffer from the
51     // builder.
52     size_t bufferCopySize = builder->GetSize();
53     void *buffer = chreHeapAlloc(bufferCopySize);
54     if (buffer == nullptr) {
55       LOG_OOM();
56     } else {
57       memcpy(buffer, builder->GetBufferPointer(), bufferCopySize);
58       if (!chreSendMessageToHostEndpoint(
59               buffer, bufferCopySize,
60               static_cast<uint32_t>(MessageType::NANOAPP_RESPONSE),
61               hostEndpoint, chre::heapFreeMessageCallback)) {
62         LOGE("Failed to send response message with success %d", success);
63       }
64     }
65   }
66 }
67 
nanoappStart()68 bool nanoappStart() {
69   LOGI("App started on platform ID %" PRIx64, chreGetPlatformId());
70 
71   RequestManagerSingleton::init();
72 
73   return true;
74 }
75 
nanoappHandleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)76 void nanoappHandleEvent(uint32_t senderInstanceId, uint16_t eventType,
77                         const void *eventData) {
78   switch (eventType) {
79     case CHRE_EVENT_MESSAGE_FROM_HOST: {
80       auto *msg = static_cast<const chreMessageFromHostData *>(eventData);
81       bool success =
82           RequestManagerSingleton::get()->handleMessageFromHost(*msg);
83       sendResponseMessageToHost(success, msg->hostEndpoint);
84       break;
85     }
86     case CHRE_EVENT_TIMER:
87       RequestManagerSingleton::get()->handleTimerEvent(eventData);
88       break;
89     case CHRE_EVENT_WIFI_ASYNC_RESULT: {
90       const struct chreAsyncResult *event =
91           static_cast<const struct chreAsyncResult *>(eventData);
92       LOGD("Wifi async result type %" PRIu8 " success %d error %" PRIu8,
93            event->requestType, event->success, event->errorCode);
94       break;
95     }
96     case CHRE_EVENT_WIFI_SCAN_RESULT: {
97       const struct chreWifiScanEvent *event =
98           static_cast<const struct chreWifiScanEvent *>(eventData);
99       LOGD("Wifi scan received with %" PRIu8 " results, scanType %" PRIu8
100            ", radioChainPref %" PRIu8,
101            event->resultCount, event->scanType, event->radioChainPref);
102       break;
103     }
104     case CHRE_EVENT_GNSS_ASYNC_RESULT: {
105       const struct chreAsyncResult *event =
106           static_cast<const struct chreAsyncResult *>(eventData);
107       LOGD("GNSS async result type %" PRIu8 " success %d error %" PRIu8,
108            event->requestType, event->success, event->errorCode);
109       break;
110     }
111     case CHRE_EVENT_GNSS_LOCATION:
112       LOGD("GNSS location received");
113       break;
114     case CHRE_EVENT_GNSS_DATA:
115       LOGD("GNSS measurement received");
116       break;
117     case CHRE_EVENT_WWAN_CELL_INFO_RESULT:
118       LOGD("Cell info received");
119       break;
120     case CHRE_EVENT_SENSOR_SAMPLING_CHANGE: {
121       const struct chreSensorSamplingStatusEvent *event =
122           static_cast<const struct chreSensorSamplingStatusEvent *>(eventData);
123       LOGD("Sensor sampling status change handle %" PRIu32
124            " enabled %d interval %" PRIu64 " latency %" PRIu64,
125            event->sensorHandle, event->status.enabled, event->status.interval,
126            event->status.latency);
127       break;
128     }
129     case CHRE_EVENT_AUDIO_DATA: {
130       const struct chreAudioDataEvent *event =
131           static_cast<const struct chreAudioDataEvent *>(eventData);
132       LOGD("Audio data received with %" PRIu32 " samples", event->sampleCount);
133       break;
134     }
135     case CHRE_EVENT_AUDIO_SAMPLING_CHANGE: {
136       const struct chreAudioSourceStatusEvent *event =
137           static_cast<const struct chreAudioSourceStatusEvent *>(eventData);
138       LOGD("Audio sampling status event for handle %" PRIu32 ", suspended: %d",
139            event->handle, event->status.suspended);
140       break;
141     }
142     default:
143       // TODO: Make this log less as sensor events will spam the logcat if debug
144       // logging is enabled.
145       LOGV("Received event type %" PRIu16, eventType);
146   }
147 }
148 
nanoappEnd()149 void nanoappEnd() {
150   RequestManagerSingleton::deinit();
151   LOGI("Stopped");
152 }
153 
154 #ifdef CHRE_NANOAPP_INTERNAL
155 }  // anonymous namespace
156 }  // namespace chre
157 
158 #include "chre/platform/static_nanoapp_init.h"
159 #include "chre/util/nanoapp/app_id.h"
160 #include "chre/util/system/napp_permissions.h"
161 
162 using chre::NanoappPermissions;
163 
164 CHRE_STATIC_NANOAPP_INIT(PowerTest, chre::kPowerTestAppId, 0,
165                          NanoappPermissions::CHRE_PERMS_AUDIO |
166                              NanoappPermissions::CHRE_PERMS_GNSS |
167                              NanoappPermissions::CHRE_PERMS_WIFI |
168                              NanoappPermissions::CHRE_PERMS_WWAN);
169 #endif  // CHRE_NANOAPP_INTERNAL
170