1 /*
2  * Copyright (C) 2016 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 <general_test/send_message_to_host_test.h>
18 
19 #include <cinttypes>
20 #include <cstddef>
21 
22 #include <shared/nano_endian.h>
23 #include <shared/nano_string.h>
24 #include <shared/send_message.h>
25 
26 #include <chre/util/nanoapp/log.h>
27 #include "chre/util/toolchain.h"
28 
29 #include "chre_api/chre.h"
30 
31 #define LOG_TAG "[SendMessageToHostTest]"
32 
33 using nanoapp_testing::MessageType;
34 using nanoapp_testing::sendFatalFailureToHost;
35 using nanoapp_testing::sendInternalFailureToHost;
36 using nanoapp_testing::sendSuccessToHost;
37 
38 /*
39  * Our test essentially has nine stages.  The first eight stages all involve
40  * sending data to the Host.  Here is a table describing them:
41  *
42  * Stage | Data length | Callback
43  * ------|-------------|--------------
44  * 0     | small       | smallMessage0
45  * 1     | small       | smallMessage1
46  * 2     | small       | nullptr
47  * 3     | small       | smallMessage0
48  * 4     | nullptr     | nullptr
49  * 5     | 4 bytes     | nullptr
50  * 6     | MAX + 1     | largeMessage
51  * 7     | MAX         | largeMessage
52  *
53  * Stage 8 involves waiting for an incoming zero-sized message from the Host.
54  *
55  * The focus of the first four stages is making sure the correct callback
56  * gets invoked and a nullptr callback works.
57  *
58  * Stage 4 tests sending a null message to the Host (that should send).
59  *
60  * Stage 5 is not testing anything, but it's necessary to get data
61  * to the host to confirm the message in stage 7 is correct.
62  *
63  * Stage 6 tests that we properly reject oversized messages.  This
64  * data should _not_ make it to the host.
65  *
66  * Stage 7 tests that we can send the maximum claimed size to the host.
67  *
68  * Every single stage which has a non-null callback is not considered a
69  * "success" until that callback has been invoked.  There is no CHRE
70  * requirement in terms of the order in which these callbacks are
71  * invoked, which is why the markSuccess() method uses a bitmask and
72  * checks for overall success every time we gets success from a single
73  * stage.
74  *
75  * We consider the test successful only when all stages have reported success.
76  * Note that the Host will not perform Stage 8 until after it has received
77  * all the expected messages from the nanoapp.  That's how we can confirm
78  * all messages actually made it through to the Host.
79  */
80 
81 // TODO(b/32114261): Remove this and actually test a variety of message types.
82 constexpr uint32_t kUntestedMessageType = UINT32_C(0x51501984);
83 
84 namespace general_test {
85 
86 // TODO(b/32114261): Remove this variable.
87 extern bool gUseNycMessageHack;
88 
89 uint8_t SendMessageToHostTest::sSmallMessageData[kSmallMessageTestCount]
90                                                 [kSmallMessageSize];
91 void *SendMessageToHostTest::sLargeMessageData[2];
92 
93 bool SendMessageToHostTest::sInMethod = false;
94 uint32_t SendMessageToHostTest::sFinishedBitmask = 0;
95 
96 template <uint8_t kCallbackIndex>
smallMessageCallback(void * message,size_t messageSize)97 void SendMessageToHostTest::smallMessageCallback(void *message,
98                                                  size_t messageSize) {
99   if (sInMethod) {
100     sendFatalFailureToHost(
101         "smallMessageCallback called while another nanoapp method is running");
102   }
103   sInMethod = true;
104   if (message == nullptr) {
105     sendFatalFailureToHost("smallMessageCallback given null message");
106   }
107   if (messageSize != kSmallMessageSize) {
108     uint32_t size = static_cast<uint32_t>(messageSize);
109     sendFatalFailureToHost("smallMessageCallback given bad messageSize:",
110                            &size);
111   }
112   const uint8_t *msg = static_cast<const uint8_t *>(message);
113   for (size_t i = 0; i < messageSize; i++) {
114     if (msg[i] != kDataByte) {
115       sendFatalFailureToHost("Corrupt data in smallMessageCallback");
116     }
117   }
118 
119   uint32_t stage = getSmallDataIndex(msg);
120   uint8_t expectedCallbackIndex = 2;
121   switch (stage) {
122     case 0:  // fall-through
123     case 3:
124       expectedCallbackIndex = 0;
125       break;
126     case 1:
127       expectedCallbackIndex = 1;
128       break;
129     case 2:
130       sendFatalFailureToHost("callback invoked when null callback given");
131       break;
132     default:
133       sendInternalFailureToHost("Invalid index", &stage);
134   }
135   if (expectedCallbackIndex != kCallbackIndex) {
136     sendFatalFailureToHost("Incorrect callback function called.");
137   }
138 
139   markSuccess(stage);
140   sInMethod = false;
141 }
142 
smallMessageCallback0(void * message,size_t messageSize)143 void SendMessageToHostTest::smallMessageCallback0(void *message,
144                                                   size_t messageSize) {
145   smallMessageCallback<0>(message, messageSize);
146 }
147 
smallMessageCallback1(void * message,size_t messageSize)148 void SendMessageToHostTest::smallMessageCallback1(void *message,
149                                                   size_t messageSize) {
150   smallMessageCallback<1>(message, messageSize);
151 }
152 
getSmallDataIndex(const uint8_t * data)153 uint32_t SendMessageToHostTest::getSmallDataIndex(const uint8_t *data) {
154   // O(N) is fine.  N is small and this is test code.
155   for (uint32_t i = 0; i < kSmallMessageTestCount; i++) {
156     if (data == sSmallMessageData[i]) {
157       return i;
158     }
159   }
160   sendFatalFailureToHost("Bad memory sent to smallMessageCallback");
161   // We should never get here.
162   return kSmallMessageTestCount;
163 }
164 
largeMessageCallback(void * message,size_t messageSize)165 void SendMessageToHostTest::largeMessageCallback(void *message,
166                                                  size_t messageSize) {
167   if (sInMethod) {
168     sendFatalFailureToHost(
169         "largeMessageCallback called while another nanoapp method is running");
170   }
171   sInMethod = true;
172   if (message == nullptr) {
173     sendFatalFailureToHost("largeMessageCallback given null message");
174   }
175   uint32_t index = 2;
176   if (message == sLargeMessageData[0]) {
177     index = 0;
178   } else if (message == sLargeMessageData[1]) {
179     index = 1;
180   } else {
181     sendFatalFailureToHost("largeMessageCallback given bad message");
182   }
183 
184   size_t expectedMessageSize = index == 0 ? chreGetMessageToHostMaxSize() + 1
185                                           : chreGetMessageToHostMaxSize();
186   if (messageSize != expectedMessageSize) {
187     sendFatalFailureToHost("largeMessageCallback given incorrect messageSize");
188   }
189   const uint8_t *msg = static_cast<const uint8_t *>(message);
190   for (size_t i = 0; i < messageSize; i++) {
191     if (msg[i] != kDataByte) {
192       sendFatalFailureToHost("Corrupt data in largeMessageCallback");
193     }
194   }
195   chreHeapFree(sLargeMessageData[index]);
196   // index 0 == stage 6, index 1 == stage 7
197   markSuccess(index + 6);
198 
199   sInMethod = false;
200 }
201 
markSuccess(uint32_t stage)202 void SendMessageToHostTest::markSuccess(uint32_t stage) {
203   LOGD("Stage %" PRIu32 " succeeded", stage);
204   uint32_t finishedBit = (1 << stage);
205   if (sFinishedBitmask & finishedBit) {
206     sendFatalFailureToHost("callback called multiple times for stage:", &stage);
207   }
208   if ((kAllFinished & finishedBit) == 0) {
209     sendFatalFailureToHost("markSuccess bad stage", &stage);
210   }
211   sFinishedBitmask |= finishedBit;
212   if (sFinishedBitmask == kAllFinished) {
213     sendSuccessToHost();
214   }
215 }
216 
prepTestMemory()217 void SendMessageToHostTest::prepTestMemory() {
218   nanoapp_testing::memset(sSmallMessageData, kDataByte,
219                           sizeof(sSmallMessageData));
220 
221   for (size_t i = 0; i < 2; i++) {
222     size_t messageSize = i == 0 ? chreGetMessageToHostMaxSize() + 1
223                                 : chreGetMessageToHostMaxSize();
224     sLargeMessageData[i] = chreHeapAlloc(messageSize);
225     if (sLargeMessageData[i] == nullptr) {
226       sendFatalFailureToHost("Insufficient heap memory for test");
227     }
228     nanoapp_testing::memset(sLargeMessageData[i], kDataByte, messageSize);
229   }
230 }
231 
sendMessageMaxSize()232 void SendMessageToHostTest::sendMessageMaxSize() {
233   // Our focus here is just sending this data; we're not trying to
234   // test anything.  So we use the helper function.
235   uint32_t maxSize = nanoapp_testing::hostToLittleEndian(
236       static_cast<uint32_t>(chreGetMessageToHostMaxSize()));
237   // TODO(b/32114261): We intentionally don't have a namespace using
238   //     declaration for sendMessageToHost because it's generally
239   //     incorrect to use while we're working around this bug.  When the
240   //     bug is fixed, we'll add this declaration, and use the method
241   //     widely.
242   nanoapp_testing::sendMessageToHost(MessageType::kContinue, &maxSize,
243                                      sizeof(maxSize));
244 }
245 
246 // Wrapper for chreSendMessageToHost() that sets sInMethod to false during its
247 // execution, to allow for inline callbacks (this CHRE API is allowed to call
248 // the free callback either within the function, or at an unspecified later time
249 // when this nanoapp is not otherwise executing).
sendMessageToHost(void * message,uint32_t messageSize,uint32_t reservedMessageType,chreMessageFreeFunction * freeCallback)250 bool SendMessageToHostTest::sendMessageToHost(
251     void *message, uint32_t messageSize, uint32_t reservedMessageType,
252     chreMessageFreeFunction *freeCallback) {
253   sInMethod = false;
254 
255   // Disable deprecation warnings
256   CHRE_DEPRECATED_PREAMBLE
257   bool success = chreSendMessageToHost(message, messageSize,
258                                        reservedMessageType, freeCallback);
259   // Enable deprecation warnings
260   CHRE_DEPRECATED_EPILOGUE
261 
262   sInMethod = true;
263 
264   return success;
265 }
266 
SendMessageToHostTest()267 SendMessageToHostTest::SendMessageToHostTest() : Test(CHRE_API_VERSION_1_10) {}
268 
setUp(uint32_t messageSize,const void *)269 void SendMessageToHostTest::setUp(uint32_t messageSize,
270                                   const void * /* message */) {
271   // TODO(b/32114261): We need this hackery so we can get the raw bytes
272   //     from the host, without the test infrastructure trying to
273   //     interpret them.  This won't be necessary when messageType is
274   //     properly sent.
275   gUseNycMessageHack = false;
276 
277   sInMethod = true;
278   if (messageSize != 0) {
279     sendFatalFailureToHost(
280         "SendMessageToHost message expects 0 additional bytes, got ",
281         &messageSize);
282   }
283 
284   prepTestMemory();
285 
286   // stage: 0
287   if (!sendMessageToHost(sSmallMessageData[0], kSmallMessageSize,
288                          kUntestedMessageType, smallMessageCallback0)) {
289     sendFatalFailureToHost("Failed chreSendMessageToHost stage 0");
290   }
291 
292   // stage: 1
293   if (!sendMessageToHost(sSmallMessageData[1], kSmallMessageSize,
294                          kUntestedMessageType, smallMessageCallback1)) {
295     sendFatalFailureToHost("Failed chreSendMessageToHost stage 1");
296   }
297 
298   // stage: 2
299   if (!sendMessageToHost(sSmallMessageData[2], kSmallMessageSize,
300                          kUntestedMessageType, nullptr)) {
301     sendFatalFailureToHost("Failed chreSendMessageToHost stage 2");
302   }
303   // There's no callback, so we mark this as a success.
304   markSuccess(2);
305 
306   // stage: 3
307   if (!sendMessageToHost(sSmallMessageData[3], kSmallMessageSize,
308                          kUntestedMessageType, smallMessageCallback0)) {
309     sendFatalFailureToHost("Failed chreSendMessageToHost stage 3");
310   }
311 
312   // stage: 4
313   if (!sendMessageToHost(nullptr, 0, kUntestedMessageType, nullptr)) {
314     sendFatalFailureToHost("Failed chreSendMessageToHost stage 4");
315   }
316   // There's no callback, so we mark this as a success.
317   markSuccess(4);
318 
319   // stage: 5
320   sendMessageMaxSize();
321   // There's no callback, so we mark this as a success.
322   markSuccess(5);
323 
324   // stage: 6
325   if (sendMessageToHost(sLargeMessageData[0], chreGetMessageToHostMaxSize() + 1,
326                         kUntestedMessageType, largeMessageCallback)) {
327     sendFatalFailureToHost(
328         "Oversized data to chreSendMessageToHost claimed success");
329   }
330 
331   // stage: 7
332   if (!sendMessageToHost(sLargeMessageData[1], chreGetMessageToHostMaxSize(),
333                          kUntestedMessageType, largeMessageCallback)) {
334     sendFatalFailureToHost("Failed chreSendMessageToHost stage 7");
335   }
336 
337   sInMethod = false;
338 }
339 
handleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)340 void SendMessageToHostTest::handleEvent(uint32_t senderInstanceId,
341                                         uint16_t eventType,
342                                         const void *eventData) {
343   if (sInMethod) {
344     sendFatalFailureToHost(
345         "handleEvent invoked while another nanoapp method is running");
346   }
347   sInMethod = true;
348 
349   // TODO(b/32114261): Use getMessageDataFromHostEvent().  We can't do
350   //     that now because our messageType is probably wrong.
351   if (senderInstanceId != CHRE_INSTANCE_ID) {
352     sendFatalFailureToHost("handleEvent got event from unexpected sender:",
353                            &senderInstanceId);
354   }
355   if (eventType != CHRE_EVENT_MESSAGE_FROM_HOST) {
356     unexpectedEvent(eventType);
357   }
358 
359   auto dataStruct = static_cast<const chreMessageFromHostData *>(eventData);
360   // TODO(b/32114261): Test the message type.
361   if (dataStruct->messageSize != 0) {
362     sendFatalFailureToHost("handleEvent got non-zero message size",
363                            &dataStruct->messageSize);
364   }
365   // We don't test dataStruct->message.  We don't require this to be
366   // nullptr.  If a CHRE chooses to deal in 0-sized memory blocks, that's
367   // acceptable.
368 
369   // Stage 8 was successful.  Note that other stages might still be waiting
370   // for freeCallbacks.  So we don't send success to the host, but just
371   // mark our stage as a success.
372   markSuccess(8);
373 
374   sInMethod = false;
375 }
376 
377 }  // namespace general_test
378