1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*84e33947SAndroid Build Coastguard Worker *
4*84e33947SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*84e33947SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*84e33947SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*84e33947SAndroid Build Coastguard Worker *
8*84e33947SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*84e33947SAndroid Build Coastguard Worker *
10*84e33947SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*84e33947SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*84e33947SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*84e33947SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*84e33947SAndroid Build Coastguard Worker * limitations under the License.
15*84e33947SAndroid Build Coastguard Worker */
16*84e33947SAndroid Build Coastguard Worker
17*84e33947SAndroid Build Coastguard Worker #include "chre/core/nanoapp.h"
18*84e33947SAndroid Build Coastguard Worker
19*84e33947SAndroid Build Coastguard Worker #include "chre/core/event_loop_manager.h"
20*84e33947SAndroid Build Coastguard Worker #include "chre/platform/assert.h"
21*84e33947SAndroid Build Coastguard Worker #include "chre/platform/fatal_error.h"
22*84e33947SAndroid Build Coastguard Worker #include "chre/platform/log.h"
23*84e33947SAndroid Build Coastguard Worker #include "chre/platform/tracing.h"
24*84e33947SAndroid Build Coastguard Worker #include "chre/util/system/debug_dump.h"
25*84e33947SAndroid Build Coastguard Worker #include "chre_api/chre/gnss.h"
26*84e33947SAndroid Build Coastguard Worker #include "chre_api/chre/version.h"
27*84e33947SAndroid Build Coastguard Worker
28*84e33947SAndroid Build Coastguard Worker #include <algorithm>
29*84e33947SAndroid Build Coastguard Worker #include <cstdint>
30*84e33947SAndroid Build Coastguard Worker
31*84e33947SAndroid Build Coastguard Worker #if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5
32*84e33947SAndroid Build Coastguard Worker #define CHRE_GNSS_MEASUREMENT_BACK_COMPAT_ENABLED
33*84e33947SAndroid Build Coastguard Worker #endif
34*84e33947SAndroid Build Coastguard Worker
35*84e33947SAndroid Build Coastguard Worker namespace chre {
36*84e33947SAndroid Build Coastguard Worker
37*84e33947SAndroid Build Coastguard Worker constexpr size_t Nanoapp::kMaxSizeWakeupBuckets;
38*84e33947SAndroid Build Coastguard Worker
Nanoapp()39*84e33947SAndroid Build Coastguard Worker Nanoapp::Nanoapp()
40*84e33947SAndroid Build Coastguard Worker : Nanoapp(EventLoopManagerSingleton::get()->getNextInstanceId()) {}
41*84e33947SAndroid Build Coastguard Worker
Nanoapp(uint16_t instanceId)42*84e33947SAndroid Build Coastguard Worker Nanoapp::Nanoapp(uint16_t instanceId) {
43*84e33947SAndroid Build Coastguard Worker // Push first bucket onto wakeup bucket queue
44*84e33947SAndroid Build Coastguard Worker cycleWakeupBuckets(SystemTime::getMonotonicTime());
45*84e33947SAndroid Build Coastguard Worker mInstanceId = instanceId;
46*84e33947SAndroid Build Coastguard Worker }
47*84e33947SAndroid Build Coastguard Worker
start()48*84e33947SAndroid Build Coastguard Worker bool Nanoapp::start() {
49*84e33947SAndroid Build Coastguard Worker // TODO(b/294116163): update trace with nanoapp instance id and nanoapp name
50*84e33947SAndroid Build Coastguard Worker CHRE_TRACE_INSTANT("Nanoapp start");
51*84e33947SAndroid Build Coastguard Worker mIsInNanoappStart = true;
52*84e33947SAndroid Build Coastguard Worker bool success = PlatformNanoapp::start();
53*84e33947SAndroid Build Coastguard Worker mIsInNanoappStart = false;
54*84e33947SAndroid Build Coastguard Worker return success;
55*84e33947SAndroid Build Coastguard Worker }
56*84e33947SAndroid Build Coastguard Worker
isRegisteredForBroadcastEvent(const Event * event) const57*84e33947SAndroid Build Coastguard Worker bool Nanoapp::isRegisteredForBroadcastEvent(const Event *event) const {
58*84e33947SAndroid Build Coastguard Worker bool registered = false;
59*84e33947SAndroid Build Coastguard Worker uint16_t eventType = event->eventType;
60*84e33947SAndroid Build Coastguard Worker uint16_t targetGroupIdMask = event->targetAppGroupMask;
61*84e33947SAndroid Build Coastguard Worker
62*84e33947SAndroid Build Coastguard Worker // The host endpoint notification is a special case, because it requires
63*84e33947SAndroid Build Coastguard Worker // explicit registration using host endpoint IDs rather than masks.
64*84e33947SAndroid Build Coastguard Worker if (eventType == CHRE_EVENT_HOST_ENDPOINT_NOTIFICATION) {
65*84e33947SAndroid Build Coastguard Worker const auto *data =
66*84e33947SAndroid Build Coastguard Worker static_cast<const chreHostEndpointNotification *>(event->eventData);
67*84e33947SAndroid Build Coastguard Worker registered = isRegisteredForHostEndpointNotifications(data->hostEndpointId);
68*84e33947SAndroid Build Coastguard Worker } else {
69*84e33947SAndroid Build Coastguard Worker size_t foundIndex = registrationIndex(eventType);
70*84e33947SAndroid Build Coastguard Worker if (foundIndex < mRegisteredEvents.size()) {
71*84e33947SAndroid Build Coastguard Worker const EventRegistration ® = mRegisteredEvents[foundIndex];
72*84e33947SAndroid Build Coastguard Worker if (targetGroupIdMask & reg.groupIdMask) {
73*84e33947SAndroid Build Coastguard Worker registered = true;
74*84e33947SAndroid Build Coastguard Worker }
75*84e33947SAndroid Build Coastguard Worker }
76*84e33947SAndroid Build Coastguard Worker }
77*84e33947SAndroid Build Coastguard Worker return registered;
78*84e33947SAndroid Build Coastguard Worker }
79*84e33947SAndroid Build Coastguard Worker
registerForBroadcastEvent(uint16_t eventType,uint16_t groupIdMask)80*84e33947SAndroid Build Coastguard Worker void Nanoapp::registerForBroadcastEvent(uint16_t eventType,
81*84e33947SAndroid Build Coastguard Worker uint16_t groupIdMask) {
82*84e33947SAndroid Build Coastguard Worker size_t foundIndex = registrationIndex(eventType);
83*84e33947SAndroid Build Coastguard Worker if (foundIndex < mRegisteredEvents.size()) {
84*84e33947SAndroid Build Coastguard Worker mRegisteredEvents[foundIndex].groupIdMask |= groupIdMask;
85*84e33947SAndroid Build Coastguard Worker } else if (!mRegisteredEvents.push_back(
86*84e33947SAndroid Build Coastguard Worker EventRegistration(eventType, groupIdMask))) {
87*84e33947SAndroid Build Coastguard Worker FATAL_ERROR_OOM();
88*84e33947SAndroid Build Coastguard Worker }
89*84e33947SAndroid Build Coastguard Worker }
90*84e33947SAndroid Build Coastguard Worker
unregisterForBroadcastEvent(uint16_t eventType,uint16_t groupIdMask)91*84e33947SAndroid Build Coastguard Worker void Nanoapp::unregisterForBroadcastEvent(uint16_t eventType,
92*84e33947SAndroid Build Coastguard Worker uint16_t groupIdMask) {
93*84e33947SAndroid Build Coastguard Worker size_t foundIndex = registrationIndex(eventType);
94*84e33947SAndroid Build Coastguard Worker if (foundIndex < mRegisteredEvents.size()) {
95*84e33947SAndroid Build Coastguard Worker EventRegistration ® = mRegisteredEvents[foundIndex];
96*84e33947SAndroid Build Coastguard Worker reg.groupIdMask &= ~groupIdMask;
97*84e33947SAndroid Build Coastguard Worker if (reg.groupIdMask == 0) {
98*84e33947SAndroid Build Coastguard Worker mRegisteredEvents.erase(foundIndex);
99*84e33947SAndroid Build Coastguard Worker }
100*84e33947SAndroid Build Coastguard Worker }
101*84e33947SAndroid Build Coastguard Worker }
102*84e33947SAndroid Build Coastguard Worker
configureNanoappInfoEvents(bool enable)103*84e33947SAndroid Build Coastguard Worker void Nanoapp::configureNanoappInfoEvents(bool enable) {
104*84e33947SAndroid Build Coastguard Worker if (enable) {
105*84e33947SAndroid Build Coastguard Worker registerForBroadcastEvent(CHRE_EVENT_NANOAPP_STARTED);
106*84e33947SAndroid Build Coastguard Worker registerForBroadcastEvent(CHRE_EVENT_NANOAPP_STOPPED);
107*84e33947SAndroid Build Coastguard Worker } else {
108*84e33947SAndroid Build Coastguard Worker unregisterForBroadcastEvent(CHRE_EVENT_NANOAPP_STARTED);
109*84e33947SAndroid Build Coastguard Worker unregisterForBroadcastEvent(CHRE_EVENT_NANOAPP_STOPPED);
110*84e33947SAndroid Build Coastguard Worker }
111*84e33947SAndroid Build Coastguard Worker }
112*84e33947SAndroid Build Coastguard Worker
configureHostSleepEvents(bool enable)113*84e33947SAndroid Build Coastguard Worker void Nanoapp::configureHostSleepEvents(bool enable) {
114*84e33947SAndroid Build Coastguard Worker if (enable) {
115*84e33947SAndroid Build Coastguard Worker registerForBroadcastEvent(CHRE_EVENT_HOST_AWAKE);
116*84e33947SAndroid Build Coastguard Worker registerForBroadcastEvent(CHRE_EVENT_HOST_ASLEEP);
117*84e33947SAndroid Build Coastguard Worker } else {
118*84e33947SAndroid Build Coastguard Worker unregisterForBroadcastEvent(CHRE_EVENT_HOST_AWAKE);
119*84e33947SAndroid Build Coastguard Worker unregisterForBroadcastEvent(CHRE_EVENT_HOST_ASLEEP);
120*84e33947SAndroid Build Coastguard Worker }
121*84e33947SAndroid Build Coastguard Worker }
122*84e33947SAndroid Build Coastguard Worker
configureDebugDumpEvent(bool enable)123*84e33947SAndroid Build Coastguard Worker void Nanoapp::configureDebugDumpEvent(bool enable) {
124*84e33947SAndroid Build Coastguard Worker if (enable) {
125*84e33947SAndroid Build Coastguard Worker registerForBroadcastEvent(CHRE_EVENT_DEBUG_DUMP);
126*84e33947SAndroid Build Coastguard Worker } else {
127*84e33947SAndroid Build Coastguard Worker unregisterForBroadcastEvent(CHRE_EVENT_DEBUG_DUMP);
128*84e33947SAndroid Build Coastguard Worker }
129*84e33947SAndroid Build Coastguard Worker }
130*84e33947SAndroid Build Coastguard Worker
configureUserSettingEvent(uint8_t setting,bool enable)131*84e33947SAndroid Build Coastguard Worker void Nanoapp::configureUserSettingEvent(uint8_t setting, bool enable) {
132*84e33947SAndroid Build Coastguard Worker if (enable) {
133*84e33947SAndroid Build Coastguard Worker registerForBroadcastEvent(CHRE_EVENT_SETTING_CHANGED_FIRST_EVENT + setting);
134*84e33947SAndroid Build Coastguard Worker } else {
135*84e33947SAndroid Build Coastguard Worker unregisterForBroadcastEvent(CHRE_EVENT_SETTING_CHANGED_FIRST_EVENT +
136*84e33947SAndroid Build Coastguard Worker setting);
137*84e33947SAndroid Build Coastguard Worker }
138*84e33947SAndroid Build Coastguard Worker }
139*84e33947SAndroid Build Coastguard Worker
processEvent(Event * event)140*84e33947SAndroid Build Coastguard Worker void Nanoapp::processEvent(Event *event) {
141*84e33947SAndroid Build Coastguard Worker Nanoseconds eventStartTime = SystemTime::getMonotonicTime();
142*84e33947SAndroid Build Coastguard Worker // TODO(b/294116163): update trace with event type and nanoapp name so it can
143*84e33947SAndroid Build Coastguard Worker // be differentiated from other events
144*84e33947SAndroid Build Coastguard Worker CHRE_TRACE_START("Handle event", "nanoapp", getInstanceId());
145*84e33947SAndroid Build Coastguard Worker if (event->eventType == CHRE_EVENT_GNSS_DATA) {
146*84e33947SAndroid Build Coastguard Worker handleGnssMeasurementDataEvent(event);
147*84e33947SAndroid Build Coastguard Worker } else {
148*84e33947SAndroid Build Coastguard Worker handleEvent(event->senderInstanceId, event->eventType, event->eventData);
149*84e33947SAndroid Build Coastguard Worker }
150*84e33947SAndroid Build Coastguard Worker // TODO(b/294116163): update trace with nanoapp name
151*84e33947SAndroid Build Coastguard Worker CHRE_TRACE_END("Handle event", "nanoapp", getInstanceId());
152*84e33947SAndroid Build Coastguard Worker Nanoseconds eventProcessTime =
153*84e33947SAndroid Build Coastguard Worker SystemTime::getMonotonicTime() - eventStartTime;
154*84e33947SAndroid Build Coastguard Worker uint64_t eventTimeMs = Milliseconds(eventProcessTime).getMilliseconds();
155*84e33947SAndroid Build Coastguard Worker if (Milliseconds(eventProcessTime) >= Milliseconds(100)) {
156*84e33947SAndroid Build Coastguard Worker LOGE("Nanoapp 0x%" PRIx64 " took %" PRIu64
157*84e33947SAndroid Build Coastguard Worker " ms to process event type 0x%" PRIx16,
158*84e33947SAndroid Build Coastguard Worker getAppId(), eventTimeMs, event->eventType);
159*84e33947SAndroid Build Coastguard Worker }
160*84e33947SAndroid Build Coastguard Worker mEventProcessTime.addValue(eventTimeMs);
161*84e33947SAndroid Build Coastguard Worker mEventProcessTimeSinceBoot += eventTimeMs;
162*84e33947SAndroid Build Coastguard Worker mWakeupBuckets.back().eventProcessTime += eventTimeMs;
163*84e33947SAndroid Build Coastguard Worker }
164*84e33947SAndroid Build Coastguard Worker
blameHostWakeup()165*84e33947SAndroid Build Coastguard Worker void Nanoapp::blameHostWakeup() {
166*84e33947SAndroid Build Coastguard Worker if (mWakeupBuckets.back().wakeupCount < UINT16_MAX) {
167*84e33947SAndroid Build Coastguard Worker ++mWakeupBuckets.back().wakeupCount;
168*84e33947SAndroid Build Coastguard Worker }
169*84e33947SAndroid Build Coastguard Worker if (mNumWakeupsSinceBoot < UINT32_MAX) ++mNumWakeupsSinceBoot;
170*84e33947SAndroid Build Coastguard Worker }
171*84e33947SAndroid Build Coastguard Worker
blameHostMessageSent()172*84e33947SAndroid Build Coastguard Worker void Nanoapp::blameHostMessageSent() {
173*84e33947SAndroid Build Coastguard Worker if (mWakeupBuckets.back().hostMessageCount < UINT16_MAX) {
174*84e33947SAndroid Build Coastguard Worker ++mWakeupBuckets.back().hostMessageCount;
175*84e33947SAndroid Build Coastguard Worker }
176*84e33947SAndroid Build Coastguard Worker if (mNumMessagesSentSinceBoot < UINT32_MAX) ++mNumMessagesSentSinceBoot;
177*84e33947SAndroid Build Coastguard Worker }
178*84e33947SAndroid Build Coastguard Worker
cycleWakeupBuckets(Nanoseconds timestamp)179*84e33947SAndroid Build Coastguard Worker void Nanoapp::cycleWakeupBuckets(Nanoseconds timestamp) {
180*84e33947SAndroid Build Coastguard Worker if (mWakeupBuckets.full()) {
181*84e33947SAndroid Build Coastguard Worker mWakeupBuckets.erase(0);
182*84e33947SAndroid Build Coastguard Worker }
183*84e33947SAndroid Build Coastguard Worker mWakeupBuckets.push_back(
184*84e33947SAndroid Build Coastguard Worker BucketedStats(0, 0, 0, timestamp.toRawNanoseconds()));
185*84e33947SAndroid Build Coastguard Worker }
186*84e33947SAndroid Build Coastguard Worker
logStateToBuffer(DebugDumpWrapper & debugDump) const187*84e33947SAndroid Build Coastguard Worker void Nanoapp::logStateToBuffer(DebugDumpWrapper &debugDump) const {
188*84e33947SAndroid Build Coastguard Worker debugDump.print(" Id=%" PRIu16 " 0x%016" PRIx64 " ", getInstanceId(),
189*84e33947SAndroid Build Coastguard Worker getAppId());
190*84e33947SAndroid Build Coastguard Worker PlatformNanoapp::logStateToBuffer(debugDump);
191*84e33947SAndroid Build Coastguard Worker debugDump.print(" v%" PRIu32 ".%" PRIu32 ".%" PRIu32 " tgtAPI=%" PRIu32
192*84e33947SAndroid Build Coastguard Worker ".%" PRIu32 "\n",
193*84e33947SAndroid Build Coastguard Worker CHRE_EXTRACT_MAJOR_VERSION(getAppVersion()),
194*84e33947SAndroid Build Coastguard Worker CHRE_EXTRACT_MINOR_VERSION(getAppVersion()),
195*84e33947SAndroid Build Coastguard Worker CHRE_EXTRACT_PATCH_VERSION(getAppVersion()),
196*84e33947SAndroid Build Coastguard Worker CHRE_EXTRACT_MAJOR_VERSION(getTargetApiVersion()),
197*84e33947SAndroid Build Coastguard Worker CHRE_EXTRACT_MINOR_VERSION(getTargetApiVersion()));
198*84e33947SAndroid Build Coastguard Worker }
199*84e33947SAndroid Build Coastguard Worker
logMemAndComputeHeader(DebugDumpWrapper & debugDump) const200*84e33947SAndroid Build Coastguard Worker void Nanoapp::logMemAndComputeHeader(DebugDumpWrapper &debugDump) const {
201*84e33947SAndroid Build Coastguard Worker // Print table header
202*84e33947SAndroid Build Coastguard Worker // Nanoapp column sized to accommodate largest known name
203*84e33947SAndroid Build Coastguard Worker debugDump.print("\n%10sNanoapp%9s| Mem Alloc (Bytes) |%2sEvent Time (Ms)\n",
204*84e33947SAndroid Build Coastguard Worker "", "", "");
205*84e33947SAndroid Build Coastguard Worker debugDump.print("%26s| Current | Max | Max | Total\n", "");
206*84e33947SAndroid Build Coastguard Worker }
207*84e33947SAndroid Build Coastguard Worker
logMemAndComputeEntry(DebugDumpWrapper & debugDump) const208*84e33947SAndroid Build Coastguard Worker void Nanoapp::logMemAndComputeEntry(DebugDumpWrapper &debugDump) const {
209*84e33947SAndroid Build Coastguard Worker debugDump.print("%25s |", getAppName());
210*84e33947SAndroid Build Coastguard Worker debugDump.print(" %7zu |", getTotalAllocatedBytes());
211*84e33947SAndroid Build Coastguard Worker debugDump.print(" %7zu |", getPeakAllocatedBytes());
212*84e33947SAndroid Build Coastguard Worker debugDump.print(" %7" PRIu64 " |", mEventProcessTime.getMax());
213*84e33947SAndroid Build Coastguard Worker debugDump.print(" %7" PRIu64 "\n", mEventProcessTimeSinceBoot);
214*84e33947SAndroid Build Coastguard Worker }
215*84e33947SAndroid Build Coastguard Worker
logMessageHistoryHeader(DebugDumpWrapper & debugDump) const216*84e33947SAndroid Build Coastguard Worker void Nanoapp::logMessageHistoryHeader(DebugDumpWrapper &debugDump) const {
217*84e33947SAndroid Build Coastguard Worker // Print time ranges for buckets
218*84e33947SAndroid Build Coastguard Worker Nanoseconds now = SystemTime::getMonotonicTime();
219*84e33947SAndroid Build Coastguard Worker uint64_t currentTimeMins = 0;
220*84e33947SAndroid Build Coastguard Worker uint64_t nextTimeMins = 0;
221*84e33947SAndroid Build Coastguard Worker uint64_t nanosecondsSince = 0;
222*84e33947SAndroid Build Coastguard Worker char bucketLabel = 'A';
223*84e33947SAndroid Build Coastguard Worker
224*84e33947SAndroid Build Coastguard Worker char bucketTags[kMaxSizeWakeupBuckets][4];
225*84e33947SAndroid Build Coastguard Worker for (int32_t i = kMaxSizeWakeupBuckets - 1; i >= 0; --i) {
226*84e33947SAndroid Build Coastguard Worker bucketTags[i][0] = '[';
227*84e33947SAndroid Build Coastguard Worker bucketTags[i][1] = bucketLabel++;
228*84e33947SAndroid Build Coastguard Worker bucketTags[i][2] = ']';
229*84e33947SAndroid Build Coastguard Worker bucketTags[i][3] = '\0';
230*84e33947SAndroid Build Coastguard Worker }
231*84e33947SAndroid Build Coastguard Worker
232*84e33947SAndroid Build Coastguard Worker debugDump.print(
233*84e33947SAndroid Build Coastguard Worker "\nHistogram stat buckets cover the following time ranges:\n");
234*84e33947SAndroid Build Coastguard Worker
235*84e33947SAndroid Build Coastguard Worker for (int32_t i = kMaxSizeWakeupBuckets - 1;
236*84e33947SAndroid Build Coastguard Worker i > static_cast<int32_t>(mWakeupBuckets.size() - 1); --i) {
237*84e33947SAndroid Build Coastguard Worker debugDump.print(" Bucket%s: N/A (unused)\n", bucketTags[i]);
238*84e33947SAndroid Build Coastguard Worker }
239*84e33947SAndroid Build Coastguard Worker
240*84e33947SAndroid Build Coastguard Worker for (int32_t i = static_cast<int32_t>(mWakeupBuckets.size() - 1); i >= 0;
241*84e33947SAndroid Build Coastguard Worker --i) {
242*84e33947SAndroid Build Coastguard Worker size_t idx = static_cast<size_t>(i);
243*84e33947SAndroid Build Coastguard Worker nanosecondsSince =
244*84e33947SAndroid Build Coastguard Worker now.toRawNanoseconds() - mWakeupBuckets[idx].creationTimestamp;
245*84e33947SAndroid Build Coastguard Worker currentTimeMins = (nanosecondsSince / kOneMinuteInNanoseconds);
246*84e33947SAndroid Build Coastguard Worker
247*84e33947SAndroid Build Coastguard Worker debugDump.print(" Bucket%s:", bucketTags[idx]);
248*84e33947SAndroid Build Coastguard Worker debugDump.print(" %3" PRIu64 "", nextTimeMins);
249*84e33947SAndroid Build Coastguard Worker debugDump.print(" - %3" PRIu64 " mins ago\n", currentTimeMins);
250*84e33947SAndroid Build Coastguard Worker nextTimeMins = currentTimeMins;
251*84e33947SAndroid Build Coastguard Worker }
252*84e33947SAndroid Build Coastguard Worker
253*84e33947SAndroid Build Coastguard Worker // Precompute column widths for Wakeup Histogram, Message Histogram, and Event
254*84e33947SAndroid Build Coastguard Worker // Time Histogram (ms). This allows the column width to be known and optimized
255*84e33947SAndroid Build Coastguard Worker // at compile time, and avoids use of inconsistently supported "%*" in printf
256*84e33947SAndroid Build Coastguard Worker //
257*84e33947SAndroid Build Coastguard Worker // A static_assert is used to ensure these calculations are updated whenever
258*84e33947SAndroid Build Coastguard Worker // the value of kMaxSizeWakeupBuckets changes
259*84e33947SAndroid Build Coastguard Worker static_assert(kMaxSizeWakeupBuckets == 5,
260*84e33947SAndroid Build Coastguard Worker "Update of nanoapp debug dump column widths requrired");
261*84e33947SAndroid Build Coastguard Worker
262*84e33947SAndroid Build Coastguard Worker // Print table header
263*84e33947SAndroid Build Coastguard Worker debugDump.print("\n%26s|", " Nanoapp ");
264*84e33947SAndroid Build Coastguard Worker debugDump.print("%11s|", " Total w/u ");
265*84e33947SAndroid Build Coastguard Worker // Wakeup Histogram = 2 + (4 * kMaxSizeWakeupBuckets);
266*84e33947SAndroid Build Coastguard Worker debugDump.print("%22s|", " Wakeup Histogram ");
267*84e33947SAndroid Build Coastguard Worker debugDump.print("%12s|", " Total Msgs ");
268*84e33947SAndroid Build Coastguard Worker // Message Histogram = 2 + (4 * kMaxSizeWakeupBuckets);
269*84e33947SAndroid Build Coastguard Worker debugDump.print("%22s|", " Message Histogram ");
270*84e33947SAndroid Build Coastguard Worker debugDump.print("%12s|", " Event Time ");
271*84e33947SAndroid Build Coastguard Worker // Event Time Histogram (ms) = 2 + (7 * kMaxSizeWakeupBuckets);
272*84e33947SAndroid Build Coastguard Worker debugDump.print("%37s", " Event Time Histogram (ms) ");
273*84e33947SAndroid Build Coastguard Worker
274*84e33947SAndroid Build Coastguard Worker debugDump.print("\n%26s|%11s|", "", "");
275*84e33947SAndroid Build Coastguard Worker for (int32_t i = kMaxSizeWakeupBuckets - 1; i >= 0; --i) {
276*84e33947SAndroid Build Coastguard Worker debugDump.print(" %3s", bucketTags[i]);
277*84e33947SAndroid Build Coastguard Worker }
278*84e33947SAndroid Build Coastguard Worker debugDump.print(" |%12s|", "");
279*84e33947SAndroid Build Coastguard Worker for (int32_t i = kMaxSizeWakeupBuckets - 1; i >= 0; --i) {
280*84e33947SAndroid Build Coastguard Worker debugDump.print(" %3s", bucketTags[i]);
281*84e33947SAndroid Build Coastguard Worker }
282*84e33947SAndroid Build Coastguard Worker debugDump.print(" |%12s|", "");
283*84e33947SAndroid Build Coastguard Worker for (int32_t i = kMaxSizeWakeupBuckets - 1; i >= 0; --i) {
284*84e33947SAndroid Build Coastguard Worker debugDump.print(" %7s", bucketTags[i]);
285*84e33947SAndroid Build Coastguard Worker }
286*84e33947SAndroid Build Coastguard Worker debugDump.print("\n");
287*84e33947SAndroid Build Coastguard Worker }
288*84e33947SAndroid Build Coastguard Worker
logMessageHistoryEntry(DebugDumpWrapper & debugDump) const289*84e33947SAndroid Build Coastguard Worker void Nanoapp::logMessageHistoryEntry(DebugDumpWrapper &debugDump) const {
290*84e33947SAndroid Build Coastguard Worker debugDump.print("%25s |", getAppName());
291*84e33947SAndroid Build Coastguard Worker
292*84e33947SAndroid Build Coastguard Worker // Print wakeupCount and histogram
293*84e33947SAndroid Build Coastguard Worker debugDump.print(" %9" PRIu32 " | ", mNumWakeupsSinceBoot);
294*84e33947SAndroid Build Coastguard Worker for (size_t i = kMaxSizeWakeupBuckets - 1; i > 0; --i) {
295*84e33947SAndroid Build Coastguard Worker if (i >= mWakeupBuckets.size()) {
296*84e33947SAndroid Build Coastguard Worker debugDump.print(" --,");
297*84e33947SAndroid Build Coastguard Worker } else {
298*84e33947SAndroid Build Coastguard Worker debugDump.print(" %2" PRIu16 ",", mWakeupBuckets[i].wakeupCount);
299*84e33947SAndroid Build Coastguard Worker }
300*84e33947SAndroid Build Coastguard Worker }
301*84e33947SAndroid Build Coastguard Worker debugDump.print(" %2" PRIu16 " |", mWakeupBuckets.front().wakeupCount);
302*84e33947SAndroid Build Coastguard Worker
303*84e33947SAndroid Build Coastguard Worker // Print hostMessage count and histogram
304*84e33947SAndroid Build Coastguard Worker debugDump.print(" %10" PRIu32 " | ", mNumMessagesSentSinceBoot);
305*84e33947SAndroid Build Coastguard Worker for (size_t i = kMaxSizeWakeupBuckets - 1; i > 0; --i) {
306*84e33947SAndroid Build Coastguard Worker if (i >= mWakeupBuckets.size()) {
307*84e33947SAndroid Build Coastguard Worker debugDump.print(" --,");
308*84e33947SAndroid Build Coastguard Worker } else {
309*84e33947SAndroid Build Coastguard Worker debugDump.print(" %2" PRIu16 ",", mWakeupBuckets[i].hostMessageCount);
310*84e33947SAndroid Build Coastguard Worker }
311*84e33947SAndroid Build Coastguard Worker }
312*84e33947SAndroid Build Coastguard Worker debugDump.print(" %2" PRIu16 " |", mWakeupBuckets.front().hostMessageCount);
313*84e33947SAndroid Build Coastguard Worker
314*84e33947SAndroid Build Coastguard Worker // Print eventProcessingTime count and histogram
315*84e33947SAndroid Build Coastguard Worker debugDump.print(" %10" PRIu64 " | ", mEventProcessTimeSinceBoot);
316*84e33947SAndroid Build Coastguard Worker for (size_t i = kMaxSizeWakeupBuckets - 1; i > 0; --i) {
317*84e33947SAndroid Build Coastguard Worker if (i >= mWakeupBuckets.size()) {
318*84e33947SAndroid Build Coastguard Worker debugDump.print(" --,");
319*84e33947SAndroid Build Coastguard Worker } else {
320*84e33947SAndroid Build Coastguard Worker debugDump.print(" %6" PRIu64 ",", mWakeupBuckets[i].eventProcessTime);
321*84e33947SAndroid Build Coastguard Worker }
322*84e33947SAndroid Build Coastguard Worker }
323*84e33947SAndroid Build Coastguard Worker debugDump.print(" %6" PRIu64 "\n", mWakeupBuckets.front().eventProcessTime);
324*84e33947SAndroid Build Coastguard Worker }
325*84e33947SAndroid Build Coastguard Worker
permitPermissionUse(uint32_t permission) const326*84e33947SAndroid Build Coastguard Worker bool Nanoapp::permitPermissionUse(uint32_t permission) const {
327*84e33947SAndroid Build Coastguard Worker return !supportsAppPermissions() ||
328*84e33947SAndroid Build Coastguard Worker ((getAppPermissions() & permission) == permission);
329*84e33947SAndroid Build Coastguard Worker }
330*84e33947SAndroid Build Coastguard Worker
registrationIndex(uint16_t eventType) const331*84e33947SAndroid Build Coastguard Worker size_t Nanoapp::registrationIndex(uint16_t eventType) const {
332*84e33947SAndroid Build Coastguard Worker size_t foundIndex = 0;
333*84e33947SAndroid Build Coastguard Worker for (; foundIndex < mRegisteredEvents.size(); ++foundIndex) {
334*84e33947SAndroid Build Coastguard Worker const EventRegistration ® = mRegisteredEvents[foundIndex];
335*84e33947SAndroid Build Coastguard Worker if (reg.eventType == eventType) {
336*84e33947SAndroid Build Coastguard Worker break;
337*84e33947SAndroid Build Coastguard Worker }
338*84e33947SAndroid Build Coastguard Worker }
339*84e33947SAndroid Build Coastguard Worker return foundIndex;
340*84e33947SAndroid Build Coastguard Worker }
341*84e33947SAndroid Build Coastguard Worker
handleGnssMeasurementDataEvent(const Event * event)342*84e33947SAndroid Build Coastguard Worker void Nanoapp::handleGnssMeasurementDataEvent(const Event *event) {
343*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_GNSS_MEASUREMENT_BACK_COMPAT_ENABLED
344*84e33947SAndroid Build Coastguard Worker const struct chreGnssDataEvent *data =
345*84e33947SAndroid Build Coastguard Worker static_cast<const struct chreGnssDataEvent *>(event->eventData);
346*84e33947SAndroid Build Coastguard Worker if (getTargetApiVersion() < CHRE_API_VERSION_1_5 &&
347*84e33947SAndroid Build Coastguard Worker data->measurement_count > CHRE_GNSS_MAX_MEASUREMENT_PRE_1_5) {
348*84e33947SAndroid Build Coastguard Worker chreGnssDataEvent localEvent;
349*84e33947SAndroid Build Coastguard Worker memcpy(&localEvent, data, sizeof(struct chreGnssDataEvent));
350*84e33947SAndroid Build Coastguard Worker localEvent.measurement_count = CHRE_GNSS_MAX_MEASUREMENT_PRE_1_5;
351*84e33947SAndroid Build Coastguard Worker handleEvent(event->senderInstanceId, event->eventType, &localEvent);
352*84e33947SAndroid Build Coastguard Worker } else
353*84e33947SAndroid Build Coastguard Worker #endif // CHRE_GNSS_MEASUREMENT_BACK_COMPAT_ENABLED
354*84e33947SAndroid Build Coastguard Worker {
355*84e33947SAndroid Build Coastguard Worker handleEvent(event->senderInstanceId, event->eventType, event->eventData);
356*84e33947SAndroid Build Coastguard Worker }
357*84e33947SAndroid Build Coastguard Worker }
358*84e33947SAndroid Build Coastguard Worker
configureHostEndpointNotifications(uint16_t hostEndpointId,bool enable)359*84e33947SAndroid Build Coastguard Worker bool Nanoapp::configureHostEndpointNotifications(uint16_t hostEndpointId,
360*84e33947SAndroid Build Coastguard Worker bool enable) {
361*84e33947SAndroid Build Coastguard Worker bool success = true;
362*84e33947SAndroid Build Coastguard Worker bool registered = isRegisteredForHostEndpointNotifications(hostEndpointId);
363*84e33947SAndroid Build Coastguard Worker if (enable && !registered) {
364*84e33947SAndroid Build Coastguard Worker success = mRegisteredHostEndpoints.push_back(hostEndpointId);
365*84e33947SAndroid Build Coastguard Worker if (!success) {
366*84e33947SAndroid Build Coastguard Worker LOG_OOM();
367*84e33947SAndroid Build Coastguard Worker }
368*84e33947SAndroid Build Coastguard Worker } else if (!enable && registered) {
369*84e33947SAndroid Build Coastguard Worker size_t index = mRegisteredHostEndpoints.find(hostEndpointId);
370*84e33947SAndroid Build Coastguard Worker mRegisteredHostEndpoints.erase(index);
371*84e33947SAndroid Build Coastguard Worker }
372*84e33947SAndroid Build Coastguard Worker
373*84e33947SAndroid Build Coastguard Worker return success;
374*84e33947SAndroid Build Coastguard Worker }
375*84e33947SAndroid Build Coastguard Worker
publishRpcServices(struct chreNanoappRpcService * services,size_t numServices)376*84e33947SAndroid Build Coastguard Worker bool Nanoapp::publishRpcServices(struct chreNanoappRpcService *services,
377*84e33947SAndroid Build Coastguard Worker size_t numServices) {
378*84e33947SAndroid Build Coastguard Worker if (!mIsInNanoappStart) {
379*84e33947SAndroid Build Coastguard Worker LOGE("publishRpcServices must be called from nanoappStart");
380*84e33947SAndroid Build Coastguard Worker return false;
381*84e33947SAndroid Build Coastguard Worker }
382*84e33947SAndroid Build Coastguard Worker
383*84e33947SAndroid Build Coastguard Worker const size_t startSize = mRpcServices.size();
384*84e33947SAndroid Build Coastguard Worker const size_t endSize = startSize + numServices;
385*84e33947SAndroid Build Coastguard Worker if (endSize > kMaxRpcServices) {
386*84e33947SAndroid Build Coastguard Worker return false;
387*84e33947SAndroid Build Coastguard Worker }
388*84e33947SAndroid Build Coastguard Worker
389*84e33947SAndroid Build Coastguard Worker mRpcServices.reserve(endSize);
390*84e33947SAndroid Build Coastguard Worker
391*84e33947SAndroid Build Coastguard Worker bool success = true;
392*84e33947SAndroid Build Coastguard Worker
393*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < numServices; i++) {
394*84e33947SAndroid Build Coastguard Worker if (!mRpcServices.push_back(services[i])) {
395*84e33947SAndroid Build Coastguard Worker LOG_OOM();
396*84e33947SAndroid Build Coastguard Worker success = false;
397*84e33947SAndroid Build Coastguard Worker break;
398*84e33947SAndroid Build Coastguard Worker }
399*84e33947SAndroid Build Coastguard Worker }
400*84e33947SAndroid Build Coastguard Worker
401*84e33947SAndroid Build Coastguard Worker if (success && mRpcServices.size() > 1) {
402*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < mRpcServices.size() - 1; i++) {
403*84e33947SAndroid Build Coastguard Worker for (size_t j = i + 1; j < mRpcServices.size(); j++) {
404*84e33947SAndroid Build Coastguard Worker if (mRpcServices[i].id == mRpcServices[j].id) {
405*84e33947SAndroid Build Coastguard Worker LOGE("Service id = 0x%016" PRIx64 " can only be published once",
406*84e33947SAndroid Build Coastguard Worker mRpcServices[i].id);
407*84e33947SAndroid Build Coastguard Worker success = false;
408*84e33947SAndroid Build Coastguard Worker }
409*84e33947SAndroid Build Coastguard Worker }
410*84e33947SAndroid Build Coastguard Worker }
411*84e33947SAndroid Build Coastguard Worker }
412*84e33947SAndroid Build Coastguard Worker
413*84e33947SAndroid Build Coastguard Worker if (!success) {
414*84e33947SAndroid Build Coastguard Worker mRpcServices.resize(startSize);
415*84e33947SAndroid Build Coastguard Worker }
416*84e33947SAndroid Build Coastguard Worker
417*84e33947SAndroid Build Coastguard Worker return success;
418*84e33947SAndroid Build Coastguard Worker }
419*84e33947SAndroid Build Coastguard Worker
linkHeapBlock(HeapBlockHeader * header)420*84e33947SAndroid Build Coastguard Worker void Nanoapp::linkHeapBlock(HeapBlockHeader *header) {
421*84e33947SAndroid Build Coastguard Worker header->data.next = mFirstHeader;
422*84e33947SAndroid Build Coastguard Worker mFirstHeader = header;
423*84e33947SAndroid Build Coastguard Worker }
424*84e33947SAndroid Build Coastguard Worker
unlinkHeapBlock(HeapBlockHeader * header)425*84e33947SAndroid Build Coastguard Worker void Nanoapp::unlinkHeapBlock(HeapBlockHeader *header) {
426*84e33947SAndroid Build Coastguard Worker if (mFirstHeader == nullptr) {
427*84e33947SAndroid Build Coastguard Worker // The list is empty.
428*84e33947SAndroid Build Coastguard Worker return;
429*84e33947SAndroid Build Coastguard Worker }
430*84e33947SAndroid Build Coastguard Worker
431*84e33947SAndroid Build Coastguard Worker if (header == mFirstHeader) {
432*84e33947SAndroid Build Coastguard Worker mFirstHeader = header->data.next;
433*84e33947SAndroid Build Coastguard Worker return;
434*84e33947SAndroid Build Coastguard Worker }
435*84e33947SAndroid Build Coastguard Worker
436*84e33947SAndroid Build Coastguard Worker HeapBlockHeader *previous = mFirstHeader;
437*84e33947SAndroid Build Coastguard Worker HeapBlockHeader *current = mFirstHeader->data.next;
438*84e33947SAndroid Build Coastguard Worker
439*84e33947SAndroid Build Coastguard Worker while (current != nullptr) {
440*84e33947SAndroid Build Coastguard Worker if (current == header) {
441*84e33947SAndroid Build Coastguard Worker previous->data.next = current->data.next;
442*84e33947SAndroid Build Coastguard Worker break;
443*84e33947SAndroid Build Coastguard Worker }
444*84e33947SAndroid Build Coastguard Worker previous = current;
445*84e33947SAndroid Build Coastguard Worker current = current->data.next;
446*84e33947SAndroid Build Coastguard Worker }
447*84e33947SAndroid Build Coastguard Worker }
448*84e33947SAndroid Build Coastguard Worker
449*84e33947SAndroid Build Coastguard Worker } // namespace chre
450