1 /*
2  * Copyright (C) 2017 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/platform/shared/host_protocol_chre.h"
18 
19 #include <inttypes.h>
20 #include <string.h>
21 
22 #include "chre/core/event_loop_manager.h"
23 #include "chre/core/host_endpoint_manager.h"
24 #include "chre/platform/log.h"
25 #include "chre/platform/shared/generated/host_messages_generated.h"
26 #include "chre/util/macros.h"
27 
28 using flatbuffers::Offset;
29 using flatbuffers::Vector;
30 
31 namespace chre {
32 
33 // This is similar to getStringFromByteVector in host_protocol_host.h. Ensure
34 // that method's implementation is kept in sync with this.
getStringFromByteVector(const flatbuffers::Vector<int8_t> * vec)35 const char *getStringFromByteVector(const flatbuffers::Vector<int8_t> *vec) {
36   constexpr int8_t kNullChar = static_cast<int8_t>('\0');
37   const char *str = nullptr;
38 
39   // Check that the vector is present, non-empty, and null-terminated
40   if (vec != nullptr && vec->size() > 0 &&
41       (*vec)[vec->size() - 1] == kNullChar) {
42     str = reinterpret_cast<const char *>(vec->Data());
43   }
44 
45   return str;
46 }
47 
decodeMessageFromHost(const void * message,size_t messageLen)48 bool HostProtocolChre::decodeMessageFromHost(const void *message,
49                                              size_t messageLen) {
50   bool success = verifyMessage(message, messageLen);
51   if (!success) {
52     LOGE("Dropping invalid/corrupted message from host (length %zu)",
53          messageLen);
54   } else {
55     const fbs::MessageContainer *container = fbs::GetMessageContainer(message);
56     uint16_t hostClientId = container->host_addr()->client_id();
57 
58     switch (container->message_type()) {
59       case fbs::ChreMessage::NanoappMessage: {
60         const auto *nanoappMsg =
61             static_cast<const fbs::NanoappMessage *>(container->message());
62         // Required field; verifier ensures that this is not null (though it
63         // may be empty)
64         const flatbuffers::Vector<uint8_t> *msgData = nanoappMsg->message();
65         HostMessageHandlers::handleNanoappMessage(
66             nanoappMsg->app_id(), nanoappMsg->message_type(),
67             nanoappMsg->host_endpoint(), msgData->data(), msgData->size(),
68             nanoappMsg->is_reliable(), nanoappMsg->message_sequence_number());
69         break;
70       }
71 
72       case fbs::ChreMessage::MessageDeliveryStatus: {
73         const auto *status = static_cast<const fbs::MessageDeliveryStatus *>(
74             container->message());
75         HostMessageHandlers::handleMessageDeliveryStatus(
76             status->message_sequence_number(), status->error_code());
77         break;
78       }
79 
80       case fbs::ChreMessage::HubInfoRequest:
81         HostMessageHandlers::handleHubInfoRequest(hostClientId);
82         break;
83 
84       case fbs::ChreMessage::NanoappListRequest:
85         HostMessageHandlers::handleNanoappListRequest(hostClientId);
86         break;
87 
88       case fbs::ChreMessage::LoadNanoappRequest: {
89         const auto *request =
90             static_cast<const fbs::LoadNanoappRequest *>(container->message());
91         const flatbuffers::Vector<uint8_t> *appBinary = request->app_binary();
92         const char *appBinaryFilename =
93             getStringFromByteVector(request->app_binary_file_name());
94         HostMessageHandlers::handleLoadNanoappRequest(
95             hostClientId, request->transaction_id(), request->app_id(),
96             request->app_version(), request->app_flags(),
97             request->target_api_version(), appBinary->data(), appBinary->size(),
98             appBinaryFilename, request->fragment_id(),
99             request->total_app_size(), request->respond_before_start());
100         break;
101       }
102 
103       case fbs::ChreMessage::UnloadNanoappRequest: {
104         const auto *request = static_cast<const fbs::UnloadNanoappRequest *>(
105             container->message());
106         HostMessageHandlers::handleUnloadNanoappRequest(
107             hostClientId, request->transaction_id(), request->app_id(),
108             request->allow_system_nanoapp_unload());
109         break;
110       }
111 
112       case fbs::ChreMessage::TimeSyncMessage: {
113         const auto *request =
114             static_cast<const fbs::TimeSyncMessage *>(container->message());
115         HostMessageHandlers::handleTimeSyncMessage(request->offset());
116         break;
117       }
118 
119       case fbs::ChreMessage::DebugDumpRequest:
120         HostMessageHandlers::handleDebugDumpRequest(hostClientId);
121         break;
122 
123       case fbs::ChreMessage::SettingChangeMessage: {
124         const auto *settingMessage =
125             static_cast<const fbs::SettingChangeMessage *>(
126                 container->message());
127         HostMessageHandlers::handleSettingChangeMessage(
128             settingMessage->setting(), settingMessage->state());
129         break;
130       }
131 
132       case fbs::ChreMessage::SelfTestRequest: {
133         HostMessageHandlers::handleSelfTestRequest(hostClientId);
134         break;
135       }
136 
137       case fbs::ChreMessage::HostEndpointConnected: {
138         const auto *connectedMessage =
139             static_cast<const fbs::HostEndpointConnected *>(
140                 container->message());
141         struct chreHostEndpointInfo info;
142         info.hostEndpointId = connectedMessage->host_endpoint();
143         info.hostEndpointType = connectedMessage->type();
144         if (strlen(reinterpret_cast<const char *>(
145                 connectedMessage->package_name()->data())) > 0) {
146           info.isNameValid = true;
147           memcpy(&info.packageName[0], connectedMessage->package_name()->data(),
148                  MIN(connectedMessage->package_name()->size(),
149                      CHRE_MAX_ENDPOINT_NAME_LEN));
150           info.packageName[CHRE_MAX_ENDPOINT_NAME_LEN - 1] = '\0';
151         } else {
152           info.isNameValid = false;
153         }
154         if (strlen(reinterpret_cast<const char *>(
155                 connectedMessage->attribution_tag()->data())) > 0) {
156           info.isTagValid = true;
157           memcpy(&info.attributionTag[0],
158                  connectedMessage->attribution_tag()->data(),
159                  MIN(connectedMessage->attribution_tag()->size(),
160                      CHRE_MAX_ENDPOINT_TAG_LEN));
161           info.attributionTag[CHRE_MAX_ENDPOINT_NAME_LEN - 1] = '\0';
162         } else {
163           info.isTagValid = false;
164         }
165 
166         EventLoopManagerSingleton::get()
167             ->getHostEndpointManager()
168             .postHostEndpointConnected(info);
169         break;
170       }
171 
172       case fbs::ChreMessage::HostEndpointDisconnected: {
173         const auto *disconnectedMessage =
174             static_cast<const fbs::HostEndpointDisconnected *>(
175                 container->message());
176         EventLoopManagerSingleton::get()
177             ->getHostEndpointManager()
178             .postHostEndpointDisconnected(disconnectedMessage->host_endpoint());
179         break;
180       }
181 
182       case fbs::ChreMessage::NanConfigurationUpdate: {
183         const auto *nanConfigUpdateMessage =
184             static_cast<const fbs::NanConfigurationUpdate *>(
185                 container->message());
186         HostMessageHandlers::handleNanConfigurationUpdate(
187             nanConfigUpdateMessage->enabled());
188         break;
189       }
190 
191       case fbs::ChreMessage::DebugConfiguration: {
192         const auto *debugConfiguration =
193             static_cast<const fbs::DebugConfiguration *>(container->message());
194         HostMessageHandlers::handleDebugConfiguration(debugConfiguration);
195         break;
196       }
197 
198       case fbs::ChreMessage::PulseRequest: {
199         HostMessageHandlers::handlePulseRequest();
200         break;
201       }
202 
203       default:
204         LOGW("Got invalid/unexpected message type %" PRIu8,
205              static_cast<uint8_t>(container->message_type()));
206         success = false;
207     }
208   }
209 
210   return success;
211 }
212 
encodeHubInfoResponse(ChreFlatBufferBuilder & builder,const char * name,const char * vendor,const char * toolchain,uint32_t legacyPlatformVersion,uint32_t legacyToolchainVersion,float peakMips,float stoppedPower,float sleepPower,float peakPower,uint32_t maxMessageLen,uint64_t platformId,uint32_t version,uint16_t hostClientId,bool supportsReliableMessages)213 void HostProtocolChre::encodeHubInfoResponse(
214     ChreFlatBufferBuilder &builder, const char *name, const char *vendor,
215     const char *toolchain, uint32_t legacyPlatformVersion,
216     uint32_t legacyToolchainVersion, float peakMips, float stoppedPower,
217     float sleepPower, float peakPower, uint32_t maxMessageLen,
218     uint64_t platformId, uint32_t version, uint16_t hostClientId,
219     bool supportsReliableMessages) {
220   auto nameOffset = addStringAsByteVector(builder, name);
221   auto vendorOffset = addStringAsByteVector(builder, vendor);
222   auto toolchainOffset = addStringAsByteVector(builder, toolchain);
223 
224   auto response = fbs::CreateHubInfoResponse(
225       builder, nameOffset, vendorOffset, toolchainOffset, legacyPlatformVersion,
226       legacyToolchainVersion, peakMips, stoppedPower, sleepPower, peakPower,
227       maxMessageLen, platformId, version, supportsReliableMessages);
228   finalize(builder, fbs::ChreMessage::HubInfoResponse, response.Union(),
229            hostClientId);
230 }
231 
addNanoappListEntry(ChreFlatBufferBuilder & builder,DynamicVector<Offset<fbs::NanoappListEntry>> & offsetVector,uint64_t appId,uint32_t appVersion,bool enabled,bool isSystemNanoapp,uint32_t appPermissions,const DynamicVector<struct chreNanoappRpcService> & rpcServices)232 void HostProtocolChre::addNanoappListEntry(
233     ChreFlatBufferBuilder &builder,
234     DynamicVector<Offset<fbs::NanoappListEntry>> &offsetVector, uint64_t appId,
235     uint32_t appVersion, bool enabled, bool isSystemNanoapp,
236     uint32_t appPermissions,
237     const DynamicVector<struct chreNanoappRpcService> &rpcServices) {
238   DynamicVector<Offset<fbs::NanoappRpcService>> rpcServiceList;
239   for (const auto &service : rpcServices) {
240     Offset<fbs::NanoappRpcService> offsetService =
241         fbs::CreateNanoappRpcService(builder, service.id, service.version);
242     if (!rpcServiceList.push_back(offsetService)) {
243       LOGE("Couldn't push RPC service to list");
244     }
245   }
246 
247   auto vectorOffset =
248       builder.CreateVector<Offset<fbs::NanoappRpcService>>(rpcServiceList);
249   auto offset = fbs::CreateNanoappListEntry(builder, appId, appVersion, enabled,
250                                             isSystemNanoapp, appPermissions,
251                                             vectorOffset);
252 
253   if (!offsetVector.push_back(offset)) {
254     LOGE("Couldn't push nanoapp list entry offset!");
255   }
256 }
257 
finishNanoappListResponse(ChreFlatBufferBuilder & builder,DynamicVector<Offset<fbs::NanoappListEntry>> & offsetVector,uint16_t hostClientId)258 void HostProtocolChre::finishNanoappListResponse(
259     ChreFlatBufferBuilder &builder,
260     DynamicVector<Offset<fbs::NanoappListEntry>> &offsetVector,
261     uint16_t hostClientId) {
262   auto vectorOffset =
263       builder.CreateVector<Offset<fbs::NanoappListEntry>>(offsetVector);
264   auto response = fbs::CreateNanoappListResponse(builder, vectorOffset);
265   finalize(builder, fbs::ChreMessage::NanoappListResponse, response.Union(),
266            hostClientId);
267 }
268 
encodePulseResponse(ChreFlatBufferBuilder & builder)269 void HostProtocolChre::encodePulseResponse(ChreFlatBufferBuilder &builder) {
270   auto response = fbs::CreatePulseResponse(builder);
271   finalize(builder, fbs::ChreMessage::PulseResponse, response.Union());
272 }
273 
encodeLoadNanoappResponse(ChreFlatBufferBuilder & builder,uint16_t hostClientId,uint32_t transactionId,bool success,uint32_t fragmentId)274 void HostProtocolChre::encodeLoadNanoappResponse(ChreFlatBufferBuilder &builder,
275                                                  uint16_t hostClientId,
276                                                  uint32_t transactionId,
277                                                  bool success,
278                                                  uint32_t fragmentId) {
279   auto response = fbs::CreateLoadNanoappResponse(builder, transactionId,
280                                                  success, fragmentId);
281   finalize(builder, fbs::ChreMessage::LoadNanoappResponse, response.Union(),
282            hostClientId);
283 }
284 
encodeNanoappTokenDatabaseInfo(ChreFlatBufferBuilder & builder,uint16_t instanceId,uint64_t appId,uint32_t tokenDatabaseOffset,size_t tokenDatabaseSize)285 void HostProtocolChre::encodeNanoappTokenDatabaseInfo(
286     ChreFlatBufferBuilder &builder, uint16_t instanceId, uint64_t appId,
287     uint32_t tokenDatabaseOffset, size_t tokenDatabaseSize) {
288   auto response = fbs::CreateNanoappTokenDatabaseInfo(
289       builder, instanceId, appId, tokenDatabaseOffset, tokenDatabaseSize);
290   finalize(builder, fbs::ChreMessage::NanoappTokenDatabaseInfo,
291            response.Union());
292 }
293 
encodeUnloadNanoappResponse(ChreFlatBufferBuilder & builder,uint16_t hostClientId,uint32_t transactionId,bool success)294 void HostProtocolChre::encodeUnloadNanoappResponse(
295     ChreFlatBufferBuilder &builder, uint16_t hostClientId,
296     uint32_t transactionId, bool success) {
297   auto response =
298       fbs::CreateUnloadNanoappResponse(builder, transactionId, success);
299   finalize(builder, fbs::ChreMessage::UnloadNanoappResponse, response.Union(),
300            hostClientId);
301 }
302 
encodeLogMessages(ChreFlatBufferBuilder & builder,const uint8_t * logBuffer,size_t bufferSize)303 void HostProtocolChre::encodeLogMessages(ChreFlatBufferBuilder &builder,
304                                          const uint8_t *logBuffer,
305                                          size_t bufferSize) {
306   auto logBufferOffset = builder.CreateVector(
307       reinterpret_cast<const int8_t *>(logBuffer), bufferSize);
308   auto message = fbs::CreateLogMessage(builder, logBufferOffset);
309   finalize(builder, fbs::ChreMessage::LogMessage, message.Union());
310 }
311 
encodeLogMessagesV2(ChreFlatBufferBuilder & builder,const uint8_t * logBuffer,size_t bufferSize,uint32_t numLogsDropped)312 void HostProtocolChre::encodeLogMessagesV2(ChreFlatBufferBuilder &builder,
313                                            const uint8_t *logBuffer,
314                                            size_t bufferSize,
315                                            uint32_t numLogsDropped) {
316   auto logBufferOffset = builder.CreateVector(
317       reinterpret_cast<const int8_t *>(logBuffer), bufferSize);
318   auto message =
319       fbs::CreateLogMessageV2(builder, logBufferOffset, numLogsDropped);
320   finalize(builder, fbs::ChreMessage::LogMessageV2, message.Union());
321 }
322 
encodeDebugDumpData(ChreFlatBufferBuilder & builder,uint16_t hostClientId,const char * debugStr,size_t debugStrSize)323 void HostProtocolChre::encodeDebugDumpData(ChreFlatBufferBuilder &builder,
324                                            uint16_t hostClientId,
325                                            const char *debugStr,
326                                            size_t debugStrSize) {
327   auto debugStrOffset = builder.CreateVector(
328       reinterpret_cast<const int8_t *>(debugStr), debugStrSize);
329   auto message = fbs::CreateDebugDumpData(builder, debugStrOffset);
330   finalize(builder, fbs::ChreMessage::DebugDumpData, message.Union(),
331            hostClientId);
332 }
333 
encodeDebugDumpResponse(ChreFlatBufferBuilder & builder,uint16_t hostClientId,bool success,uint32_t dataCount)334 void HostProtocolChre::encodeDebugDumpResponse(ChreFlatBufferBuilder &builder,
335                                                uint16_t hostClientId,
336                                                bool success,
337                                                uint32_t dataCount) {
338   auto response = fbs::CreateDebugDumpResponse(builder, success, dataCount);
339   finalize(builder, fbs::ChreMessage::DebugDumpResponse, response.Union(),
340            hostClientId);
341 }
342 
encodeTimeSyncRequest(ChreFlatBufferBuilder & builder)343 void HostProtocolChre::encodeTimeSyncRequest(ChreFlatBufferBuilder &builder) {
344   auto request = fbs::CreateTimeSyncRequest(builder);
345   finalize(builder, fbs::ChreMessage::TimeSyncRequest, request.Union());
346 }
347 
encodeLowPowerMicAccessRequest(ChreFlatBufferBuilder & builder)348 void HostProtocolChre::encodeLowPowerMicAccessRequest(
349     ChreFlatBufferBuilder &builder) {
350   auto request = fbs::CreateLowPowerMicAccessRequest(builder);
351   finalize(builder, fbs::ChreMessage::LowPowerMicAccessRequest,
352            request.Union());
353 }
354 
encodeLowPowerMicAccessRelease(ChreFlatBufferBuilder & builder)355 void HostProtocolChre::encodeLowPowerMicAccessRelease(
356     ChreFlatBufferBuilder &builder) {
357   auto request = fbs::CreateLowPowerMicAccessRelease(builder);
358   finalize(builder, fbs::ChreMessage::LowPowerMicAccessRelease,
359            request.Union());
360 }
361 
encodeSelfTestResponse(ChreFlatBufferBuilder & builder,uint16_t hostClientId,bool success)362 void HostProtocolChre::encodeSelfTestResponse(ChreFlatBufferBuilder &builder,
363                                               uint16_t hostClientId,
364                                               bool success) {
365   auto response = fbs::CreateSelfTestResponse(builder, success);
366   finalize(builder, fbs::ChreMessage::SelfTestResponse, response.Union(),
367            hostClientId);
368 }
369 
encodeMetricLog(ChreFlatBufferBuilder & builder,uint32_t metricId,const uint8_t * encodedMsg,size_t metricSize)370 void HostProtocolChre::encodeMetricLog(ChreFlatBufferBuilder &builder,
371                                        uint32_t metricId,
372                                        const uint8_t *encodedMsg,
373                                        size_t metricSize) {
374   auto encodedMessage = builder.CreateVector(
375       reinterpret_cast<const int8_t *>(encodedMsg), metricSize);
376   auto message = fbs::CreateMetricLog(builder, metricId, encodedMessage);
377   finalize(builder, fbs::ChreMessage::MetricLog, message.Union());
378 }
379 
encodeNanConfigurationRequest(ChreFlatBufferBuilder & builder,bool enable)380 void HostProtocolChre::encodeNanConfigurationRequest(
381     ChreFlatBufferBuilder &builder, bool enable) {
382   auto request = fbs::CreateNanConfigurationRequest(builder, enable);
383   finalize(builder, fbs::ChreMessage::NanConfigurationRequest, request.Union());
384 }
385 
getSettingFromFbs(fbs::Setting setting,Setting * chreSetting)386 bool HostProtocolChre::getSettingFromFbs(fbs::Setting setting,
387                                          Setting *chreSetting) {
388   bool success = true;
389   switch (setting) {
390     case fbs::Setting::LOCATION:
391       *chreSetting = Setting::LOCATION;
392       break;
393     case fbs::Setting::WIFI_AVAILABLE:
394       *chreSetting = Setting::WIFI_AVAILABLE;
395       break;
396     case fbs::Setting::AIRPLANE_MODE:
397       *chreSetting = Setting::AIRPLANE_MODE;
398       break;
399     case fbs::Setting::MICROPHONE:
400       *chreSetting = Setting::MICROPHONE;
401       break;
402     case fbs::Setting::BLE_AVAILABLE:
403       *chreSetting = Setting::BLE_AVAILABLE;
404       break;
405     default:
406       LOGE("Unknown setting %" PRIu8, static_cast<uint8_t>(setting));
407       success = false;
408   }
409 
410   return success;
411 }
412 
getSettingEnabledFromFbs(fbs::SettingState state,bool * chreSettingEnabled)413 bool HostProtocolChre::getSettingEnabledFromFbs(fbs::SettingState state,
414                                                 bool *chreSettingEnabled) {
415   bool success = true;
416   switch (state) {
417     case fbs::SettingState::DISABLED:
418       *chreSettingEnabled = false;
419       break;
420     case fbs::SettingState::ENABLED:
421       *chreSettingEnabled = true;
422       break;
423     default:
424       LOGE("Unknown state %" PRIu8, static_cast<uint8_t>(state));
425       success = false;
426   }
427 
428   return success;
429 }
430 
431 }  // namespace chre
432