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