• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #ifndef CHRE_SIMULATION_TEST_UTIL_H_
18 #define CHRE_SIMULATION_TEST_UTIL_H_
19 
20 #include <chre/nanoapp.h>
21 #include <cstdint>
22 
23 #include "chre/core/event_loop_manager.h"
24 #include "chre/core/nanoapp.h"
25 #include "chre/util/unique_ptr.h"
26 #include "test_event.h"
27 #include "test_event_queue.h"
28 
29 namespace chre {
30 
31 struct TestNanoapp;
32 
33 /**
34  * @return the statically loaded nanoapp based on the arguments.
35  *
36  * @see chreNslNanoappInfo for param descriptions.
37  */
38 UniquePtr<Nanoapp> createStaticNanoapp(
39     const char *name, uint64_t appId, uint32_t appVersion, uint32_t appPerms,
40     decltype(nanoappStart) *startFunc,
41     decltype(nanoappHandleEvent) *handleEventFunc,
42     decltype(nanoappEnd) *endFunc);
43 
44 /**
45  * @return the statically loaded nanoapp based on the arguments, additionally
46  * sets info struct version
47  *
48  * @see chreNslNanoappInfo for param descriptions.
49  */
50 UniquePtr<Nanoapp> createStaticNanoapp(
51     uint8_t infoStructVersion, const char *name, uint64_t appId,
52     uint32_t appVersion, uint32_t appPerms, decltype(nanoappStart) *startFunc,
53     decltype(nanoappHandleEvent) *handleEventFunc,
54     decltype(nanoappEnd) *endFunc);
55 
56 /**
57  * Deletes memory allocated by createStaticNanoapp.
58  *
59  * This function must be called when the nanoapp is no more used.
60  */
61 void deleteNanoappInfos();
62 
63 /**
64  * Default CHRE nanoapp entry points that don't do anything.
65  */
66 bool defaultNanoappStart();
67 void defaultNanoappHandleEvent(uint32_t senderInstanceId, uint16_t eventType,
68                                const void *eventData);
69 void defaultNanoappEnd();
70 
71 /**
72  * Create static nanoapp and load it in CHRE.
73  *
74  * This function returns after the nanoapp start has been executed.
75  *
76  * @see createStatic Nanoapp.
77  */
78 void loadNanoapp(const char *name, uint64_t appId, uint32_t appVersion,
79                  uint32_t appPerms, decltype(nanoappStart) *startFunc,
80                  decltype(nanoappHandleEvent) *handleEventFunc,
81                  decltype(nanoappEnd) *endFunc);
82 
83 /**
84  * Create a static nanoapp and load it in CHRE.
85  *
86  * This function returns after the nanoapp start has been executed.
87  *
88  * @return An instance of the TestNanoapp.
89  */
90 template <class Nanoapp>
loadNanoapp()91 Nanoapp loadNanoapp() {
92   static_assert(std::is_base_of<TestNanoapp, Nanoapp>::value);
93   Nanoapp app;
94   loadNanoapp(app.name, app.id, app.version, app.perms, app.start,
95               app.handleEvent, app.end);
96 
97   return app;
98 }
99 
100 /**
101  * Unload a test nanoapp.
102  *
103  * This function returns after the nanoapp end has been executed.
104  *
105  * @param app An instance of TestNanoapp.
106  */
107 template <class Nanoapp>
unloadNanoapp(Nanoapp app)108 void unloadNanoapp(Nanoapp app) {
109   static_assert(std::is_base_of<TestNanoapp, Nanoapp>::value);
110   unloadNanoapp(app.id);
111 }
112 
113 /**
114  * Unload nanoapp corresponding to appId.
115  *
116  * This function returns after the nanoapp end has been executed.
117  *
118  * @param appId App Id of nanoapp to be unloaded.
119  */
120 template <>
121 void unloadNanoapp<uint64_t>(uint64_t appId);
122 
123 /**
124  * A convenience deferred callback function that can be used to start an already
125  * loaded nanoapp.
126  *
127  * @param type The callback type.
128  * @param nanoapp A pointer to the nanoapp that is already loaded.
129  */
130 void testFinishLoadingNanoappCallback(SystemCallbackType type,
131                                       UniquePtr<Nanoapp> &&nanoapp);
132 
133 /**
134  * A convenience deferred callback function to unload a nanoapp.
135  *
136  * @param type The callback type.
137  * @param data The data containing the appId.
138  * @param extraData Extra data.
139  */
140 void testFinishUnloadingNanoappCallback(uint16_t type, void *data,
141                                         void *extraData);
142 
143 /**
144  * Test nanoapp.
145  *
146  * Tests typically inherit this struct to test the nanoapp behavior.
147  * The bulk of the code should be in the handleEvent closure to respond to
148  * events sent to the nanoapp by the platform and by the sendEventToNanoapp
149  * function. start and end can be use to setup and cleanup the test environment
150  * around each test.
151  *
152  * Note: end is only executed when the nanoapp is explicitly unloaded.
153  */
154 struct TestNanoapp {
155   const char *name = "Test";
156   uint64_t id = 0x0123456789abcdef;
157   uint32_t version = 0;
158   uint32_t perms = NanoappPermissions::CHRE_PERMS_NONE;
159 
decltypeTestNanoapp160   decltype(nanoappStart) *start = []() { return true; };
161 
decltypeTestNanoapp162   decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t,
163                                                  const void *) {};
164 
decltypeTestNanoapp165   decltype(nanoappEnd) *end = []() {};
166 };
167 
168 /**
169  * Deallocate the memory allocated for a TestEvent.
170  */
171 void freeTestEventDataCallback(uint16_t /*eventType*/, void *eventData);
172 
173 /**
174  * Sends a message to a nanoapp.
175  *
176  * This function is typically used to execute code in the context of the
177  * nanoapp in its handleEvent method.
178  *
179  * @param app An instance of TestNanoapp.
180  * @param eventType The event to send.
181  */
182 template <class Nanoapp>
sendEventToNanoapp(const Nanoapp & app,uint16_t eventType)183 void sendEventToNanoapp(const Nanoapp &app, uint16_t eventType) {
184   static_assert(std::is_base_of<TestNanoapp, Nanoapp>::value);
185   uint16_t instanceId;
186   if (EventLoopManagerSingleton::get()
187           ->getEventLoop()
188           .findNanoappInstanceIdByAppId(app.id, &instanceId)) {
189     auto event = memoryAlloc<TestEvent>();
190     ASSERT_NE(event, nullptr);
191     event->type = eventType;
192     EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
193         CHRE_EVENT_TEST_EVENT, static_cast<void *>(event),
194         freeTestEventDataCallback, instanceId);
195 
196   } else {
197     LOGE("No instance found for nanoapp id = 0x%016" PRIx64, app.id);
198   }
199 }
200 
201 /**
202  * Sends a message to a nanoapp with data.
203  *
204  * This function is typically used to execute code in the context of the
205  * nanoapp in its handleEvent method.
206  *
207  * The nanoapp handleEvent function will receive a a TestEvent instance
208  * populated with the eventType and a pointer to as copy of the evenData as
209  * a CHRE_EVENT_TEST_EVENT event.
210  *
211  * @param app An instance of TestNanoapp.
212  * @param eventType The event to send.
213  * @param eventData The data to send.
214  */
215 template <class Nanoapp, class T>
sendEventToNanoapp(const Nanoapp & app,uint16_t eventType,const T & eventData)216 void sendEventToNanoapp(const Nanoapp &app, uint16_t eventType,
217                         const T &eventData) {
218   static_assert(std::is_base_of<TestNanoapp, Nanoapp>::value);
219   static_assert(std::is_trivial<T>::value);
220   uint16_t instanceId;
221   if (EventLoopManagerSingleton::get()
222           ->getEventLoop()
223           .findNanoappInstanceIdByAppId(app.id, &instanceId)) {
224     auto event = memoryAlloc<TestEvent>();
225     ASSERT_NE(event, nullptr);
226     event->type = eventType;
227     auto ptr = memoryAlloc<T>();
228     ASSERT_NE(ptr, nullptr);
229     *ptr = eventData;
230     event->data = ptr;
231     EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
232         CHRE_EVENT_TEST_EVENT, static_cast<void *>(event),
233         freeTestEventDataCallback, instanceId);
234   } else {
235     LOGE("No instance found for nanoapp id = 0x%016" PRIx64, app.id);
236   }
237 }
238 
239 }  // namespace chre
240 
241 #endif  // CHRE_SIMULATION_TEST_UTIL_H_
242