1 /*
2 * Copyright (C) 2016 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 /**
18 * Nanoapp which performs a number of operations within nanoappStart().
19 *
20 * This nanoapp is to confirm a number of CHRE methods can be invoked from
21 * within nanoappStart(). There are other tests which test each of these
22 * CHRE methods more in depth. We're just doing a sanity check that calling
23 * from nanoappStart() works at all.
24 *
25 * Specifically, we're testing:
26 * o chreHeapAlloc() and chreHeapFree()
27 * o chreGetInstanceId()
28 * o chreSendEvent() [*]
29 * o chreTimerSet() [*]
30 * o chreSensorFindDefault() and chreSensorConfigure() [*]
31 * o chreSendMessageToHost() [**]
32 *
33 * [*] These require nanoappHandleEvent() to be called successfully in order
34 * to confirm.
35 * [**] This is confirmed by the host receiving this message.
36 *
37 * This isn't a "general" test, so it doesn't have a standard communication
38 * protocol. Notably, the Host doesn't send any messages to this nanoapp.
39 *
40 * Protocol:
41 * Nanoapp to Host: kContinue
42 * Nanoapp to Host: kSuccess
43 */
44
45 #include <cinttypes>
46
47 #include <chre.h>
48
49 #include <shared/send_message.h>
50
51 using nanoapp_testing::MessageType;
52 using nanoapp_testing::sendMessageToHost;
53 using nanoapp_testing::sendFatalFailureToHost;
54 using nanoapp_testing::sendSuccessToHost;
55
56
57 static bool gInMethod = false;
58 static uint32_t gInstanceId;
59 static uint32_t gTimerId;
60 static uint32_t gSensorHandle;
61
62 constexpr size_t kSelfEventStage = 0;
63 constexpr size_t kTimerStage = 1;
64 constexpr size_t kSensorStage = 2;
65 constexpr size_t kStageCount = 3;
66
67 constexpr uint32_t kAllFinished = (1 << kStageCount) - 1;
68 static uint32_t gFinishedBitmask = 0;
69
70 constexpr uint16_t kEventType = CHRE_EVENT_FIRST_USER_VALUE;
71
markSuccess(uint32_t stage)72 static void markSuccess(uint32_t stage) {
73 uint32_t finishedBit = (1 << stage);
74 if ((kAllFinished & finishedBit) == 0) {
75 sendFatalFailureToHost("markSuccess bad stage", &stage);
76 }
77
78 if ((gFinishedBitmask & finishedBit) == 0) {
79 chreLog(CHRE_LOG_DEBUG, "Stage %" PRIu32 " succeeded", stage);
80 gFinishedBitmask |= finishedBit;
81 if (gFinishedBitmask == kAllFinished) {
82 sendSuccessToHost();
83 }
84 }
85 }
86
checkSelfEvent(uint16_t eventType,const uint32_t * eventData)87 static void checkSelfEvent(uint16_t eventType, const uint32_t *eventData) {
88 if (eventType != kEventType) {
89 uint32_t e = eventType;
90 sendFatalFailureToHost("Event from self, bad event type:", &e);
91 }
92 if (eventData == nullptr) {
93 sendFatalFailureToHost("Event from self, null data");
94 }
95 if (*eventData != gInstanceId) {
96 sendFatalFailureToHost("Event from self, bad data:", eventData);
97 }
98 markSuccess(kSelfEventStage);
99 }
100
checkTimerEvent(const uint32_t * eventData)101 static void checkTimerEvent(const uint32_t *eventData) {
102 if (eventData == nullptr) {
103 sendFatalFailureToHost("TimerEvent, null data");
104 }
105 if (*eventData != gInstanceId) {
106 sendFatalFailureToHost("TimerEvent, bad data:", eventData);
107 }
108 markSuccess(kTimerStage);
109 }
110
checkSensorEvent(const void * eventData)111 static void checkSensorEvent(const void *eventData) {
112 const chreSensorDataHeader* header =
113 static_cast<const chreSensorDataHeader *>(eventData);
114 if (header == nullptr) {
115 sendFatalFailureToHost("sensorEvent, null data");
116 }
117 if (header->sensorHandle != gSensorHandle) {
118 sendFatalFailureToHost("sensorEvent for wrong handle",
119 &header->sensorHandle);
120 }
121 if (header->readingCount == 0) {
122 sendFatalFailureToHost("sensorEvent has readingCount of 0");
123 }
124 if ((header->reserved[0] != 0) || (header->reserved[1] != 0)) {
125 sendFatalFailureToHost("sensorEvent has non-zero reserved bytes");
126 }
127 markSuccess(kSensorStage);
128 }
129
nanoappHandleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)130 extern "C" void nanoappHandleEvent(uint32_t senderInstanceId,
131 uint16_t eventType,
132 const void* eventData) {
133 if (gInMethod) {
134 sendFatalFailureToHost("CHRE reentered nanoapp");
135 }
136 gInMethod = true;
137 const uint32_t *intData = static_cast<const uint32_t *>(eventData);
138 if (senderInstanceId == gInstanceId) {
139 checkSelfEvent(eventType, intData);
140
141 } else if (senderInstanceId == CHRE_INSTANCE_ID) {
142 if (eventType == CHRE_EVENT_TIMER) {
143 checkTimerEvent(intData);
144 } else if (eventType == CHRE_EVENT_SENSOR_ACCELEROMETER_DATA) {
145 checkSensorEvent(eventData);
146 } else if (eventType == CHRE_EVENT_SENSOR_SAMPLING_CHANGE) {
147 // This could have been generated when we configured the
148 // sensor. We just ignore it.
149 } else {
150 uint32_t e = eventType;
151 sendFatalFailureToHost("Unexpected event from CHRE:", &e);
152 }
153 } else {
154 sendFatalFailureToHost("Unexpected senderInstanceId",
155 &senderInstanceId);
156 }
157 gInMethod = false;
158 }
159
nanoappStart(void)160 extern "C" bool nanoappStart(void) {
161 gInMethod = true;
162 void *ptr = chreHeapAlloc(15);
163 if (ptr == nullptr) {
164 // TODO(b/32326854): We're not able to send messages from
165 // nanoappStart(), so we just use chreLog() here, and make
166 // the user look through the logs to determine why this failed.
167 chreLog(CHRE_LOG_ERROR, "Unable to malloc in start");
168 return false;
169 }
170 gInstanceId = chreGetInstanceId();
171 if (gInstanceId == CHRE_INSTANCE_ID) {
172 chreLog(CHRE_LOG_ERROR, "Got bad instance ID in start");
173 return false;
174 }
175
176 // Send an event to ourself.
177 if (!chreSendEvent(kEventType, &gInstanceId, nullptr, gInstanceId)) {
178 chreLog(CHRE_LOG_ERROR, "Failed chreSendEvent in start");
179 return false;
180 }
181
182 // One shot timer that should trigger very quickly.
183 gTimerId = chreTimerSet(1, &gInstanceId, true);
184 if (gTimerId == CHRE_TIMER_INVALID) {
185 chreLog(CHRE_LOG_ERROR, "Failed chreTimerSet in start");
186 return false;
187 }
188
189 // We don't have a way to confirm the 'free' worked, we'll just look
190 // to see that we didn't crash. We intentionally move this 'free' to
191 // be not immediately after the 'alloc', and still before we're done
192 // calling other methods.
193 chreHeapFree(ptr);
194
195 // Confirm we can find and configure a sensor.
196 if (!chreSensorFindDefault(CHRE_SENSOR_TYPE_ACCELEROMETER,
197 &gSensorHandle)) {
198 chreLog(CHRE_LOG_ERROR, "Failed sensorFindDefault in start");
199 return false;
200 }
201 if (!chreSensorConfigure(gSensorHandle,
202 CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS,
203 CHRE_SENSOR_INTERVAL_DEFAULT,
204 CHRE_SENSOR_LATENCY_ASAP)) {
205 chreLog(CHRE_LOG_ERROR, "Failed sensorConfigure in start");
206 return false;
207 }
208
209 // TODO(b/32326854): Confirm we can send a message to the host.
210
211 gInMethod = false;
212 return true;
213 }
214
nanoappEnd(void)215 extern "C" void nanoappEnd(void) {
216 if (!chreSensorConfigureModeOnly(gSensorHandle,
217 CHRE_SENSOR_CONFIGURE_MODE_DONE)) {
218 sendFatalFailureToHost("Unable to configure sensor mode to DONE");
219 }
220
221 if (gInMethod) {
222 // This message won't be noticed by the host; but hopefully the
223 // fatal failure prevents a clean unload of the app and fails the test.
224 sendFatalFailureToHost("nanoappEnd called in reentrant manner");
225 }
226 }
227