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