xref: /aosp_15_r20/system/chre/platform/slpi/host_link.cc (revision 84e339476a462649f82315436d70fd732297a399)
1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker  * Copyright (C) 2017 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 #ifndef FARF_MEDIUM
18*84e33947SAndroid Build Coastguard Worker #define FARF_MEDIUM 1
19*84e33947SAndroid Build Coastguard Worker #endif
20*84e33947SAndroid Build Coastguard Worker 
21*84e33947SAndroid Build Coastguard Worker #include "HAP_farf.h"
22*84e33947SAndroid Build Coastguard Worker #include "timer.h"
23*84e33947SAndroid Build Coastguard Worker 
24*84e33947SAndroid Build Coastguard Worker #include "chre/core/event_loop_manager.h"
25*84e33947SAndroid Build Coastguard Worker #include "chre/core/host_comms_manager.h"
26*84e33947SAndroid Build Coastguard Worker #include "chre/core/settings.h"
27*84e33947SAndroid Build Coastguard Worker #include "chre/platform/fatal_error.h"
28*84e33947SAndroid Build Coastguard Worker #include "chre/platform/log.h"
29*84e33947SAndroid Build Coastguard Worker #include "chre/platform/memory.h"
30*84e33947SAndroid Build Coastguard Worker #include "chre/platform/shared/host_protocol_chre.h"
31*84e33947SAndroid Build Coastguard Worker #include "chre/platform/shared/nanoapp_load_manager.h"
32*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_USE_BUFFERED_LOGGING
33*84e33947SAndroid Build Coastguard Worker #include "chre/platform/shared/log_buffer_manager.h"
34*84e33947SAndroid Build Coastguard Worker #endif
35*84e33947SAndroid Build Coastguard Worker #include "chre/platform/slpi/fastrpc.h"
36*84e33947SAndroid Build Coastguard Worker #include "chre/platform/slpi/power_control_util.h"
37*84e33947SAndroid Build Coastguard Worker #include "chre/platform/system_time.h"
38*84e33947SAndroid Build Coastguard Worker #include "chre/platform/system_timer.h"
39*84e33947SAndroid Build Coastguard Worker #include "chre/util/flatbuffers/helpers.h"
40*84e33947SAndroid Build Coastguard Worker #include "chre/util/macros.h"
41*84e33947SAndroid Build Coastguard Worker #include "chre/util/nested_data_ptr.h"
42*84e33947SAndroid Build Coastguard Worker #include "chre/util/system/fixed_size_blocking_queue.h"
43*84e33947SAndroid Build Coastguard Worker #include "chre/util/unique_ptr.h"
44*84e33947SAndroid Build Coastguard Worker #include "chre_api/chre/version.h"
45*84e33947SAndroid Build Coastguard Worker 
46*84e33947SAndroid Build Coastguard Worker #include <inttypes.h>
47*84e33947SAndroid Build Coastguard Worker #include <limits.h>
48*84e33947SAndroid Build Coastguard Worker 
49*84e33947SAndroid Build Coastguard Worker namespace chre {
50*84e33947SAndroid Build Coastguard Worker 
51*84e33947SAndroid Build Coastguard Worker namespace {
52*84e33947SAndroid Build Coastguard Worker 
53*84e33947SAndroid Build Coastguard Worker constexpr size_t kOutboundQueueSize = 32;
54*84e33947SAndroid Build Coastguard Worker 
55*84e33947SAndroid Build Coastguard Worker //! The last time a time sync request message has been sent.
56*84e33947SAndroid Build Coastguard Worker //! TODO: Make this a member of HostLinkBase
57*84e33947SAndroid Build Coastguard Worker Nanoseconds gLastTimeSyncRequestNanos(0);
58*84e33947SAndroid Build Coastguard Worker 
59*84e33947SAndroid Build Coastguard Worker struct NanoappListData {
60*84e33947SAndroid Build Coastguard Worker   ChreFlatBufferBuilder *builder;
61*84e33947SAndroid Build Coastguard Worker   DynamicVector<NanoappListEntryOffset> nanoappEntries;
62*84e33947SAndroid Build Coastguard Worker   uint16_t hostClientId;
63*84e33947SAndroid Build Coastguard Worker };
64*84e33947SAndroid Build Coastguard Worker 
65*84e33947SAndroid Build Coastguard Worker enum class PendingMessageType {
66*84e33947SAndroid Build Coastguard Worker   Shutdown,
67*84e33947SAndroid Build Coastguard Worker   NanoappMessageToHost,
68*84e33947SAndroid Build Coastguard Worker   HubInfoResponse,
69*84e33947SAndroid Build Coastguard Worker   NanoappListResponse,
70*84e33947SAndroid Build Coastguard Worker   LoadNanoappResponse,
71*84e33947SAndroid Build Coastguard Worker   UnloadNanoappResponse,
72*84e33947SAndroid Build Coastguard Worker   DebugDumpData,
73*84e33947SAndroid Build Coastguard Worker   DebugDumpResponse,
74*84e33947SAndroid Build Coastguard Worker   TimeSyncRequest,
75*84e33947SAndroid Build Coastguard Worker   LowPowerMicAccessRequest,
76*84e33947SAndroid Build Coastguard Worker   LowPowerMicAccessRelease,
77*84e33947SAndroid Build Coastguard Worker   EncodedLogMessage,
78*84e33947SAndroid Build Coastguard Worker   SelfTestResponse,
79*84e33947SAndroid Build Coastguard Worker   MetricLog,
80*84e33947SAndroid Build Coastguard Worker   NanConfigurationRequest,
81*84e33947SAndroid Build Coastguard Worker };
82*84e33947SAndroid Build Coastguard Worker 
83*84e33947SAndroid Build Coastguard Worker struct PendingMessage {
PendingMessagechre::__anon98ca9eb40111::PendingMessage84*84e33947SAndroid Build Coastguard Worker   PendingMessage(PendingMessageType msgType, uint16_t hostClientId) {
85*84e33947SAndroid Build Coastguard Worker     type = msgType;
86*84e33947SAndroid Build Coastguard Worker     data.hostClientId = hostClientId;
87*84e33947SAndroid Build Coastguard Worker   }
88*84e33947SAndroid Build Coastguard Worker 
PendingMessagechre::__anon98ca9eb40111::PendingMessage89*84e33947SAndroid Build Coastguard Worker   PendingMessage(PendingMessageType msgType,
90*84e33947SAndroid Build Coastguard Worker                  const MessageToHost *msgToHost = nullptr) {
91*84e33947SAndroid Build Coastguard Worker     type = msgType;
92*84e33947SAndroid Build Coastguard Worker     data.msgToHost = msgToHost;
93*84e33947SAndroid Build Coastguard Worker   }
94*84e33947SAndroid Build Coastguard Worker 
PendingMessagechre::__anon98ca9eb40111::PendingMessage95*84e33947SAndroid Build Coastguard Worker   PendingMessage(PendingMessageType msgType, ChreFlatBufferBuilder *builder) {
96*84e33947SAndroid Build Coastguard Worker     type = msgType;
97*84e33947SAndroid Build Coastguard Worker     data.builder = builder;
98*84e33947SAndroid Build Coastguard Worker   }
99*84e33947SAndroid Build Coastguard Worker 
100*84e33947SAndroid Build Coastguard Worker   PendingMessageType type;
101*84e33947SAndroid Build Coastguard Worker   union {
102*84e33947SAndroid Build Coastguard Worker     const MessageToHost *msgToHost;
103*84e33947SAndroid Build Coastguard Worker     uint16_t hostClientId;
104*84e33947SAndroid Build Coastguard Worker     ChreFlatBufferBuilder *builder;
105*84e33947SAndroid Build Coastguard Worker   } data;
106*84e33947SAndroid Build Coastguard Worker };
107*84e33947SAndroid Build Coastguard Worker 
108*84e33947SAndroid Build Coastguard Worker struct UnloadNanoappCallbackData {
109*84e33947SAndroid Build Coastguard Worker   uint64_t appId;
110*84e33947SAndroid Build Coastguard Worker   uint32_t transactionId;
111*84e33947SAndroid Build Coastguard Worker   uint16_t hostClientId;
112*84e33947SAndroid Build Coastguard Worker   bool allowSystemNanoappUnload;
113*84e33947SAndroid Build Coastguard Worker };
114*84e33947SAndroid Build Coastguard Worker 
115*84e33947SAndroid Build Coastguard Worker /**
116*84e33947SAndroid Build Coastguard Worker  * @see buildAndEnqueueMessage()
117*84e33947SAndroid Build Coastguard Worker  */
118*84e33947SAndroid Build Coastguard Worker typedef void(MessageBuilderFunction)(ChreFlatBufferBuilder &builder,
119*84e33947SAndroid Build Coastguard Worker                                      void *cookie);
120*84e33947SAndroid Build Coastguard Worker 
121*84e33947SAndroid Build Coastguard Worker FixedSizeBlockingQueue<PendingMessage, kOutboundQueueSize> gOutboundQueue;
122*84e33947SAndroid Build Coastguard Worker 
copyToHostBuffer(const ChreFlatBufferBuilder & builder,unsigned char * buffer,size_t bufferSize,unsigned int * messageLen)123*84e33947SAndroid Build Coastguard Worker int copyToHostBuffer(const ChreFlatBufferBuilder &builder,
124*84e33947SAndroid Build Coastguard Worker                      unsigned char *buffer, size_t bufferSize,
125*84e33947SAndroid Build Coastguard Worker                      unsigned int *messageLen) {
126*84e33947SAndroid Build Coastguard Worker   uint8_t *data = builder.GetBufferPointer();
127*84e33947SAndroid Build Coastguard Worker   size_t size = builder.GetSize();
128*84e33947SAndroid Build Coastguard Worker   int result;
129*84e33947SAndroid Build Coastguard Worker 
130*84e33947SAndroid Build Coastguard Worker   if (size > bufferSize) {
131*84e33947SAndroid Build Coastguard Worker     LOGE("Encoded structure size %zu too big for host buffer %zu; dropping",
132*84e33947SAndroid Build Coastguard Worker          size, bufferSize);
133*84e33947SAndroid Build Coastguard Worker     result = CHRE_FASTRPC_ERROR;
134*84e33947SAndroid Build Coastguard Worker   } else {
135*84e33947SAndroid Build Coastguard Worker     memcpy(buffer, data, size);
136*84e33947SAndroid Build Coastguard Worker     *messageLen = size;
137*84e33947SAndroid Build Coastguard Worker     result = CHRE_FASTRPC_SUCCESS;
138*84e33947SAndroid Build Coastguard Worker   }
139*84e33947SAndroid Build Coastguard Worker 
140*84e33947SAndroid Build Coastguard Worker   return result;
141*84e33947SAndroid Build Coastguard Worker }
142*84e33947SAndroid Build Coastguard Worker 
143*84e33947SAndroid Build Coastguard Worker /**
144*84e33947SAndroid Build Coastguard Worker  * Wrapper function to enqueue a message on the outbound message queue. All
145*84e33947SAndroid Build Coastguard Worker  * outgoing message to the host must be called through this function.
146*84e33947SAndroid Build Coastguard Worker  *
147*84e33947SAndroid Build Coastguard Worker  * @param message The message to send to host.
148*84e33947SAndroid Build Coastguard Worker  *
149*84e33947SAndroid Build Coastguard Worker  * @return true if the message was successfully added to the queue.
150*84e33947SAndroid Build Coastguard Worker  */
enqueueMessage(PendingMessage message)151*84e33947SAndroid Build Coastguard Worker bool enqueueMessage(PendingMessage message) {
152*84e33947SAndroid Build Coastguard Worker   // Vote for big image temporarily when waking up the main thread waiting for
153*84e33947SAndroid Build Coastguard Worker   // the message
154*84e33947SAndroid Build Coastguard Worker   bool voteSuccess = slpiForceBigImage();
155*84e33947SAndroid Build Coastguard Worker   bool success = gOutboundQueue.push(message);
156*84e33947SAndroid Build Coastguard Worker 
157*84e33947SAndroid Build Coastguard Worker   // Remove the vote only if we successfully made a big image transition
158*84e33947SAndroid Build Coastguard Worker   if (voteSuccess) {
159*84e33947SAndroid Build Coastguard Worker     slpiRemoveBigImageVote();
160*84e33947SAndroid Build Coastguard Worker   }
161*84e33947SAndroid Build Coastguard Worker 
162*84e33947SAndroid Build Coastguard Worker   return success;
163*84e33947SAndroid Build Coastguard Worker }
164*84e33947SAndroid Build Coastguard Worker 
165*84e33947SAndroid Build Coastguard Worker /**
166*84e33947SAndroid Build Coastguard Worker  * Helper function that takes care of the boilerplate for allocating a
167*84e33947SAndroid Build Coastguard Worker  * ChreFlatBufferBuilder on the heap and adding it to the outbound message
168*84e33947SAndroid Build Coastguard Worker  * queue.
169*84e33947SAndroid Build Coastguard Worker  *
170*84e33947SAndroid Build Coastguard Worker  * @param msgType Identifies the message while in the outboud queue
171*84e33947SAndroid Build Coastguard Worker  * @param initialBufferSize Number of bytes to reserve when first allocating the
172*84e33947SAndroid Build Coastguard Worker  *        ChreFlatBufferBuilder
173*84e33947SAndroid Build Coastguard Worker  * @param buildMsgFunc Synchronous callback used to encode the FlatBuffer
174*84e33947SAndroid Build Coastguard Worker  *        message. Will not be invoked if allocation fails.
175*84e33947SAndroid Build Coastguard Worker  * @param cookie Opaque pointer that will be passed through to buildMsgFunc
176*84e33947SAndroid Build Coastguard Worker  *
177*84e33947SAndroid Build Coastguard Worker  * @return true if the message was successfully added to the queue
178*84e33947SAndroid Build Coastguard Worker  */
buildAndEnqueueMessage(PendingMessageType msgType,size_t initialBufferSize,MessageBuilderFunction * msgBuilder,void * cookie)179*84e33947SAndroid Build Coastguard Worker bool buildAndEnqueueMessage(PendingMessageType msgType,
180*84e33947SAndroid Build Coastguard Worker                             size_t initialBufferSize,
181*84e33947SAndroid Build Coastguard Worker                             MessageBuilderFunction *msgBuilder, void *cookie) {
182*84e33947SAndroid Build Coastguard Worker   bool pushed = false;
183*84e33947SAndroid Build Coastguard Worker 
184*84e33947SAndroid Build Coastguard Worker   auto builder = MakeUnique<ChreFlatBufferBuilder>(initialBufferSize);
185*84e33947SAndroid Build Coastguard Worker   if (builder.isNull()) {
186*84e33947SAndroid Build Coastguard Worker     LOGE("Couldn't allocate memory for message type %d",
187*84e33947SAndroid Build Coastguard Worker          static_cast<int>(msgType));
188*84e33947SAndroid Build Coastguard Worker   } else {
189*84e33947SAndroid Build Coastguard Worker     msgBuilder(*builder, cookie);
190*84e33947SAndroid Build Coastguard Worker 
191*84e33947SAndroid Build Coastguard Worker     // TODO: if this fails, ideally we should block for some timeout until
192*84e33947SAndroid Build Coastguard Worker     // there's space in the queue
193*84e33947SAndroid Build Coastguard Worker     if (!enqueueMessage(PendingMessage(msgType, builder.get()))) {
194*84e33947SAndroid Build Coastguard Worker       LOGE("Couldn't push message type %d to outbound queue",
195*84e33947SAndroid Build Coastguard Worker            static_cast<int>(msgType));
196*84e33947SAndroid Build Coastguard Worker     } else {
197*84e33947SAndroid Build Coastguard Worker       builder.release();
198*84e33947SAndroid Build Coastguard Worker       pushed = true;
199*84e33947SAndroid Build Coastguard Worker     }
200*84e33947SAndroid Build Coastguard Worker   }
201*84e33947SAndroid Build Coastguard Worker 
202*84e33947SAndroid Build Coastguard Worker   return pushed;
203*84e33947SAndroid Build Coastguard Worker }
204*84e33947SAndroid Build Coastguard Worker 
205*84e33947SAndroid Build Coastguard Worker /**
206*84e33947SAndroid Build Coastguard Worker  * FlatBuffer message builder callback used with handleNanoappListRequest()
207*84e33947SAndroid Build Coastguard Worker  */
buildNanoappListResponse(ChreFlatBufferBuilder & builder,void * cookie)208*84e33947SAndroid Build Coastguard Worker void buildNanoappListResponse(ChreFlatBufferBuilder &builder, void *cookie) {
209*84e33947SAndroid Build Coastguard Worker   auto nanoappAdderCallback = [](const Nanoapp *nanoapp, void *data) {
210*84e33947SAndroid Build Coastguard Worker     auto *cbData = static_cast<NanoappListData *>(data);
211*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::addNanoappListEntry(
212*84e33947SAndroid Build Coastguard Worker         *(cbData->builder), cbData->nanoappEntries, nanoapp->getAppId(),
213*84e33947SAndroid Build Coastguard Worker         nanoapp->getAppVersion(), true /*enabled*/, nanoapp->isSystemNanoapp(),
214*84e33947SAndroid Build Coastguard Worker         nanoapp->getAppPermissions(), nanoapp->getRpcServices());
215*84e33947SAndroid Build Coastguard Worker   };
216*84e33947SAndroid Build Coastguard Worker 
217*84e33947SAndroid Build Coastguard Worker   // Add a NanoappListEntry to the FlatBuffer for each nanoapp
218*84e33947SAndroid Build Coastguard Worker   auto *cbData = static_cast<NanoappListData *>(cookie);
219*84e33947SAndroid Build Coastguard Worker   cbData->builder = &builder;
220*84e33947SAndroid Build Coastguard Worker   EventLoop &eventLoop = EventLoopManagerSingleton::get()->getEventLoop();
221*84e33947SAndroid Build Coastguard Worker   eventLoop.forEachNanoapp(nanoappAdderCallback, cbData);
222*84e33947SAndroid Build Coastguard Worker   HostProtocolChre::finishNanoappListResponse(builder, cbData->nanoappEntries,
223*84e33947SAndroid Build Coastguard Worker                                               cbData->hostClientId);
224*84e33947SAndroid Build Coastguard Worker }
225*84e33947SAndroid Build Coastguard Worker 
handleUnloadNanoappCallback(SystemCallbackType,UniquePtr<UnloadNanoappCallbackData> && data)226*84e33947SAndroid Build Coastguard Worker void handleUnloadNanoappCallback(SystemCallbackType /*type*/,
227*84e33947SAndroid Build Coastguard Worker                                  UniquePtr<UnloadNanoappCallbackData> &&data) {
228*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
229*84e33947SAndroid Build Coastguard Worker     auto *cbData = static_cast<UnloadNanoappCallbackData *>(cookie);
230*84e33947SAndroid Build Coastguard Worker 
231*84e33947SAndroid Build Coastguard Worker     bool success = false;
232*84e33947SAndroid Build Coastguard Worker     uint16_t instanceId;
233*84e33947SAndroid Build Coastguard Worker     EventLoop &eventLoop = EventLoopManagerSingleton::get()->getEventLoop();
234*84e33947SAndroid Build Coastguard Worker     if (!eventLoop.findNanoappInstanceIdByAppId(cbData->appId, &instanceId)) {
235*84e33947SAndroid Build Coastguard Worker       LOGE("Couldn't unload app ID 0x%016" PRIx64 ": not found", cbData->appId);
236*84e33947SAndroid Build Coastguard Worker     } else {
237*84e33947SAndroid Build Coastguard Worker       success =
238*84e33947SAndroid Build Coastguard Worker           eventLoop.unloadNanoapp(instanceId, cbData->allowSystemNanoappUnload);
239*84e33947SAndroid Build Coastguard Worker     }
240*84e33947SAndroid Build Coastguard Worker 
241*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeUnloadNanoappResponse(
242*84e33947SAndroid Build Coastguard Worker         builder, cbData->hostClientId, cbData->transactionId, success);
243*84e33947SAndroid Build Coastguard Worker   };
244*84e33947SAndroid Build Coastguard Worker 
245*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialBufferSize = 52;
246*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::UnloadNanoappResponse,
247*84e33947SAndroid Build Coastguard Worker                          kInitialBufferSize, msgBuilder, data.get());
248*84e33947SAndroid Build Coastguard Worker }
249*84e33947SAndroid Build Coastguard Worker 
generateMessageToHost(const MessageToHost * msgToHost,unsigned char * buffer,size_t bufferSize,unsigned int * messageLen)250*84e33947SAndroid Build Coastguard Worker int generateMessageToHost(const MessageToHost *msgToHost, unsigned char *buffer,
251*84e33947SAndroid Build Coastguard Worker                           size_t bufferSize, unsigned int *messageLen) {
252*84e33947SAndroid Build Coastguard Worker   // TODO: ideally we'd construct our flatbuffer directly in the
253*84e33947SAndroid Build Coastguard Worker   // host-supplied buffer
254*84e33947SAndroid Build Coastguard Worker   constexpr size_t kFixedSizePortion = 88;
255*84e33947SAndroid Build Coastguard Worker   ChreFlatBufferBuilder builder(msgToHost->message.size() + kFixedSizePortion);
256*84e33947SAndroid Build Coastguard Worker   HostProtocolChre::encodeNanoappMessage(
257*84e33947SAndroid Build Coastguard Worker       builder, msgToHost->appId, msgToHost->toHostData.messageType,
258*84e33947SAndroid Build Coastguard Worker       msgToHost->toHostData.hostEndpoint, msgToHost->message.data(),
259*84e33947SAndroid Build Coastguard Worker       msgToHost->message.size(), msgToHost->toHostData.appPermissions,
260*84e33947SAndroid Build Coastguard Worker       msgToHost->toHostData.messagePermissions, msgToHost->toHostData.wokeHost);
261*84e33947SAndroid Build Coastguard Worker 
262*84e33947SAndroid Build Coastguard Worker   int result = copyToHostBuffer(builder, buffer, bufferSize, messageLen);
263*84e33947SAndroid Build Coastguard Worker 
264*84e33947SAndroid Build Coastguard Worker   auto &hostCommsManager =
265*84e33947SAndroid Build Coastguard Worker       EventLoopManagerSingleton::get()->getHostCommsManager();
266*84e33947SAndroid Build Coastguard Worker   hostCommsManager.onMessageToHostComplete(msgToHost);
267*84e33947SAndroid Build Coastguard Worker 
268*84e33947SAndroid Build Coastguard Worker   return result;
269*84e33947SAndroid Build Coastguard Worker }
270*84e33947SAndroid Build Coastguard Worker 
generateHubInfoResponse(uint16_t hostClientId,unsigned char * buffer,size_t bufferSize,unsigned int * messageLen)271*84e33947SAndroid Build Coastguard Worker int generateHubInfoResponse(uint16_t hostClientId, unsigned char *buffer,
272*84e33947SAndroid Build Coastguard Worker                             size_t bufferSize, unsigned int *messageLen) {
273*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialBufferSize = 192;
274*84e33947SAndroid Build Coastguard Worker 
275*84e33947SAndroid Build Coastguard Worker   constexpr char kHubName[] = "CHRE on SLPI";
276*84e33947SAndroid Build Coastguard Worker   constexpr char kVendor[] = "Google";
277*84e33947SAndroid Build Coastguard Worker   constexpr char kToolchain[] =
278*84e33947SAndroid Build Coastguard Worker       "Hexagon Tools 8.x (clang " STRINGIFY(__clang_major__) "." STRINGIFY(
279*84e33947SAndroid Build Coastguard Worker           __clang_minor__) "." STRINGIFY(__clang_patchlevel__) ")";
280*84e33947SAndroid Build Coastguard Worker   constexpr uint32_t kLegacyPlatformVersion = 0;
281*84e33947SAndroid Build Coastguard Worker   constexpr uint32_t kLegacyToolchainVersion =
282*84e33947SAndroid Build Coastguard Worker       ((__clang_major__ & 0xFF) << 24) | ((__clang_minor__ & 0xFF) << 16) |
283*84e33947SAndroid Build Coastguard Worker       (__clang_patchlevel__ & 0xFFFF);
284*84e33947SAndroid Build Coastguard Worker   constexpr float kPeakMips = 350;
285*84e33947SAndroid Build Coastguard Worker   constexpr float kStoppedPower = 0;
286*84e33947SAndroid Build Coastguard Worker   constexpr float kSleepPower = 1;
287*84e33947SAndroid Build Coastguard Worker   constexpr float kPeakPower = 15;
288*84e33947SAndroid Build Coastguard Worker 
289*84e33947SAndroid Build Coastguard Worker   // Note that this may execute prior to EventLoopManager::lateInit() completing
290*84e33947SAndroid Build Coastguard Worker   ChreFlatBufferBuilder builder(kInitialBufferSize);
291*84e33947SAndroid Build Coastguard Worker   HostProtocolChre::encodeHubInfoResponse(
292*84e33947SAndroid Build Coastguard Worker       builder, kHubName, kVendor, kToolchain, kLegacyPlatformVersion,
293*84e33947SAndroid Build Coastguard Worker       kLegacyToolchainVersion, kPeakMips, kStoppedPower, kSleepPower,
294*84e33947SAndroid Build Coastguard Worker       kPeakPower, chreGetMessageToHostMaxSize(), chreGetPlatformId(),
295*84e33947SAndroid Build Coastguard Worker       chreGetVersion(), hostClientId, /* supportsReliableMessage= */ false);
296*84e33947SAndroid Build Coastguard Worker 
297*84e33947SAndroid Build Coastguard Worker   return copyToHostBuffer(builder, buffer, bufferSize, messageLen);
298*84e33947SAndroid Build Coastguard Worker }
299*84e33947SAndroid Build Coastguard Worker 
generateMessageFromBuilder(ChreFlatBufferBuilder * builder,unsigned char * buffer,size_t bufferSize,unsigned int * messageLen,bool isEncodedLogMessage)300*84e33947SAndroid Build Coastguard Worker int generateMessageFromBuilder(ChreFlatBufferBuilder *builder,
301*84e33947SAndroid Build Coastguard Worker                                unsigned char *buffer, size_t bufferSize,
302*84e33947SAndroid Build Coastguard Worker                                unsigned int *messageLen,
303*84e33947SAndroid Build Coastguard Worker                                bool isEncodedLogMessage) {
304*84e33947SAndroid Build Coastguard Worker   CHRE_ASSERT(builder != nullptr);
305*84e33947SAndroid Build Coastguard Worker   int result = copyToHostBuffer(*builder, buffer, bufferSize, messageLen);
306*84e33947SAndroid Build Coastguard Worker 
307*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_USE_BUFFERED_LOGGING
308*84e33947SAndroid Build Coastguard Worker   if (isEncodedLogMessage && LogBufferManagerSingleton::isInitialized()) {
309*84e33947SAndroid Build Coastguard Worker     LogBufferManagerSingleton::get()->onLogsSentToHost();
310*84e33947SAndroid Build Coastguard Worker   }
311*84e33947SAndroid Build Coastguard Worker #else
312*84e33947SAndroid Build Coastguard Worker   UNUSED_VAR(isEncodedLogMessage);
313*84e33947SAndroid Build Coastguard Worker #endif
314*84e33947SAndroid Build Coastguard Worker 
315*84e33947SAndroid Build Coastguard Worker   builder->~ChreFlatBufferBuilder();
316*84e33947SAndroid Build Coastguard Worker   memoryFree(builder);
317*84e33947SAndroid Build Coastguard Worker   return result;
318*84e33947SAndroid Build Coastguard Worker }
319*84e33947SAndroid Build Coastguard Worker 
sendDebugDumpData(uint16_t hostClientId,const char * debugStr,size_t debugStrSize)320*84e33947SAndroid Build Coastguard Worker void sendDebugDumpData(uint16_t hostClientId, const char *debugStr,
321*84e33947SAndroid Build Coastguard Worker                        size_t debugStrSize) {
322*84e33947SAndroid Build Coastguard Worker   struct DebugDumpMessageData {
323*84e33947SAndroid Build Coastguard Worker     uint16_t hostClientId;
324*84e33947SAndroid Build Coastguard Worker     const char *debugStr;
325*84e33947SAndroid Build Coastguard Worker     size_t debugStrSize;
326*84e33947SAndroid Build Coastguard Worker   };
327*84e33947SAndroid Build Coastguard Worker 
328*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
329*84e33947SAndroid Build Coastguard Worker     const auto *data = static_cast<const DebugDumpMessageData *>(cookie);
330*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeDebugDumpData(builder, data->hostClientId,
331*84e33947SAndroid Build Coastguard Worker                                           data->debugStr, data->debugStrSize);
332*84e33947SAndroid Build Coastguard Worker   };
333*84e33947SAndroid Build Coastguard Worker 
334*84e33947SAndroid Build Coastguard Worker   constexpr size_t kFixedSizePortion = 52;
335*84e33947SAndroid Build Coastguard Worker   DebugDumpMessageData data;
336*84e33947SAndroid Build Coastguard Worker   data.hostClientId = hostClientId;
337*84e33947SAndroid Build Coastguard Worker   data.debugStr = debugStr;
338*84e33947SAndroid Build Coastguard Worker   data.debugStrSize = debugStrSize;
339*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::DebugDumpData,
340*84e33947SAndroid Build Coastguard Worker                          kFixedSizePortion + debugStrSize, msgBuilder, &data);
341*84e33947SAndroid Build Coastguard Worker }
342*84e33947SAndroid Build Coastguard Worker 
sendDebugDumpResponse(uint16_t hostClientId,bool success,uint32_t dataCount)343*84e33947SAndroid Build Coastguard Worker void sendDebugDumpResponse(uint16_t hostClientId, bool success,
344*84e33947SAndroid Build Coastguard Worker                            uint32_t dataCount) {
345*84e33947SAndroid Build Coastguard Worker   struct DebugDumpResponseData {
346*84e33947SAndroid Build Coastguard Worker     uint16_t hostClientId;
347*84e33947SAndroid Build Coastguard Worker     bool success;
348*84e33947SAndroid Build Coastguard Worker     uint32_t dataCount;
349*84e33947SAndroid Build Coastguard Worker   };
350*84e33947SAndroid Build Coastguard Worker 
351*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
352*84e33947SAndroid Build Coastguard Worker     const auto *data = static_cast<const DebugDumpResponseData *>(cookie);
353*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeDebugDumpResponse(builder, data->hostClientId,
354*84e33947SAndroid Build Coastguard Worker                                               data->success, data->dataCount);
355*84e33947SAndroid Build Coastguard Worker   };
356*84e33947SAndroid Build Coastguard Worker 
357*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialSize = 52;
358*84e33947SAndroid Build Coastguard Worker   DebugDumpResponseData data;
359*84e33947SAndroid Build Coastguard Worker   data.hostClientId = hostClientId;
360*84e33947SAndroid Build Coastguard Worker   data.success = success;
361*84e33947SAndroid Build Coastguard Worker   data.dataCount = dataCount;
362*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::DebugDumpResponse, kInitialSize,
363*84e33947SAndroid Build Coastguard Worker                          msgBuilder, &data);
364*84e33947SAndroid Build Coastguard Worker }
365*84e33947SAndroid Build Coastguard Worker 
sendSelfTestResponse(uint16_t hostClientId,bool success)366*84e33947SAndroid Build Coastguard Worker void sendSelfTestResponse(uint16_t hostClientId, bool success) {
367*84e33947SAndroid Build Coastguard Worker   struct SelfTestResponseData {
368*84e33947SAndroid Build Coastguard Worker     uint16_t hostClientId;
369*84e33947SAndroid Build Coastguard Worker     bool success;
370*84e33947SAndroid Build Coastguard Worker   };
371*84e33947SAndroid Build Coastguard Worker 
372*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
373*84e33947SAndroid Build Coastguard Worker     const auto *data = static_cast<const SelfTestResponseData *>(cookie);
374*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeSelfTestResponse(builder, data->hostClientId,
375*84e33947SAndroid Build Coastguard Worker                                              data->success);
376*84e33947SAndroid Build Coastguard Worker   };
377*84e33947SAndroid Build Coastguard Worker 
378*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialSize = 52;
379*84e33947SAndroid Build Coastguard Worker   SelfTestResponseData data;
380*84e33947SAndroid Build Coastguard Worker   data.hostClientId = hostClientId;
381*84e33947SAndroid Build Coastguard Worker   data.success = success;
382*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::SelfTestResponse, kInitialSize,
383*84e33947SAndroid Build Coastguard Worker                          msgBuilder, &data);
384*84e33947SAndroid Build Coastguard Worker }
385*84e33947SAndroid Build Coastguard Worker 
386*84e33947SAndroid Build Coastguard Worker /**
387*84e33947SAndroid Build Coastguard Worker  * Sends a request to the host for a time sync message.
388*84e33947SAndroid Build Coastguard Worker  */
sendTimeSyncRequest()389*84e33947SAndroid Build Coastguard Worker void sendTimeSyncRequest() {
390*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
391*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeTimeSyncRequest(builder);
392*84e33947SAndroid Build Coastguard Worker   };
393*84e33947SAndroid Build Coastguard Worker 
394*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialSize = 52;
395*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::TimeSyncRequest, kInitialSize,
396*84e33947SAndroid Build Coastguard Worker                          msgBuilder, nullptr);
397*84e33947SAndroid Build Coastguard Worker 
398*84e33947SAndroid Build Coastguard Worker   gLastTimeSyncRequestNanos = SystemTime::getMonotonicTime();
399*84e33947SAndroid Build Coastguard Worker }
400*84e33947SAndroid Build Coastguard Worker 
setTimeSyncRequestTimer(Nanoseconds delay)401*84e33947SAndroid Build Coastguard Worker void setTimeSyncRequestTimer(Nanoseconds delay) {
402*84e33947SAndroid Build Coastguard Worker   static SystemTimer sTimeSyncRequestTimer;
403*84e33947SAndroid Build Coastguard Worker   static bool sTimeSyncRequestTimerInitialized = false;
404*84e33947SAndroid Build Coastguard Worker 
405*84e33947SAndroid Build Coastguard Worker   // Check for timer init since this method might be called before CHRE
406*84e33947SAndroid Build Coastguard Worker   // init is called.
407*84e33947SAndroid Build Coastguard Worker   if (!sTimeSyncRequestTimerInitialized) {
408*84e33947SAndroid Build Coastguard Worker     if (!sTimeSyncRequestTimer.init()) {
409*84e33947SAndroid Build Coastguard Worker       FATAL_ERROR("Failed to initialize time sync request timer.");
410*84e33947SAndroid Build Coastguard Worker     } else {
411*84e33947SAndroid Build Coastguard Worker       sTimeSyncRequestTimerInitialized = true;
412*84e33947SAndroid Build Coastguard Worker     }
413*84e33947SAndroid Build Coastguard Worker   }
414*84e33947SAndroid Build Coastguard Worker   if (sTimeSyncRequestTimer.isActive()) {
415*84e33947SAndroid Build Coastguard Worker     sTimeSyncRequestTimer.cancel();
416*84e33947SAndroid Build Coastguard Worker   }
417*84e33947SAndroid Build Coastguard Worker   auto callback = [](void * /* data */) { sendTimeSyncRequest(); };
418*84e33947SAndroid Build Coastguard Worker   if (!sTimeSyncRequestTimer.set(callback, nullptr /* data */, delay)) {
419*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to set time sync request timer.");
420*84e33947SAndroid Build Coastguard Worker   }
421*84e33947SAndroid Build Coastguard Worker }
422*84e33947SAndroid Build Coastguard Worker 
423*84e33947SAndroid Build Coastguard Worker /**
424*84e33947SAndroid Build Coastguard Worker  * Helper function that prepares a nanoapp that can be loaded into the system
425*84e33947SAndroid Build Coastguard Worker  * from a file stored on disk.
426*84e33947SAndroid Build Coastguard Worker  *
427*84e33947SAndroid Build Coastguard Worker  * @param hostClientId the ID of client that originated this transaction
428*84e33947SAndroid Build Coastguard Worker  * @param transactionId the ID of the transaction
429*84e33947SAndroid Build Coastguard Worker  * @param appId the ID of the app to load
430*84e33947SAndroid Build Coastguard Worker  * @param appVersion the version of the app to load
431*84e33947SAndroid Build Coastguard Worker  * @param targetApiVersion the API version this nanoapp is targeted for
432*84e33947SAndroid Build Coastguard Worker  * @param appFilename Null-terminated ASCII string containing the file name that
433*84e33947SAndroid Build Coastguard Worker  *     contains the app binary to be loaded.
434*84e33947SAndroid Build Coastguard Worker  *
435*84e33947SAndroid Build Coastguard Worker  * @return A valid pointer to a nanoapp that can be loaded into the system. A
436*84e33947SAndroid Build Coastguard Worker  *     nullptr if the preparation process fails.
437*84e33947SAndroid Build Coastguard Worker  */
handleLoadNanoappFile(uint16_t hostClientId,uint32_t transactionId,uint64_t appId,uint32_t appVersion,uint32_t targetApiVersion,const char * appFilename)438*84e33947SAndroid Build Coastguard Worker UniquePtr<Nanoapp> handleLoadNanoappFile(uint16_t hostClientId,
439*84e33947SAndroid Build Coastguard Worker                                          uint32_t transactionId, uint64_t appId,
440*84e33947SAndroid Build Coastguard Worker                                          uint32_t appVersion,
441*84e33947SAndroid Build Coastguard Worker                                          uint32_t targetApiVersion,
442*84e33947SAndroid Build Coastguard Worker                                          const char *appFilename) {
443*84e33947SAndroid Build Coastguard Worker   LOGD("Load nanoapp request for app ID 0x%016" PRIx64 " ver 0x%" PRIx32
444*84e33947SAndroid Build Coastguard Worker        " target API 0x%08" PRIx32 " (txnId %" PRIu32 " client %" PRIu16 ")",
445*84e33947SAndroid Build Coastguard Worker        appId, appVersion, targetApiVersion, transactionId, hostClientId);
446*84e33947SAndroid Build Coastguard Worker 
447*84e33947SAndroid Build Coastguard Worker   auto nanoapp = MakeUnique<Nanoapp>();
448*84e33947SAndroid Build Coastguard Worker 
449*84e33947SAndroid Build Coastguard Worker   if (nanoapp.isNull()) {
450*84e33947SAndroid Build Coastguard Worker     LOG_OOM();
451*84e33947SAndroid Build Coastguard Worker   } else if (!nanoapp->setAppInfo(appId, appVersion, appFilename,
452*84e33947SAndroid Build Coastguard Worker                                   targetApiVersion) ||
453*84e33947SAndroid Build Coastguard Worker              !nanoapp->isLoaded()) {
454*84e33947SAndroid Build Coastguard Worker     nanoapp.reset(nullptr);
455*84e33947SAndroid Build Coastguard Worker   }
456*84e33947SAndroid Build Coastguard Worker 
457*84e33947SAndroid Build Coastguard Worker   return nanoapp;
458*84e33947SAndroid Build Coastguard Worker }
459*84e33947SAndroid Build Coastguard Worker 
460*84e33947SAndroid Build Coastguard Worker /**
461*84e33947SAndroid Build Coastguard Worker  * FastRPC method invoked by the host to block on messages
462*84e33947SAndroid Build Coastguard Worker  *
463*84e33947SAndroid Build Coastguard Worker  * @param buffer Output buffer to populate with message data
464*84e33947SAndroid Build Coastguard Worker  * @param bufferLen Size of the buffer, in bytes
465*84e33947SAndroid Build Coastguard Worker  * @param messageLen Output parameter to populate with the size of the message
466*84e33947SAndroid Build Coastguard Worker  *        in bytes upon success
467*84e33947SAndroid Build Coastguard Worker  *
468*84e33947SAndroid Build Coastguard Worker  * @return 0 on success, nonzero on failure
469*84e33947SAndroid Build Coastguard Worker  */
chre_slpi_get_message_to_host(unsigned char * buffer,int bufferLen,unsigned int * messageLen)470*84e33947SAndroid Build Coastguard Worker extern "C" int chre_slpi_get_message_to_host(unsigned char *buffer,
471*84e33947SAndroid Build Coastguard Worker                                              int bufferLen,
472*84e33947SAndroid Build Coastguard Worker                                              unsigned int *messageLen) {
473*84e33947SAndroid Build Coastguard Worker   CHRE_ASSERT(buffer != nullptr);
474*84e33947SAndroid Build Coastguard Worker   CHRE_ASSERT(bufferLen > 0);
475*84e33947SAndroid Build Coastguard Worker   CHRE_ASSERT(messageLen != nullptr);
476*84e33947SAndroid Build Coastguard Worker   int result = CHRE_FASTRPC_ERROR;
477*84e33947SAndroid Build Coastguard Worker 
478*84e33947SAndroid Build Coastguard Worker   if (bufferLen <= 0 || buffer == nullptr || messageLen == nullptr) {
479*84e33947SAndroid Build Coastguard Worker     // Note that we can't use regular logs here as they can result in sending
480*84e33947SAndroid Build Coastguard Worker     // a message, leading to an infinite loop if the error is persistent
481*84e33947SAndroid Build Coastguard Worker     FARF(FATAL, "Invalid buffer size %d or bad pointers (buf %d len %d)",
482*84e33947SAndroid Build Coastguard Worker          bufferLen, (buffer == nullptr), (messageLen == nullptr));
483*84e33947SAndroid Build Coastguard Worker   } else {
484*84e33947SAndroid Build Coastguard Worker     size_t bufferSize = static_cast<size_t>(bufferLen);
485*84e33947SAndroid Build Coastguard Worker     PendingMessage pendingMsg = gOutboundQueue.pop();
486*84e33947SAndroid Build Coastguard Worker 
487*84e33947SAndroid Build Coastguard Worker     switch (pendingMsg.type) {
488*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::Shutdown:
489*84e33947SAndroid Build Coastguard Worker         result = CHRE_FASTRPC_ERROR_SHUTTING_DOWN;
490*84e33947SAndroid Build Coastguard Worker         break;
491*84e33947SAndroid Build Coastguard Worker 
492*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::NanoappMessageToHost:
493*84e33947SAndroid Build Coastguard Worker         result = generateMessageToHost(pendingMsg.data.msgToHost, buffer,
494*84e33947SAndroid Build Coastguard Worker                                        bufferSize, messageLen);
495*84e33947SAndroid Build Coastguard Worker         break;
496*84e33947SAndroid Build Coastguard Worker 
497*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::HubInfoResponse:
498*84e33947SAndroid Build Coastguard Worker         result = generateHubInfoResponse(pendingMsg.data.hostClientId, buffer,
499*84e33947SAndroid Build Coastguard Worker                                          bufferSize, messageLen);
500*84e33947SAndroid Build Coastguard Worker         break;
501*84e33947SAndroid Build Coastguard Worker 
502*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::NanoappListResponse:
503*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::LoadNanoappResponse:
504*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::UnloadNanoappResponse:
505*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::DebugDumpData:
506*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::DebugDumpResponse:
507*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::TimeSyncRequest:
508*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::LowPowerMicAccessRequest:
509*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::LowPowerMicAccessRelease:
510*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::EncodedLogMessage:
511*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::SelfTestResponse:
512*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::MetricLog:
513*84e33947SAndroid Build Coastguard Worker       case PendingMessageType::NanConfigurationRequest:
514*84e33947SAndroid Build Coastguard Worker         result = generateMessageFromBuilder(
515*84e33947SAndroid Build Coastguard Worker             pendingMsg.data.builder, buffer, bufferSize, messageLen,
516*84e33947SAndroid Build Coastguard Worker             pendingMsg.type == PendingMessageType::EncodedLogMessage);
517*84e33947SAndroid Build Coastguard Worker         break;
518*84e33947SAndroid Build Coastguard Worker 
519*84e33947SAndroid Build Coastguard Worker       default:
520*84e33947SAndroid Build Coastguard Worker         CHRE_ASSERT_LOG(false, "Unexpected pending message type");
521*84e33947SAndroid Build Coastguard Worker     }
522*84e33947SAndroid Build Coastguard Worker   }
523*84e33947SAndroid Build Coastguard Worker 
524*84e33947SAndroid Build Coastguard Worker   // Opportunistically send a time sync message (1 hour period threshold)
525*84e33947SAndroid Build Coastguard Worker   constexpr Seconds kOpportunisticTimeSyncPeriod = Seconds(60 * 60 * 1);
526*84e33947SAndroid Build Coastguard Worker   if (SystemTime::getMonotonicTime() >
527*84e33947SAndroid Build Coastguard Worker       gLastTimeSyncRequestNanos + kOpportunisticTimeSyncPeriod) {
528*84e33947SAndroid Build Coastguard Worker     sendTimeSyncRequest();
529*84e33947SAndroid Build Coastguard Worker   }
530*84e33947SAndroid Build Coastguard Worker 
531*84e33947SAndroid Build Coastguard Worker   return result;
532*84e33947SAndroid Build Coastguard Worker }
533*84e33947SAndroid Build Coastguard Worker 
534*84e33947SAndroid Build Coastguard Worker /**
535*84e33947SAndroid Build Coastguard Worker  * FastRPC method invoked by the host to send a message to the system
536*84e33947SAndroid Build Coastguard Worker  *
537*84e33947SAndroid Build Coastguard Worker  * @param buffer
538*84e33947SAndroid Build Coastguard Worker  * @param size
539*84e33947SAndroid Build Coastguard Worker  *
540*84e33947SAndroid Build Coastguard Worker  * @return 0 on success, nonzero on failure
541*84e33947SAndroid Build Coastguard Worker  */
chre_slpi_deliver_message_from_host(const unsigned char * message,int messageLen)542*84e33947SAndroid Build Coastguard Worker extern "C" int chre_slpi_deliver_message_from_host(const unsigned char *message,
543*84e33947SAndroid Build Coastguard Worker                                                    int messageLen) {
544*84e33947SAndroid Build Coastguard Worker   CHRE_ASSERT(message != nullptr);
545*84e33947SAndroid Build Coastguard Worker   CHRE_ASSERT(messageLen > 0);
546*84e33947SAndroid Build Coastguard Worker   int result = CHRE_FASTRPC_ERROR;
547*84e33947SAndroid Build Coastguard Worker 
548*84e33947SAndroid Build Coastguard Worker   if (message == nullptr || messageLen <= 0) {
549*84e33947SAndroid Build Coastguard Worker     LOGE("Got null or invalid size (%d) message from host", messageLen);
550*84e33947SAndroid Build Coastguard Worker   } else if (!HostProtocolChre::decodeMessageFromHost(
551*84e33947SAndroid Build Coastguard Worker                  message, static_cast<size_t>(messageLen))) {
552*84e33947SAndroid Build Coastguard Worker     LOGE("Failed to decode/handle message");
553*84e33947SAndroid Build Coastguard Worker   } else {
554*84e33947SAndroid Build Coastguard Worker     result = CHRE_FASTRPC_SUCCESS;
555*84e33947SAndroid Build Coastguard Worker   }
556*84e33947SAndroid Build Coastguard Worker 
557*84e33947SAndroid Build Coastguard Worker   return result;
558*84e33947SAndroid Build Coastguard Worker }
559*84e33947SAndroid Build Coastguard Worker 
560*84e33947SAndroid Build Coastguard Worker }  // anonymous namespace
561*84e33947SAndroid Build Coastguard Worker 
sendDebugDumpResultToHost(uint16_t hostClientId,const char * debugStr,size_t debugStrSize,bool complete,uint32_t dataCount)562*84e33947SAndroid Build Coastguard Worker void sendDebugDumpResultToHost(uint16_t hostClientId, const char *debugStr,
563*84e33947SAndroid Build Coastguard Worker                                size_t debugStrSize, bool complete,
564*84e33947SAndroid Build Coastguard Worker                                uint32_t dataCount) {
565*84e33947SAndroid Build Coastguard Worker   if (debugStrSize > 0) {
566*84e33947SAndroid Build Coastguard Worker     sendDebugDumpData(hostClientId, debugStr, debugStrSize);
567*84e33947SAndroid Build Coastguard Worker   }
568*84e33947SAndroid Build Coastguard Worker 
569*84e33947SAndroid Build Coastguard Worker   if (complete) {
570*84e33947SAndroid Build Coastguard Worker     sendDebugDumpResponse(hostClientId, true /*success*/, dataCount);
571*84e33947SAndroid Build Coastguard Worker   }
572*84e33947SAndroid Build Coastguard Worker }
573*84e33947SAndroid Build Coastguard Worker 
flushMessagesSentByNanoapp(uint64_t)574*84e33947SAndroid Build Coastguard Worker void HostLink::flushMessagesSentByNanoapp(uint64_t /*appId*/) {
575*84e33947SAndroid Build Coastguard Worker   // TODO: this is not completely safe since it's timer-based, but should work
576*84e33947SAndroid Build Coastguard Worker   // well enough for the initial implementation. To be fully safe, we'd need
577*84e33947SAndroid Build Coastguard Worker   // some synchronization with the thread that runs
578*84e33947SAndroid Build Coastguard Worker   // chre_slpi_get_message_to_host(), e.g. a mutex that is held by that thread
579*84e33947SAndroid Build Coastguard Worker   // prior to calling pop() and only released after onMessageToHostComplete
580*84e33947SAndroid Build Coastguard Worker   // would've been called. If we acquire that mutex here, and hold it while
581*84e33947SAndroid Build Coastguard Worker   // purging any messages sent by the nanoapp in the queue, we can be certain
582*84e33947SAndroid Build Coastguard Worker   // that onMessageToHostComplete will not be called after this function returns
583*84e33947SAndroid Build Coastguard Worker   // for messages sent by that nanoapp
584*84e33947SAndroid Build Coastguard Worker   flushOutboundQueue();
585*84e33947SAndroid Build Coastguard Worker 
586*84e33947SAndroid Build Coastguard Worker   // One extra sleep to try to ensure that any messages popped just before
587*84e33947SAndroid Build Coastguard Worker   // checking empty() are fully processed before we return
588*84e33947SAndroid Build Coastguard Worker   constexpr time_timetick_type kFinalDelayUsec = 10000;
589*84e33947SAndroid Build Coastguard Worker   timer_sleep(kFinalDelayUsec, T_USEC, true /* non_deferrable */);
590*84e33947SAndroid Build Coastguard Worker }
591*84e33947SAndroid Build Coastguard Worker 
sendMessage(const MessageToHost * message)592*84e33947SAndroid Build Coastguard Worker bool HostLink::sendMessage(const MessageToHost *message) {
593*84e33947SAndroid Build Coastguard Worker   return enqueueMessage(
594*84e33947SAndroid Build Coastguard Worker       PendingMessage(PendingMessageType::NanoappMessageToHost, message));
595*84e33947SAndroid Build Coastguard Worker }
596*84e33947SAndroid Build Coastguard Worker 
sendMessageDeliveryStatus(uint32_t,uint8_t)597*84e33947SAndroid Build Coastguard Worker bool HostLink::sendMessageDeliveryStatus(uint32_t /* messageSequenceNumber */,
598*84e33947SAndroid Build Coastguard Worker                                          uint8_t /* errorCode */) {
599*84e33947SAndroid Build Coastguard Worker   return false;
600*84e33947SAndroid Build Coastguard Worker }
601*84e33947SAndroid Build Coastguard Worker 
sendMetricLog(uint32_t metricId,const uint8_t * encodedMetric,size_t encodedMetricLen)602*84e33947SAndroid Build Coastguard Worker bool HostLink::sendMetricLog(uint32_t metricId, const uint8_t *encodedMetric,
603*84e33947SAndroid Build Coastguard Worker                              size_t encodedMetricLen) {
604*84e33947SAndroid Build Coastguard Worker   struct MetricLogData {
605*84e33947SAndroid Build Coastguard Worker     uint32_t metricId;
606*84e33947SAndroid Build Coastguard Worker     const uint8_t *encodedMetric;
607*84e33947SAndroid Build Coastguard Worker     size_t encodedMetricLen;
608*84e33947SAndroid Build Coastguard Worker   };
609*84e33947SAndroid Build Coastguard Worker 
610*84e33947SAndroid Build Coastguard Worker   MetricLogData data;
611*84e33947SAndroid Build Coastguard Worker   data.metricId = metricId;
612*84e33947SAndroid Build Coastguard Worker   data.encodedMetric = encodedMetric;
613*84e33947SAndroid Build Coastguard Worker   data.encodedMetricLen = encodedMetricLen;
614*84e33947SAndroid Build Coastguard Worker 
615*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
616*84e33947SAndroid Build Coastguard Worker     const auto *data = static_cast<const MetricLogData *>(cookie);
617*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeMetricLog(
618*84e33947SAndroid Build Coastguard Worker         builder, data->metricId, data->encodedMetric, data->encodedMetricLen);
619*84e33947SAndroid Build Coastguard Worker   };
620*84e33947SAndroid Build Coastguard Worker 
621*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialSize = 52;
622*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::MetricLog, kInitialSize,
623*84e33947SAndroid Build Coastguard Worker                          msgBuilder, &data);
624*84e33947SAndroid Build Coastguard Worker   return true;
625*84e33947SAndroid Build Coastguard Worker }
626*84e33947SAndroid Build Coastguard Worker 
flushOutboundQueue()627*84e33947SAndroid Build Coastguard Worker bool HostLinkBase::flushOutboundQueue() {
628*84e33947SAndroid Build Coastguard Worker   int waitCount = 5;
629*84e33947SAndroid Build Coastguard Worker 
630*84e33947SAndroid Build Coastguard Worker   FARF(MEDIUM, "Draining message queue");
631*84e33947SAndroid Build Coastguard Worker   while (!gOutboundQueue.empty() && waitCount-- > 0) {
632*84e33947SAndroid Build Coastguard Worker     timer_sleep(kPollingIntervalUsec, T_USEC, true /* non_deferrable */);
633*84e33947SAndroid Build Coastguard Worker   }
634*84e33947SAndroid Build Coastguard Worker 
635*84e33947SAndroid Build Coastguard Worker   return (waitCount >= 0);
636*84e33947SAndroid Build Coastguard Worker }
637*84e33947SAndroid Build Coastguard Worker 
sendLogMessage(const uint8_t * logMessage,size_t logMessageSize)638*84e33947SAndroid Build Coastguard Worker void HostLinkBase::sendLogMessage(const uint8_t *logMessage,
639*84e33947SAndroid Build Coastguard Worker                                   size_t logMessageSize) {
640*84e33947SAndroid Build Coastguard Worker   struct LogMessageData {
641*84e33947SAndroid Build Coastguard Worker     const uint8_t *logMsg;
642*84e33947SAndroid Build Coastguard Worker     size_t logMsgSize;
643*84e33947SAndroid Build Coastguard Worker   };
644*84e33947SAndroid Build Coastguard Worker 
645*84e33947SAndroid Build Coastguard Worker   LogMessageData logMessageData;
646*84e33947SAndroid Build Coastguard Worker 
647*84e33947SAndroid Build Coastguard Worker   logMessageData.logMsg = logMessage;
648*84e33947SAndroid Build Coastguard Worker   logMessageData.logMsgSize = logMessageSize;
649*84e33947SAndroid Build Coastguard Worker 
650*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
651*84e33947SAndroid Build Coastguard Worker     const auto *data = static_cast<const LogMessageData *>(cookie);
652*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeLogMessages(builder, data->logMsg,
653*84e33947SAndroid Build Coastguard Worker                                         data->logMsgSize);
654*84e33947SAndroid Build Coastguard Worker   };
655*84e33947SAndroid Build Coastguard Worker 
656*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialSize = 128;
657*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::EncodedLogMessage, kInitialSize,
658*84e33947SAndroid Build Coastguard Worker                          msgBuilder, &logMessageData);
659*84e33947SAndroid Build Coastguard Worker }
660*84e33947SAndroid Build Coastguard Worker 
sendLogMessageV2(const uint8_t * logMessage,size_t logMessageSize,uint32_t numLogsDropped)661*84e33947SAndroid Build Coastguard Worker void HostLinkBase::sendLogMessageV2(const uint8_t *logMessage,
662*84e33947SAndroid Build Coastguard Worker                                     size_t logMessageSize,
663*84e33947SAndroid Build Coastguard Worker                                     uint32_t numLogsDropped) {
664*84e33947SAndroid Build Coastguard Worker   struct LogMessageData {
665*84e33947SAndroid Build Coastguard Worker     const uint8_t *logMsg;
666*84e33947SAndroid Build Coastguard Worker     size_t logMsgSize;
667*84e33947SAndroid Build Coastguard Worker     uint32_t numLogsDropped;
668*84e33947SAndroid Build Coastguard Worker   };
669*84e33947SAndroid Build Coastguard Worker 
670*84e33947SAndroid Build Coastguard Worker   LogMessageData logMessageData{logMessage, logMessageSize, numLogsDropped};
671*84e33947SAndroid Build Coastguard Worker 
672*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
673*84e33947SAndroid Build Coastguard Worker     const auto *data = static_cast<const LogMessageData *>(cookie);
674*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeLogMessagesV2(
675*84e33947SAndroid Build Coastguard Worker         builder, data->logMsg, data->logMsgSize, data->numLogsDropped);
676*84e33947SAndroid Build Coastguard Worker   };
677*84e33947SAndroid Build Coastguard Worker 
678*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialSize = 128;
679*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::EncodedLogMessage, kInitialSize,
680*84e33947SAndroid Build Coastguard Worker                          msgBuilder, &logMessageData);
681*84e33947SAndroid Build Coastguard Worker }
682*84e33947SAndroid Build Coastguard Worker 
sendNanConfiguration(bool enable)683*84e33947SAndroid Build Coastguard Worker void HostLinkBase::sendNanConfiguration(bool enable) {
684*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
685*84e33947SAndroid Build Coastguard Worker     const auto *data = static_cast<const bool *>(cookie);
686*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeNanConfigurationRequest(builder, *data);
687*84e33947SAndroid Build Coastguard Worker   };
688*84e33947SAndroid Build Coastguard Worker 
689*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialSize = 48;
690*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::NanConfigurationRequest,
691*84e33947SAndroid Build Coastguard Worker                          kInitialSize, msgBuilder, &enable);
692*84e33947SAndroid Build Coastguard Worker }
693*84e33947SAndroid Build Coastguard Worker 
shutdown()694*84e33947SAndroid Build Coastguard Worker void HostLinkBase::shutdown() {
695*84e33947SAndroid Build Coastguard Worker   // Push a null message so the blocking call in chre_slpi_get_message_to_host()
696*84e33947SAndroid Build Coastguard Worker   // returns and the host can exit cleanly. If the queue is full, try again to
697*84e33947SAndroid Build Coastguard Worker   // avoid getting stuck (no other new messages should be entering the queue at
698*84e33947SAndroid Build Coastguard Worker   // this time). Don't wait too long as the host-side binary may have died in
699*84e33947SAndroid Build Coastguard Worker   // a state where it's not blocked in chre_slpi_get_message_to_host().
700*84e33947SAndroid Build Coastguard Worker   int retryCount = 5;
701*84e33947SAndroid Build Coastguard Worker   FARF(MEDIUM, "Shutting down host link");
702*84e33947SAndroid Build Coastguard Worker   while (!enqueueMessage(PendingMessage(PendingMessageType::Shutdown)) &&
703*84e33947SAndroid Build Coastguard Worker          --retryCount > 0) {
704*84e33947SAndroid Build Coastguard Worker     timer_sleep(kPollingIntervalUsec, T_USEC, true /* non_deferrable */);
705*84e33947SAndroid Build Coastguard Worker   }
706*84e33947SAndroid Build Coastguard Worker 
707*84e33947SAndroid Build Coastguard Worker   if (retryCount <= 0) {
708*84e33947SAndroid Build Coastguard Worker     // Don't use LOGE, as it may involve trying to send a message
709*84e33947SAndroid Build Coastguard Worker     FARF(ERROR,
710*84e33947SAndroid Build Coastguard Worker          "No room in outbound queue for shutdown message and host not "
711*84e33947SAndroid Build Coastguard Worker          "draining queue!");
712*84e33947SAndroid Build Coastguard Worker   } else {
713*84e33947SAndroid Build Coastguard Worker     // We were able to push the shutdown message. Wait for the queue to
714*84e33947SAndroid Build Coastguard Worker     // completely flush before returning.
715*84e33947SAndroid Build Coastguard Worker     if (!flushOutboundQueue()) {
716*84e33947SAndroid Build Coastguard Worker       FARF(ERROR, "Host took too long to drain outbound queue; exiting anyway");
717*84e33947SAndroid Build Coastguard Worker     } else {
718*84e33947SAndroid Build Coastguard Worker       FARF(MEDIUM, "Finished draining queue");
719*84e33947SAndroid Build Coastguard Worker     }
720*84e33947SAndroid Build Coastguard Worker   }
721*84e33947SAndroid Build Coastguard Worker }
722*84e33947SAndroid Build Coastguard Worker 
sendAudioRequest()723*84e33947SAndroid Build Coastguard Worker void sendAudioRequest() {
724*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
725*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeLowPowerMicAccessRequest(builder);
726*84e33947SAndroid Build Coastguard Worker   };
727*84e33947SAndroid Build Coastguard Worker 
728*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialSize = 32;
729*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::LowPowerMicAccessRequest,
730*84e33947SAndroid Build Coastguard Worker                          kInitialSize, msgBuilder, nullptr);
731*84e33947SAndroid Build Coastguard Worker }
732*84e33947SAndroid Build Coastguard Worker 
sendAudioRelease()733*84e33947SAndroid Build Coastguard Worker void sendAudioRelease() {
734*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
735*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeLowPowerMicAccessRelease(builder);
736*84e33947SAndroid Build Coastguard Worker   };
737*84e33947SAndroid Build Coastguard Worker 
738*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialSize = 32;
739*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::LowPowerMicAccessRelease,
740*84e33947SAndroid Build Coastguard Worker                          kInitialSize, msgBuilder, nullptr);
741*84e33947SAndroid Build Coastguard Worker }
742*84e33947SAndroid Build Coastguard Worker 
sendFragmentResponse(uint16_t hostClientId,uint32_t transactionId,uint32_t fragmentId,bool success)743*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::sendFragmentResponse(uint16_t hostClientId,
744*84e33947SAndroid Build Coastguard Worker                                                uint32_t transactionId,
745*84e33947SAndroid Build Coastguard Worker                                                uint32_t fragmentId,
746*84e33947SAndroid Build Coastguard Worker                                                bool success) {
747*84e33947SAndroid Build Coastguard Worker   struct FragmentedLoadInfoResponse {
748*84e33947SAndroid Build Coastguard Worker     uint16_t hostClientId;
749*84e33947SAndroid Build Coastguard Worker     uint32_t transactionId;
750*84e33947SAndroid Build Coastguard Worker     uint32_t fragmentId;
751*84e33947SAndroid Build Coastguard Worker     bool success;
752*84e33947SAndroid Build Coastguard Worker   };
753*84e33947SAndroid Build Coastguard Worker 
754*84e33947SAndroid Build Coastguard Worker   auto msgBuilder = [](ChreFlatBufferBuilder &builder, void *cookie) {
755*84e33947SAndroid Build Coastguard Worker     auto *cbData = static_cast<FragmentedLoadInfoResponse *>(cookie);
756*84e33947SAndroid Build Coastguard Worker     HostProtocolChre::encodeLoadNanoappResponse(
757*84e33947SAndroid Build Coastguard Worker         builder, cbData->hostClientId, cbData->transactionId, cbData->success,
758*84e33947SAndroid Build Coastguard Worker         cbData->fragmentId);
759*84e33947SAndroid Build Coastguard Worker   };
760*84e33947SAndroid Build Coastguard Worker 
761*84e33947SAndroid Build Coastguard Worker   FragmentedLoadInfoResponse response = {
762*84e33947SAndroid Build Coastguard Worker       .hostClientId = hostClientId,
763*84e33947SAndroid Build Coastguard Worker       .transactionId = transactionId,
764*84e33947SAndroid Build Coastguard Worker       .fragmentId = fragmentId,
765*84e33947SAndroid Build Coastguard Worker       .success = success,
766*84e33947SAndroid Build Coastguard Worker   };
767*84e33947SAndroid Build Coastguard Worker   constexpr size_t kInitialBufferSize = 48;
768*84e33947SAndroid Build Coastguard Worker   buildAndEnqueueMessage(PendingMessageType::LoadNanoappResponse,
769*84e33947SAndroid Build Coastguard Worker                          kInitialBufferSize, msgBuilder, &response);
770*84e33947SAndroid Build Coastguard Worker }
771*84e33947SAndroid Build Coastguard Worker 
handleNanoappMessage(uint64_t appId,uint32_t messageType,uint16_t hostEndpoint,const void * messageData,size_t messageDataLen,bool isReliable,uint32_t messageSequenceNumber)772*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleNanoappMessage(
773*84e33947SAndroid Build Coastguard Worker     uint64_t appId, uint32_t messageType, uint16_t hostEndpoint,
774*84e33947SAndroid Build Coastguard Worker     const void *messageData, size_t messageDataLen, bool isReliable,
775*84e33947SAndroid Build Coastguard Worker     uint32_t messageSequenceNumber) {
776*84e33947SAndroid Build Coastguard Worker   LOGD("Parsed nanoapp message from host: app ID 0x%016" PRIx64
777*84e33947SAndroid Build Coastguard Worker        ", endpoint "
778*84e33947SAndroid Build Coastguard Worker        "0x%" PRIx16 ", msgType %" PRIu32 ", payload size %zu",
779*84e33947SAndroid Build Coastguard Worker        appId, hostEndpoint, messageType, messageDataLen);
780*84e33947SAndroid Build Coastguard Worker 
781*84e33947SAndroid Build Coastguard Worker   HostCommsManager &manager =
782*84e33947SAndroid Build Coastguard Worker       EventLoopManagerSingleton::get()->getHostCommsManager();
783*84e33947SAndroid Build Coastguard Worker   manager.sendMessageToNanoappFromHost(appId, messageType, hostEndpoint,
784*84e33947SAndroid Build Coastguard Worker                                        messageData, messageDataLen, isReliable,
785*84e33947SAndroid Build Coastguard Worker                                        messageSequenceNumber);
786*84e33947SAndroid Build Coastguard Worker }
787*84e33947SAndroid Build Coastguard Worker 
handleMessageDeliveryStatus(uint32_t,uint8_t)788*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleMessageDeliveryStatus(
789*84e33947SAndroid Build Coastguard Worker     uint32_t /* messageSequenceNumber */, uint8_t /* errorCode */) {}
790*84e33947SAndroid Build Coastguard Worker 
handleHubInfoRequest(uint16_t hostClientId)791*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleHubInfoRequest(uint16_t hostClientId) {
792*84e33947SAndroid Build Coastguard Worker   // We generate the response in the context of chre_slpi_get_message_to_host
793*84e33947SAndroid Build Coastguard Worker   LOGD("Hub info request from client ID %" PRIu16, hostClientId);
794*84e33947SAndroid Build Coastguard Worker   enqueueMessage(
795*84e33947SAndroid Build Coastguard Worker       PendingMessage(PendingMessageType::HubInfoResponse, hostClientId));
796*84e33947SAndroid Build Coastguard Worker }
797*84e33947SAndroid Build Coastguard Worker 
handleNanoappListRequest(uint16_t hostClientId)798*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleNanoappListRequest(uint16_t hostClientId) {
799*84e33947SAndroid Build Coastguard Worker   auto callback = [](uint16_t /*type*/, void *data, void * /*extraData*/) {
800*84e33947SAndroid Build Coastguard Worker     uint16_t cbHostClientId = NestedDataPtr<uint16_t>(data);
801*84e33947SAndroid Build Coastguard Worker 
802*84e33947SAndroid Build Coastguard Worker     NanoappListData cbData = {};
803*84e33947SAndroid Build Coastguard Worker     cbData.hostClientId = cbHostClientId;
804*84e33947SAndroid Build Coastguard Worker 
805*84e33947SAndroid Build Coastguard Worker     size_t expectedNanoappCount =
806*84e33947SAndroid Build Coastguard Worker         EventLoopManagerSingleton::get()->getEventLoop().getNanoappCount();
807*84e33947SAndroid Build Coastguard Worker     if (!cbData.nanoappEntries.reserve(expectedNanoappCount)) {
808*84e33947SAndroid Build Coastguard Worker       LOG_OOM();
809*84e33947SAndroid Build Coastguard Worker     } else {
810*84e33947SAndroid Build Coastguard Worker       constexpr size_t kFixedOverhead = 48;
811*84e33947SAndroid Build Coastguard Worker       constexpr size_t kPerNanoappSize = 32;
812*84e33947SAndroid Build Coastguard Worker       size_t initialBufferSize =
813*84e33947SAndroid Build Coastguard Worker           (kFixedOverhead + expectedNanoappCount * kPerNanoappSize);
814*84e33947SAndroid Build Coastguard Worker 
815*84e33947SAndroid Build Coastguard Worker       buildAndEnqueueMessage(PendingMessageType::NanoappListResponse,
816*84e33947SAndroid Build Coastguard Worker                              initialBufferSize, buildNanoappListResponse,
817*84e33947SAndroid Build Coastguard Worker                              &cbData);
818*84e33947SAndroid Build Coastguard Worker     }
819*84e33947SAndroid Build Coastguard Worker   };
820*84e33947SAndroid Build Coastguard Worker 
821*84e33947SAndroid Build Coastguard Worker   LOGD("Nanoapp list request from client ID %" PRIu16, hostClientId);
822*84e33947SAndroid Build Coastguard Worker   EventLoopManagerSingleton::get()->deferCallback(
823*84e33947SAndroid Build Coastguard Worker       SystemCallbackType::NanoappListResponse,
824*84e33947SAndroid Build Coastguard Worker       NestedDataPtr<uint16_t>(hostClientId), callback);
825*84e33947SAndroid Build Coastguard Worker }
826*84e33947SAndroid Build Coastguard Worker 
handleLoadNanoappRequest(uint16_t hostClientId,uint32_t transactionId,uint64_t appId,uint32_t appVersion,uint32_t appFlags,uint32_t targetApiVersion,const void * buffer,size_t bufferLen,const char * appFileName,uint32_t fragmentId,size_t appBinaryLen,bool respondBeforeStart)827*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleLoadNanoappRequest(
828*84e33947SAndroid Build Coastguard Worker     uint16_t hostClientId, uint32_t transactionId, uint64_t appId,
829*84e33947SAndroid Build Coastguard Worker     uint32_t appVersion, uint32_t appFlags, uint32_t targetApiVersion,
830*84e33947SAndroid Build Coastguard Worker     const void *buffer, size_t bufferLen, const char *appFileName,
831*84e33947SAndroid Build Coastguard Worker     uint32_t fragmentId, size_t appBinaryLen, bool respondBeforeStart) {
832*84e33947SAndroid Build Coastguard Worker   if (appFileName == nullptr) {
833*84e33947SAndroid Build Coastguard Worker     loadNanoappData(hostClientId, transactionId, appId, appVersion, appFlags,
834*84e33947SAndroid Build Coastguard Worker                     targetApiVersion, buffer, bufferLen, fragmentId,
835*84e33947SAndroid Build Coastguard Worker                     appBinaryLen, respondBeforeStart);
836*84e33947SAndroid Build Coastguard Worker     return;
837*84e33947SAndroid Build Coastguard Worker   }
838*84e33947SAndroid Build Coastguard Worker 
839*84e33947SAndroid Build Coastguard Worker   UniquePtr<Nanoapp> pendingNanoapp =
840*84e33947SAndroid Build Coastguard Worker       handleLoadNanoappFile(hostClientId, transactionId, appId, appVersion,
841*84e33947SAndroid Build Coastguard Worker                             targetApiVersion, appFileName);
842*84e33947SAndroid Build Coastguard Worker 
843*84e33947SAndroid Build Coastguard Worker   if (!pendingNanoapp.isNull()) {
844*84e33947SAndroid Build Coastguard Worker     auto cbData = MakeUnique<LoadNanoappCallbackData>();
845*84e33947SAndroid Build Coastguard Worker     if (cbData.isNull()) {
846*84e33947SAndroid Build Coastguard Worker       LOG_OOM();
847*84e33947SAndroid Build Coastguard Worker     } else {
848*84e33947SAndroid Build Coastguard Worker       cbData->transactionId = transactionId;
849*84e33947SAndroid Build Coastguard Worker       cbData->hostClientId = hostClientId;
850*84e33947SAndroid Build Coastguard Worker       cbData->appId = appId;
851*84e33947SAndroid Build Coastguard Worker       cbData->fragmentId = fragmentId;
852*84e33947SAndroid Build Coastguard Worker       cbData->nanoapp = std::move(pendingNanoapp);
853*84e33947SAndroid Build Coastguard Worker 
854*84e33947SAndroid Build Coastguard Worker       // Note that if this fails, we'll generate the error response in
855*84e33947SAndroid Build Coastguard Worker       // the normal deferred callback
856*84e33947SAndroid Build Coastguard Worker       EventLoopManagerSingleton::get()->deferCallback(
857*84e33947SAndroid Build Coastguard Worker           SystemCallbackType::FinishLoadingNanoapp, std::move(cbData),
858*84e33947SAndroid Build Coastguard Worker           finishLoadingNanoappCallback);
859*84e33947SAndroid Build Coastguard Worker     }
860*84e33947SAndroid Build Coastguard Worker   }
861*84e33947SAndroid Build Coastguard Worker }
862*84e33947SAndroid Build Coastguard Worker 
handleUnloadNanoappRequest(uint16_t hostClientId,uint32_t transactionId,uint64_t appId,bool allowSystemNanoappUnload)863*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleUnloadNanoappRequest(
864*84e33947SAndroid Build Coastguard Worker     uint16_t hostClientId, uint32_t transactionId, uint64_t appId,
865*84e33947SAndroid Build Coastguard Worker     bool allowSystemNanoappUnload) {
866*84e33947SAndroid Build Coastguard Worker   LOGD("Unload nanoapp request (txnID %" PRIu32 ") for appId 0x%016" PRIx64
867*84e33947SAndroid Build Coastguard Worker        " system %d",
868*84e33947SAndroid Build Coastguard Worker        transactionId, appId, allowSystemNanoappUnload);
869*84e33947SAndroid Build Coastguard Worker   auto cbData = MakeUnique<UnloadNanoappCallbackData>();
870*84e33947SAndroid Build Coastguard Worker   if (cbData == nullptr) {
871*84e33947SAndroid Build Coastguard Worker     LOG_OOM();
872*84e33947SAndroid Build Coastguard Worker   } else {
873*84e33947SAndroid Build Coastguard Worker     cbData->appId = appId;
874*84e33947SAndroid Build Coastguard Worker     cbData->transactionId = transactionId;
875*84e33947SAndroid Build Coastguard Worker     cbData->hostClientId = hostClientId;
876*84e33947SAndroid Build Coastguard Worker     cbData->allowSystemNanoappUnload = allowSystemNanoappUnload;
877*84e33947SAndroid Build Coastguard Worker 
878*84e33947SAndroid Build Coastguard Worker     EventLoopManagerSingleton::get()->deferCallback(
879*84e33947SAndroid Build Coastguard Worker         SystemCallbackType::HandleUnloadNanoapp, std::move(cbData),
880*84e33947SAndroid Build Coastguard Worker         handleUnloadNanoappCallback);
881*84e33947SAndroid Build Coastguard Worker   }
882*84e33947SAndroid Build Coastguard Worker }
883*84e33947SAndroid Build Coastguard Worker 
handleTimeSyncMessage(int64_t offset)884*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleTimeSyncMessage(int64_t offset) {
885*84e33947SAndroid Build Coastguard Worker   SystemTime::setEstimatedHostTimeOffset(offset);
886*84e33947SAndroid Build Coastguard Worker 
887*84e33947SAndroid Build Coastguard Worker   // Schedule a time sync request since offset may drift
888*84e33947SAndroid Build Coastguard Worker   constexpr Seconds kClockDriftTimeSyncPeriod =
889*84e33947SAndroid Build Coastguard Worker       Seconds(60 * 60 * 6);  // 6 hours
890*84e33947SAndroid Build Coastguard Worker   setTimeSyncRequestTimer(kClockDriftTimeSyncPeriod);
891*84e33947SAndroid Build Coastguard Worker }
892*84e33947SAndroid Build Coastguard Worker 
handleDebugDumpRequest(uint16_t hostClientId)893*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleDebugDumpRequest(uint16_t hostClientId) {
894*84e33947SAndroid Build Coastguard Worker   if (!chre::EventLoopManagerSingleton::get()
895*84e33947SAndroid Build Coastguard Worker            ->getDebugDumpManager()
896*84e33947SAndroid Build Coastguard Worker            .onDebugDumpRequested(hostClientId)) {
897*84e33947SAndroid Build Coastguard Worker     LOGE("Couldn't trigger debug dump process");
898*84e33947SAndroid Build Coastguard Worker     sendDebugDumpResponse(hostClientId, false /*success*/, 0 /*dataCount*/);
899*84e33947SAndroid Build Coastguard Worker   }
900*84e33947SAndroid Build Coastguard Worker }
901*84e33947SAndroid Build Coastguard Worker 
handleSettingChangeMessage(fbs::Setting setting,fbs::SettingState state)902*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleSettingChangeMessage(fbs::Setting setting,
903*84e33947SAndroid Build Coastguard Worker                                                      fbs::SettingState state) {
904*84e33947SAndroid Build Coastguard Worker   Setting chreSetting;
905*84e33947SAndroid Build Coastguard Worker   bool chreSettingEnabled;
906*84e33947SAndroid Build Coastguard Worker   if (HostProtocolChre::getSettingFromFbs(setting, &chreSetting) &&
907*84e33947SAndroid Build Coastguard Worker       HostProtocolChre::getSettingEnabledFromFbs(state, &chreSettingEnabled)) {
908*84e33947SAndroid Build Coastguard Worker     EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
909*84e33947SAndroid Build Coastguard Worker         chreSetting, chreSettingEnabled);
910*84e33947SAndroid Build Coastguard Worker   }
911*84e33947SAndroid Build Coastguard Worker }
912*84e33947SAndroid Build Coastguard Worker 
handleSelfTestRequest(uint16_t hostClientId)913*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleSelfTestRequest(uint16_t hostClientId) {
914*84e33947SAndroid Build Coastguard Worker   // TODO(b/182201569): Run test
915*84e33947SAndroid Build Coastguard Worker   bool success = true;
916*84e33947SAndroid Build Coastguard Worker   sendSelfTestResponse(hostClientId, success);
917*84e33947SAndroid Build Coastguard Worker }
918*84e33947SAndroid Build Coastguard Worker 
handlePulseRequest()919*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handlePulseRequest() {}
920*84e33947SAndroid Build Coastguard Worker 
handleNanConfigurationUpdate(bool enabled)921*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleNanConfigurationUpdate(bool enabled) {
922*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_WIFI_NAN_SUPPORT_ENABLED
923*84e33947SAndroid Build Coastguard Worker   EventLoopManagerSingleton::get()
924*84e33947SAndroid Build Coastguard Worker       ->getWifiRequestManager()
925*84e33947SAndroid Build Coastguard Worker       .updateNanAvailability(enabled);
926*84e33947SAndroid Build Coastguard Worker #else
927*84e33947SAndroid Build Coastguard Worker   UNUSED_VAR(enabled);
928*84e33947SAndroid Build Coastguard Worker #endif  // CHRE_WIFI_NAN_SUPPORT_ENABLED
929*84e33947SAndroid Build Coastguard Worker }
930*84e33947SAndroid Build Coastguard Worker 
handleBtSocketOpen(uint16_t,uint64_t,const char *,uint64_t,uint64_t,uint32_t,uint32_t,uint32_t,uint32_t,uint32_t,uint32_t,uint32_t,uint32_t,uint32_t,uint32_t)931*84e33947SAndroid Build Coastguard Worker void HostMessageHandlers::handleBtSocketOpen(
932*84e33947SAndroid Build Coastguard Worker     uint16_t /* hostClientId */, uint64_t /* socketId */,
933*84e33947SAndroid Build Coastguard Worker     const char * /* name */, uint64_t /* endpointId */, uint64_t /* hubId */,
934*84e33947SAndroid Build Coastguard Worker     uint32_t /* aclConnectionHandle */, uint32_t /* localCid */,
935*84e33947SAndroid Build Coastguard Worker     uint32_t /* remoteCid */, uint32_t /* psm */, uint32_t /* localMtu */,
936*84e33947SAndroid Build Coastguard Worker     uint32_t /* remoteMtu */, uint32_t /* localMps */, uint32_t /* remoteMps */,
937*84e33947SAndroid Build Coastguard Worker     uint32_t /* initialRxCredits */, uint32_t /* initialTxCredits */) {
938*84e33947SAndroid Build Coastguard Worker   LOGE("BT Socket offload not supported");
939*84e33947SAndroid Build Coastguard Worker }
940*84e33947SAndroid Build Coastguard Worker 
941*84e33947SAndroid Build Coastguard Worker }  // namespace chre
942