blob: a6632f9b1f439bfe7f5622fc5a7d4901df9dfd2b [file] [log] [blame]
Brian Duddiee64f1802016-11-03 17:13:42 -07001/*
2 * Copyright (C) 2016 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#include "chre/core/nanoapp.h"
18
Brian Duddie9d5b5002017-03-22 16:13:24 -070019#include "chre/core/event_loop_manager.h"
Brian Duddiee64f1802016-11-03 17:13:42 -070020#include "chre/platform/assert.h"
Andrew Rossignol1b895c72016-12-21 17:41:14 -080021#include "chre/platform/fatal_error.h"
Brian Duddiee64f1802016-11-03 17:13:42 -070022#include "chre/platform/log.h"
Arthur Ishigurod0530f42017-06-16 13:26:37 -070023#include "chre/util/system/debug_dump.h"
Arthur Ishiguro82af7e92021-06-14 15:19:35 -070024#include "chre_api/chre/gnss.h"
Brian Duddiee8e5e7f2020-04-10 18:21:39 -070025#include "chre_api/chre/version.h"
Brian Duddiee64f1802016-11-03 17:13:42 -070026
Stan Rokitab3b6b822019-07-29 12:57:04 -070027#include <algorithm>
28
Arthur Ishiguro82af7e92021-06-14 15:19:35 -070029#if CHRE_FIRST_SUPPORTED_API_VERSION < CHRE_API_VERSION_1_5
30#define CHRE_GNSS_MEASUREMENT_BACK_COMPAT_ENABLED
31#endif
32
Brian Duddiee64f1802016-11-03 17:13:42 -070033namespace chre {
34
Stan Rokitaaed1e972019-08-08 14:05:33 -070035constexpr size_t Nanoapp::kMaxSizeWakeupBuckets;
36
Stan Rokita6e0d5ae2019-07-18 16:26:47 -070037Nanoapp::Nanoapp() {
38 // Push first bucket onto wakeup bucket queue
39 cycleWakeupBuckets(1);
40}
41
Anthony Stangefd7d4182019-04-05 14:29:48 -040042Nanoapp::~Nanoapp() {
karthik bharadwajfbf15452019-10-11 14:12:51 -070043 const size_t totalAllocatedBytes = getTotalAllocatedBytes();
44
45 if (totalAllocatedBytes > 0) {
46 // TODO: Consider asserting here
47 LOGE("Nanoapp ID=0x%016" PRIx64 " still has %zu allocated bytes!",
48 getAppId(), totalAllocatedBytes);
49 }
Anthony Stangefd7d4182019-04-05 14:29:48 -040050}
51
Anthony Stangedef6edb2021-04-13 21:53:42 +000052bool Nanoapp::isRegisteredForBroadcastEvent(uint16_t eventType,
53 uint16_t targetGroupIdMask) const {
54 bool registered = false;
55 size_t foundIndex = registrationIndex(eventType);
56 if (foundIndex < mRegisteredEvents.size()) {
57 const EventRegistration &reg = mRegisteredEvents[foundIndex];
58 if (targetGroupIdMask & reg.groupIdMask) {
59 registered = true;
60 }
61 }
62 return registered;
Brian Duddiee64f1802016-11-03 17:13:42 -070063}
64
Anthony Stangedef6edb2021-04-13 21:53:42 +000065void Nanoapp::registerForBroadcastEvent(uint16_t eventType,
66 uint16_t groupIdMask) {
67 size_t foundIndex = registrationIndex(eventType);
68 if (foundIndex < mRegisteredEvents.size()) {
69 mRegisteredEvents[foundIndex].groupIdMask |= groupIdMask;
70 } else if (!mRegisteredEvents.push_back(
71 EventRegistration(eventType, groupIdMask))) {
Andrew Rossignol0f2e64a2018-10-31 13:26:43 -070072 FATAL_ERROR_OOM();
Andrew Rossignol1b895c72016-12-21 17:41:14 -080073 }
Brian Duddiee64f1802016-11-03 17:13:42 -070074}
75
Anthony Stangedef6edb2021-04-13 21:53:42 +000076void Nanoapp::unregisterForBroadcastEvent(uint16_t eventType,
77 uint16_t groupIdMask) {
78 size_t foundIndex = registrationIndex(eventType);
79 if (foundIndex < mRegisteredEvents.size()) {
80 EventRegistration &reg = mRegisteredEvents[foundIndex];
81 reg.groupIdMask &= ~groupIdMask;
82 if (reg.groupIdMask == 0) {
83 mRegisteredEvents.erase(foundIndex);
84 }
Andrew Rossignol29b8ae82017-01-26 11:49:45 -080085 }
Andrew Rossignol29b8ae82017-01-26 11:49:45 -080086}
87
Andrew Rossignol6248f7a2017-05-01 16:24:06 -070088void Nanoapp::configureNanoappInfoEvents(bool enable) {
Andrew Rossignol6248f7a2017-05-01 16:24:06 -070089 if (enable) {
Brian Duddie33e9d2a2018-02-21 15:50:52 -080090 registerForBroadcastEvent(CHRE_EVENT_NANOAPP_STARTED);
91 registerForBroadcastEvent(CHRE_EVENT_NANOAPP_STOPPED);
Andrew Rossignol6248f7a2017-05-01 16:24:06 -070092 } else {
Brian Duddie33e9d2a2018-02-21 15:50:52 -080093 unregisterForBroadcastEvent(CHRE_EVENT_NANOAPP_STARTED);
94 unregisterForBroadcastEvent(CHRE_EVENT_NANOAPP_STOPPED);
Andrew Rossignol6248f7a2017-05-01 16:24:06 -070095 }
96}
97
Andrew Rossignolb3ef65f2017-11-17 11:33:40 -080098void Nanoapp::configureHostSleepEvents(bool enable) {
Andrew Rossignolb3ef65f2017-11-17 11:33:40 -080099 if (enable) {
Brian Duddie33e9d2a2018-02-21 15:50:52 -0800100 registerForBroadcastEvent(CHRE_EVENT_HOST_AWAKE);
101 registerForBroadcastEvent(CHRE_EVENT_HOST_ASLEEP);
Andrew Rossignolb3ef65f2017-11-17 11:33:40 -0800102 } else {
Brian Duddie33e9d2a2018-02-21 15:50:52 -0800103 unregisterForBroadcastEvent(CHRE_EVENT_HOST_AWAKE);
104 unregisterForBroadcastEvent(CHRE_EVENT_HOST_ASLEEP);
Andrew Rossignolb3ef65f2017-11-17 11:33:40 -0800105 }
106}
107
Meng-hsuan Chunga697f4e2020-03-09 16:46:58 -0700108void Nanoapp::configureDebugDumpEvent(bool enable) {
109 if (enable) {
110 registerForBroadcastEvent(CHRE_EVENT_DEBUG_DUMP);
111 } else {
112 unregisterForBroadcastEvent(CHRE_EVENT_DEBUG_DUMP);
113 }
114}
115
karthik bharadwajc1079502021-03-17 12:32:18 -0700116void Nanoapp::configureUserSettingEvent(uint8_t setting, bool enable) {
117 if (enable) {
118 registerForBroadcastEvent(CHRE_EVENT_SETTING_CHANGED_FIRST_EVENT + setting);
119 } else {
120 unregisterForBroadcastEvent(CHRE_EVENT_SETTING_CHANGED_FIRST_EVENT +
121 setting);
122 }
123}
124
Brian Duddiee64f1802016-11-03 17:13:42 -0700125Event *Nanoapp::processNextEvent() {
126 Event *event = mEventQueue.pop();
127
Brian Duddiea2f5add2017-03-19 18:47:19 -0700128 CHRE_ASSERT_LOG(event != nullptr, "Tried delivering event, but queue empty");
Brian Duddiee64f1802016-11-03 17:13:42 -0700129 if (event != nullptr) {
Arthur Ishiguro82af7e92021-06-14 15:19:35 -0700130 if (event->eventType == CHRE_EVENT_GNSS_DATA) {
131 handleGnssMeasurementDataEvent(event);
132 } else {
133 handleEvent(event->senderInstanceId, event->eventType, event->eventData);
134 }
Brian Duddiee64f1802016-11-03 17:13:42 -0700135 }
136
137 return event;
138}
139
Stan Rokita6e0d5ae2019-07-18 16:26:47 -0700140void Nanoapp::blameHostWakeup() {
Stan Rokitab3b6b822019-07-29 12:57:04 -0700141 if (mWakeupBuckets.back() < UINT16_MAX) ++mWakeupBuckets.back();
Stan Rokita6e0d5ae2019-07-18 16:26:47 -0700142}
143
144void Nanoapp::cycleWakeupBuckets(size_t numBuckets) {
Stan Rokitab3b6b822019-07-29 12:57:04 -0700145 numBuckets = std::min(numBuckets, kMaxSizeWakeupBuckets);
Stan Rokita6e0d5ae2019-07-18 16:26:47 -0700146 for (size_t i = 0; i < numBuckets; ++i) {
Stan Rokitab3b6b822019-07-29 12:57:04 -0700147 if (mWakeupBuckets.full()) {
148 mWakeupBuckets.erase(0);
149 }
150 mWakeupBuckets.push_back(0);
Stan Rokita6e0d5ae2019-07-18 16:26:47 -0700151 }
152}
153
Stan Rokitaaed1e972019-08-08 14:05:33 -0700154void Nanoapp::logStateToBuffer(DebugDumpWrapper &debugDump) const {
Brian Duddiee8e5e7f2020-04-10 18:21:39 -0700155 debugDump.print(" Id=%" PRIu32 " 0x%016" PRIx64 " ", getInstanceId(),
156 getAppId());
Stan Rokitaaed1e972019-08-08 14:05:33 -0700157 PlatformNanoapp::logStateToBuffer(debugDump);
Brian Duddiee8e5e7f2020-04-10 18:21:39 -0700158 debugDump.print(" v%" PRIu32 ".%" PRIu32 ".%" PRIu32 " tgtAPI=%" PRIu32
159 ".%" PRIu32 " curAlloc=%zu peakAlloc=%zu",
160 CHRE_EXTRACT_MAJOR_VERSION(getAppVersion()),
161 CHRE_EXTRACT_MINOR_VERSION(getAppVersion()),
162 CHRE_EXTRACT_PATCH_VERSION(getAppVersion()),
163 CHRE_EXTRACT_MAJOR_VERSION(getTargetApiVersion()),
164 CHRE_EXTRACT_MINOR_VERSION(getTargetApiVersion()),
165 getTotalAllocatedBytes(), getPeakAllocatedBytes());
166 debugDump.print(" hostWakeups=[ cur->");
Stan Rokita6e0d5ae2019-07-18 16:26:47 -0700167 // Get buckets latest -> earliest except last one
168 for (size_t i = mWakeupBuckets.size() - 1; i > 0; --i) {
Stan Rokitaaed1e972019-08-08 14:05:33 -0700169 debugDump.print("%" PRIu16 ", ", mWakeupBuckets[i]);
Stan Rokita6e0d5ae2019-07-18 16:26:47 -0700170 }
Brian Duddiee8e5e7f2020-04-10 18:21:39 -0700171 // Earliest bucket gets no comma
Stan Rokitaaed1e972019-08-08 14:05:33 -0700172 debugDump.print("%" PRIu16 " ]\n", mWakeupBuckets.front());
Arthur Ishigurod0530f42017-06-16 13:26:37 -0700173}
174
Anthony Stangeb346bb02021-02-12 15:44:18 +0000175bool Nanoapp::permitPermissionUse(uint32_t permission) const {
176 return !supportsAppPermissions() ||
177 ((getAppPermissions() & permission) == permission);
178}
179
Anthony Stangedef6edb2021-04-13 21:53:42 +0000180size_t Nanoapp::registrationIndex(uint16_t eventType) const {
181 size_t foundIndex = 0;
182 for (; foundIndex < mRegisteredEvents.size(); ++foundIndex) {
183 const EventRegistration &reg = mRegisteredEvents[foundIndex];
184 if (reg.eventType == eventType) {
185 break;
186 }
187 }
188 return foundIndex;
189}
190
Arthur Ishiguro82af7e92021-06-14 15:19:35 -0700191void Nanoapp::handleGnssMeasurementDataEvent(const Event *event) {
192#ifdef CHRE_GNSS_MEASUREMENT_BACK_COMPAT_ENABLED
193 const struct chreGnssDataEvent *data =
194 static_cast<const struct chreGnssDataEvent *>(event->eventData);
195 if (getTargetApiVersion() < CHRE_API_VERSION_1_5 &&
196 data->measurement_count > CHRE_GNSS_MAX_MEASUREMENT_PRE_1_5) {
197 chreGnssDataEvent localEvent;
198 memcpy(&localEvent, data, sizeof(struct chreGnssDataEvent));
199 localEvent.measurement_count = CHRE_GNSS_MAX_MEASUREMENT_PRE_1_5;
200 handleEvent(event->senderInstanceId, event->eventType, &localEvent);
201 } else
202#endif // CHRE_GNSS_MEASUREMENT_BACK_COMPAT_ENABLED
203 {
204 handleEvent(event->senderInstanceId, event->eventType, event->eventData);
205 }
206}
207
Brian Duddiee64f1802016-11-03 17:13:42 -0700208} // namespace chre