• 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 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