• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 consistency check that
23  * calling 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 chreSendMessageToHostEndpoint() [**]
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/util/nanoapp/log.h>
48 
49 #include <shared/macros.h>
50 #include <shared/send_message.h>
51 #include <shared/test_success_marker.h>
52 #include <shared/time_util.h>
53 #include "chre_api/chre.h"
54 
55 #define LOG_TAG "[BusyStartup]"
56 
57 using nanoapp_testing::MessageType;
58 
59 using nanoapp_testing::sendMessageToHost;
60 using nanoapp_testing::sendSuccessToHost;
61 using nanoapp_testing::TestSuccessMarker;
62 
63 static bool gInMethod = false;
64 static uint32_t gInstanceId;
65 static uint32_t gTimerId;
66 static uint32_t gSensorHandle;
67 
68 /**
69  * Busy startup stages and total number of stages.
70  */
71 enum BusyStartupStage {
72   BUSY_STARTUP_STAGE_SELF_EVENT = 0,
73   BUSY_STARTUP_STAGE_TIMER,
74   BUSY_STARTUP_STAGE_SENSOR,
75   BUSY_STARTUP_STAGE_COUNT,
76 };
77 
78 //! TestSuccessMarker object to mark success of a stage.
79 TestSuccessMarker gTestSuccessMarker =
80     TestSuccessMarker(BUSY_STARTUP_STAGE_COUNT);
81 
82 constexpr uint16_t kEventType = CHRE_EVENT_FIRST_USER_VALUE;
83 
checkSelfEvent(uint16_t eventType,const uint32_t * eventData)84 static void checkSelfEvent(uint16_t eventType, const uint32_t *eventData) {
85   if (eventType != kEventType) {
86     uint32_t e = eventType;
87     EXPECT_FAIL_RETURN("Event from self, bad event type:", &e);
88   }
89   if (eventData == nullptr) {
90     EXPECT_FAIL_RETURN("Event from self, null data");
91   }
92   if (*eventData != gInstanceId) {
93     EXPECT_FAIL_RETURN("Event from self, bad data:", eventData);
94   }
95   gTestSuccessMarker.markStageAndSuccessOnFinish(BUSY_STARTUP_STAGE_SELF_EVENT);
96 }
97 
checkTimerEvent(const uint32_t * eventData)98 static void checkTimerEvent(const uint32_t *eventData) {
99   if (eventData == nullptr) {
100     EXPECT_FAIL_RETURN("TimerEvent, null data");
101   }
102   if (*eventData != gInstanceId) {
103     EXPECT_FAIL_RETURN("TimerEvent, bad data:", eventData);
104   }
105   gTestSuccessMarker.markStageAndSuccessOnFinish(BUSY_STARTUP_STAGE_TIMER);
106 }
107 
checkSensorEvent(const void * eventData)108 static void checkSensorEvent(const void *eventData) {
109   const chreSensorDataHeader *header =
110       static_cast<const chreSensorDataHeader *>(eventData);
111   if (header == nullptr) {
112     EXPECT_FAIL_RETURN("sensorEvent, null data");
113   }
114   if (header->sensorHandle != gSensorHandle) {
115     EXPECT_FAIL_RETURN("sensorEvent for wrong handle", &header->sensorHandle);
116   }
117   if (header->readingCount == 0) {
118     EXPECT_FAIL_RETURN("sensorEvent has readingCount of 0");
119   }
120   if (header->reserved != 0) {
121     EXPECT_FAIL_RETURN("sensorEvent has non-zero reserved field");
122   }
123 
124   if (chreGetApiVersion() < CHRE_API_VERSION_1_3) {
125     if (header->accuracy != 0) {
126       EXPECT_FAIL_RETURN("sensorEvent has non-zero reserved field");
127     }
128   } else if (header->accuracy > CHRE_SENSOR_ACCURACY_HIGH) {
129     EXPECT_FAIL_RETURN_UINT8("Sensor accuracy is not within valid range: ",
130                              header->accuracy);
131   }
132 
133   gTestSuccessMarker.markStageAndSuccessOnFinish(BUSY_STARTUP_STAGE_SENSOR);
134 }
135 
nanoappHandleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)136 extern "C" void nanoappHandleEvent(uint32_t senderInstanceId,
137                                    uint16_t eventType, const void *eventData) {
138   if (gInMethod) {
139     EXPECT_FAIL_RETURN("CHRE reentered nanoapp");
140   }
141   gInMethod = true;
142   const uint32_t *intData = static_cast<const uint32_t *>(eventData);
143   if (senderInstanceId == gInstanceId) {
144     checkSelfEvent(eventType, intData);
145 
146   } else if (senderInstanceId == CHRE_INSTANCE_ID) {
147     if (eventType == CHRE_EVENT_TIMER) {
148       checkTimerEvent(intData);
149     } else if (eventType == CHRE_EVENT_SENSOR_ACCELEROMETER_DATA) {
150       checkSensorEvent(eventData);
151     } else if (eventType == CHRE_EVENT_SENSOR_SAMPLING_CHANGE ||
152                eventType == CHRE_EVENT_SENSOR_ACCELEROMETER_BIAS_INFO) {
153       // This could have been generated when we configured the
154       // sensor.  We just ignore it.
155     } else {
156       uint32_t e = eventType;
157       EXPECT_FAIL_RETURN("Unexpected event from CHRE:", &e);
158     }
159   } else {
160     EXPECT_FAIL_RETURN("Unexpected senderInstanceId", &senderInstanceId);
161   }
162   gInMethod = false;
163 }
164 
nanoappStart(void)165 extern "C" bool nanoappStart(void) {
166   gInMethod = true;
167   void *ptr = chreHeapAlloc(15);
168   if (ptr == nullptr) {
169     // TODO(b/32326854): We're not able to send messages from
170     //     nanoappStart(), so we just use LOGE() here, and make
171     //     the user look through the logs to determine why this failed.
172     LOGE("Unable to malloc in start");
173     return false;
174   }
175   gInstanceId = chreGetInstanceId();
176   if (gInstanceId == CHRE_INSTANCE_ID) {
177     LOGE("Got bad instance ID in start");
178     return false;
179   }
180 
181   // Send an event to ourself.
182   if (!chreSendEvent(kEventType, &gInstanceId, nullptr, gInstanceId)) {
183     LOGE("Failed chreSendEvent in start");
184     return false;
185   }
186 
187   // One shot timer that should trigger very quickly.
188   gTimerId = chreTimerSet(1, &gInstanceId, true);
189   if (gTimerId == CHRE_TIMER_INVALID) {
190     LOGE("Failed chreTimerSet in start");
191     return false;
192   }
193 
194   // We don't have a way to confirm the 'free' worked, we'll just look
195   // to see that we didn't crash.  We intentionally move this 'free' to
196   // be not immediately after the 'alloc', and still before we're done
197   // calling other methods.
198   chreHeapFree(ptr);
199 
200   // Confirm we can find and configure a sensor.
201   if (!chreSensorFindDefault(CHRE_SENSOR_TYPE_ACCELEROMETER, &gSensorHandle)) {
202     LOGE("Failed sensorFindDefault in start");
203     return false;
204   }
205 
206   // Configure accel request at 50 Hz (reasonable rate, e.g. for AR)
207   // TODO: Add a way to find the range of possible sample rates
208   if (!chreSensorConfigure(gSensorHandle, CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS,
209                            20 * nanoapp_testing::kOneMillisecondInNanoseconds,
210                            CHRE_SENSOR_LATENCY_ASAP)) {
211     LOGE("Failed sensorConfigure in start");
212     return false;
213   }
214 
215   // TODO(b/32326854): Confirm we can send a message to the host.
216 
217   gInMethod = false;
218   return true;
219 }
220 
nanoappEnd(void)221 extern "C" void nanoappEnd(void) {
222   if (!chreSensorConfigureModeOnly(gSensorHandle,
223                                    CHRE_SENSOR_CONFIGURE_MODE_DONE)) {
224     EXPECT_FAIL_RETURN("Unable to configure sensor mode to DONE");
225   }
226 
227   if (gInMethod) {
228     // This message won't be noticed by the host; but hopefully the
229     // fatal failure prevents a clean unload of the app and fails the test.
230     EXPECT_FAIL_RETURN("nanoappEnd called in reentrant manner");
231   }
232 }
233