• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         break;
69       }
70 
71       case fbs::ChreMessage::HubInfoRequest:
72         HostMessageHandlers::handleHubInfoRequest(hostClientId);
73         break;
74 
75       case fbs::ChreMessage::NanoappListRequest:
76         HostMessageHandlers::handleNanoappListRequest(hostClientId);
77         break;
78 
79       case fbs::ChreMessage::LoadNanoappRequest: {
80         const auto *request =
81             static_cast<const fbs::LoadNanoappRequest *>(container->message());
82         const flatbuffers::Vector<uint8_t> *appBinary = request->app_binary();
83         const char *appBinaryFilename =
84             getStringFromByteVector(request->app_binary_file_name());
85         HostMessageHandlers::handleLoadNanoappRequest(
86             hostClientId, request->transaction_id(), request->app_id(),
87             request->app_version(), request->app_flags(),
88             request->target_api_version(), appBinary->data(), appBinary->size(),
89             appBinaryFilename, request->fragment_id(),
90             request->total_app_size(), request->respond_before_start());
91         break;
92       }
93 
94       case fbs::ChreMessage::UnloadNanoappRequest: {
95         const auto *request = static_cast<const fbs::UnloadNanoappRequest *>(
96             container->message());
97         HostMessageHandlers::handleUnloadNanoappRequest(
98             hostClientId, request->transaction_id(), request->app_id(),
99             request->allow_system_nanoapp_unload());
100         break;
101       }
102 
103       case fbs::ChreMessage::TimeSyncMessage: {
104         const auto *request =
105             static_cast<const fbs::TimeSyncMessage *>(container->message());
106         HostMessageHandlers::handleTimeSyncMessage(request->offset());
107         break;
108       }
109 
110       case fbs::ChreMessage::DebugDumpRequest:
111         HostMessageHandlers::handleDebugDumpRequest(hostClientId);
112         break;
113 
114       case fbs::ChreMessage::SettingChangeMessage: {
115         const auto *settingMessage =
116             static_cast<const fbs::SettingChangeMessage *>(
117                 container->message());
118         HostMessageHandlers::handleSettingChangeMessage(
119             settingMessage->setting(), settingMessage->state());
120         break;
121       }
122 
123       case fbs::ChreMessage::SelfTestRequest: {
124         HostMessageHandlers::handleSelfTestRequest(hostClientId);
125         break;
126       }
127 
128       case fbs::ChreMessage::HostEndpointConnected: {
129         const auto *connectedMessage =
130             static_cast<const fbs::HostEndpointConnected *>(
131                 container->message());
132         struct chreHostEndpointInfo info;
133         info.hostEndpointId = connectedMessage->host_endpoint();
134         info.hostEndpointType = connectedMessage->type();
135         if (strlen(reinterpret_cast<const char *>(
136                 connectedMessage->package_name()->data())) > 0) {
137           info.isNameValid = true;
138           memcpy(&info.packageName[0], connectedMessage->package_name()->data(),
139                  MIN(connectedMessage->package_name()->size(),
140                      CHRE_MAX_ENDPOINT_NAME_LEN));
141           info.packageName[CHRE_MAX_ENDPOINT_NAME_LEN - 1] = '\0';
142         } else {
143           info.isNameValid = false;
144         }
145         if (strlen(reinterpret_cast<const char *>(
146                 connectedMessage->attribution_tag()->data())) > 0) {
147           info.isTagValid = true;
148           memcpy(&info.attributionTag[0],
149                  connectedMessage->attribution_tag()->data(),
150                  MIN(connectedMessage->attribution_tag()->size(),
151                      CHRE_MAX_ENDPOINT_TAG_LEN));
152           info.attributionTag[CHRE_MAX_ENDPOINT_NAME_LEN - 1] = '\0';
153         } else {
154           info.isTagValid = false;
155         }
156 
157         EventLoopManagerSingleton::get()
158             ->getHostEndpointManager()
159             .postHostEndpointConnected(info);
160         break;
161       }
162 
163       case fbs::ChreMessage::HostEndpointDisconnected: {
164         const auto *disconnectedMessage =
165             static_cast<const fbs::HostEndpointDisconnected *>(
166                 container->message());
167         EventLoopManagerSingleton::get()
168             ->getHostEndpointManager()
169             .postHostEndpointDisconnected(disconnectedMessage->host_endpoint());
170         break;
171       }
172 
173       case fbs::ChreMessage::NanConfigurationUpdate: {
174         const auto *nanConfigUpdateMessage =
175             static_cast<const fbs::NanConfigurationUpdate *>(
176                 container->message());
177         HostMessageHandlers::handleNanConfigurationUpdate(
178             nanConfigUpdateMessage->enabled());
179         break;
180       }
181 
182       case fbs::ChreMessage::DebugConfiguration: {
183         const auto *debugConfiguration =
184             static_cast<const fbs::DebugConfiguration *>(container->message());
185         HostMessageHandlers::handleDebugConfiguration(debugConfiguration);
186         break;
187       }
188 
189       default:
190         LOGW("Got invalid/unexpected message type %" PRIu8,
191              static_cast<uint8_t>(container->message_type()));
192         success = false;
193     }
194   }
195 
196   return success;
197 }
198 
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)199 void HostProtocolChre::encodeHubInfoResponse(
200     ChreFlatBufferBuilder &builder, const char *name, const char *vendor,
201     const char *toolchain, uint32_t legacyPlatformVersion,
202     uint32_t legacyToolchainVersion, float peakMips, float stoppedPower,
203     float sleepPower, float peakPower, uint32_t maxMessageLen,
204     uint64_t platformId, uint32_t version, uint16_t hostClientId) {
205   auto nameOffset = addStringAsByteVector(builder, name);
206   auto vendorOffset = addStringAsByteVector(builder, vendor);
207   auto toolchainOffset = addStringAsByteVector(builder, toolchain);
208 
209   auto response = fbs::CreateHubInfoResponse(
210       builder, nameOffset, vendorOffset, toolchainOffset, legacyPlatformVersion,
211       legacyToolchainVersion, peakMips, stoppedPower, sleepPower, peakPower,
212       maxMessageLen, platformId, version);
213   finalize(builder, fbs::ChreMessage::HubInfoResponse, response.Union(),
214            hostClientId);
215 }
216 
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)217 void HostProtocolChre::addNanoappListEntry(
218     ChreFlatBufferBuilder &builder,
219     DynamicVector<Offset<fbs::NanoappListEntry>> &offsetVector, uint64_t appId,
220     uint32_t appVersion, bool enabled, bool isSystemNanoapp,
221     uint32_t appPermissions,
222     const DynamicVector<struct chreNanoappRpcService> &rpcServices) {
223   DynamicVector<Offset<fbs::NanoappRpcService>> rpcServiceList;
224   for (const auto &service : rpcServices) {
225     Offset<fbs::NanoappRpcService> offsetService =
226         fbs::CreateNanoappRpcService(builder, service.id, service.version);
227     if (!rpcServiceList.push_back(offsetService)) {
228       LOGE("Couldn't push RPC service to list");
229     }
230   }
231 
232   auto vectorOffset =
233       builder.CreateVector<Offset<fbs::NanoappRpcService>>(rpcServiceList);
234   auto offset = fbs::CreateNanoappListEntry(builder, appId, appVersion, enabled,
235                                             isSystemNanoapp, appPermissions,
236                                             vectorOffset);
237 
238   if (!offsetVector.push_back(offset)) {
239     LOGE("Couldn't push nanoapp list entry offset!");
240   }
241 }
242 
finishNanoappListResponse(ChreFlatBufferBuilder & builder,DynamicVector<Offset<fbs::NanoappListEntry>> & offsetVector,uint16_t hostClientId)243 void HostProtocolChre::finishNanoappListResponse(
244     ChreFlatBufferBuilder &builder,
245     DynamicVector<Offset<fbs::NanoappListEntry>> &offsetVector,
246     uint16_t hostClientId) {
247   auto vectorOffset =
248       builder.CreateVector<Offset<fbs::NanoappListEntry>>(offsetVector);
249   auto response = fbs::CreateNanoappListResponse(builder, vectorOffset);
250   finalize(builder, fbs::ChreMessage::NanoappListResponse, response.Union(),
251            hostClientId);
252 }
253 
encodeLoadNanoappResponse(ChreFlatBufferBuilder & builder,uint16_t hostClientId,uint32_t transactionId,bool success,uint32_t fragmentId)254 void HostProtocolChre::encodeLoadNanoappResponse(ChreFlatBufferBuilder &builder,
255                                                  uint16_t hostClientId,
256                                                  uint32_t transactionId,
257                                                  bool success,
258                                                  uint32_t fragmentId) {
259   auto response = fbs::CreateLoadNanoappResponse(builder, transactionId,
260                                                  success, fragmentId);
261   finalize(builder, fbs::ChreMessage::LoadNanoappResponse, response.Union(),
262            hostClientId);
263 }
264 
encodeUnloadNanoappResponse(ChreFlatBufferBuilder & builder,uint16_t hostClientId,uint32_t transactionId,bool success)265 void HostProtocolChre::encodeUnloadNanoappResponse(
266     ChreFlatBufferBuilder &builder, uint16_t hostClientId,
267     uint32_t transactionId, bool success) {
268   auto response =
269       fbs::CreateUnloadNanoappResponse(builder, transactionId, success);
270   finalize(builder, fbs::ChreMessage::UnloadNanoappResponse, response.Union(),
271            hostClientId);
272 }
273 
encodeLogMessages(ChreFlatBufferBuilder & builder,const uint8_t * logBuffer,size_t bufferSize)274 void HostProtocolChre::encodeLogMessages(ChreFlatBufferBuilder &builder,
275                                          const uint8_t *logBuffer,
276                                          size_t bufferSize) {
277   auto logBufferOffset = builder.CreateVector(
278       reinterpret_cast<const int8_t *>(logBuffer), bufferSize);
279   auto message = fbs::CreateLogMessage(builder, logBufferOffset);
280   finalize(builder, fbs::ChreMessage::LogMessage, message.Union());
281 }
282 
encodeLogMessagesV2(ChreFlatBufferBuilder & builder,const uint8_t * logBuffer,size_t bufferSize,uint32_t numLogsDropped)283 void HostProtocolChre::encodeLogMessagesV2(ChreFlatBufferBuilder &builder,
284                                            const uint8_t *logBuffer,
285                                            size_t bufferSize,
286                                            uint32_t numLogsDropped) {
287   auto logBufferOffset = builder.CreateVector(
288       reinterpret_cast<const int8_t *>(logBuffer), bufferSize);
289   auto message =
290       fbs::CreateLogMessageV2(builder, logBufferOffset, numLogsDropped);
291   finalize(builder, fbs::ChreMessage::LogMessageV2, message.Union());
292 }
293 
encodeDebugDumpData(ChreFlatBufferBuilder & builder,uint16_t hostClientId,const char * debugStr,size_t debugStrSize)294 void HostProtocolChre::encodeDebugDumpData(ChreFlatBufferBuilder &builder,
295                                            uint16_t hostClientId,
296                                            const char *debugStr,
297                                            size_t debugStrSize) {
298   auto debugStrOffset = builder.CreateVector(
299       reinterpret_cast<const int8_t *>(debugStr), debugStrSize);
300   auto message = fbs::CreateDebugDumpData(builder, debugStrOffset);
301   finalize(builder, fbs::ChreMessage::DebugDumpData, message.Union(),
302            hostClientId);
303 }
304 
encodeDebugDumpResponse(ChreFlatBufferBuilder & builder,uint16_t hostClientId,bool success,uint32_t dataCount)305 void HostProtocolChre::encodeDebugDumpResponse(ChreFlatBufferBuilder &builder,
306                                                uint16_t hostClientId,
307                                                bool success,
308                                                uint32_t dataCount) {
309   auto response = fbs::CreateDebugDumpResponse(builder, success, dataCount);
310   finalize(builder, fbs::ChreMessage::DebugDumpResponse, response.Union(),
311            hostClientId);
312 }
313 
encodeTimeSyncRequest(ChreFlatBufferBuilder & builder)314 void HostProtocolChre::encodeTimeSyncRequest(ChreFlatBufferBuilder &builder) {
315   auto request = fbs::CreateTimeSyncRequest(builder);
316   finalize(builder, fbs::ChreMessage::TimeSyncRequest, request.Union());
317 }
318 
encodeLowPowerMicAccessRequest(ChreFlatBufferBuilder & builder)319 void HostProtocolChre::encodeLowPowerMicAccessRequest(
320     ChreFlatBufferBuilder &builder) {
321   auto request = fbs::CreateLowPowerMicAccessRequest(builder);
322   finalize(builder, fbs::ChreMessage::LowPowerMicAccessRequest,
323            request.Union());
324 }
325 
encodeLowPowerMicAccessRelease(ChreFlatBufferBuilder & builder)326 void HostProtocolChre::encodeLowPowerMicAccessRelease(
327     ChreFlatBufferBuilder &builder) {
328   auto request = fbs::CreateLowPowerMicAccessRelease(builder);
329   finalize(builder, fbs::ChreMessage::LowPowerMicAccessRelease,
330            request.Union());
331 }
332 
encodeSelfTestResponse(ChreFlatBufferBuilder & builder,uint16_t hostClientId,bool success)333 void HostProtocolChre::encodeSelfTestResponse(ChreFlatBufferBuilder &builder,
334                                               uint16_t hostClientId,
335                                               bool success) {
336   auto response = fbs::CreateSelfTestResponse(builder, success);
337   finalize(builder, fbs::ChreMessage::SelfTestResponse, response.Union(),
338            hostClientId);
339 }
340 
encodeMetricLog(ChreFlatBufferBuilder & builder,uint32_t metricId,const uint8_t * encodedMsg,size_t metricSize)341 void HostProtocolChre::encodeMetricLog(ChreFlatBufferBuilder &builder,
342                                        uint32_t metricId,
343                                        const uint8_t *encodedMsg,
344                                        size_t metricSize) {
345   auto encodedMessage = builder.CreateVector(
346       reinterpret_cast<const int8_t *>(encodedMsg), metricSize);
347   auto message = fbs::CreateMetricLog(builder, metricId, encodedMessage);
348   finalize(builder, fbs::ChreMessage::MetricLog, message.Union());
349 }
350 
encodeNanConfigurationRequest(ChreFlatBufferBuilder & builder,bool enable)351 void HostProtocolChre::encodeNanConfigurationRequest(
352     ChreFlatBufferBuilder &builder, bool enable) {
353   auto request = fbs::CreateNanConfigurationRequest(builder, enable);
354   finalize(builder, fbs::ChreMessage::NanConfigurationRequest, request.Union());
355 }
356 
getSettingFromFbs(fbs::Setting setting,Setting * chreSetting)357 bool HostProtocolChre::getSettingFromFbs(fbs::Setting setting,
358                                          Setting *chreSetting) {
359   bool success = true;
360   switch (setting) {
361     case fbs::Setting::LOCATION:
362       *chreSetting = Setting::LOCATION;
363       break;
364     case fbs::Setting::WIFI_AVAILABLE:
365       *chreSetting = Setting::WIFI_AVAILABLE;
366       break;
367     case fbs::Setting::AIRPLANE_MODE:
368       *chreSetting = Setting::AIRPLANE_MODE;
369       break;
370     case fbs::Setting::MICROPHONE:
371       *chreSetting = Setting::MICROPHONE;
372       break;
373     case fbs::Setting::BLE_AVAILABLE:
374       *chreSetting = Setting::BLE_AVAILABLE;
375       break;
376     default:
377       LOGE("Unknown setting %" PRIu8, static_cast<uint8_t>(setting));
378       success = false;
379   }
380 
381   return success;
382 }
383 
getSettingEnabledFromFbs(fbs::SettingState state,bool * chreSettingEnabled)384 bool HostProtocolChre::getSettingEnabledFromFbs(fbs::SettingState state,
385                                                 bool *chreSettingEnabled) {
386   bool success = true;
387   switch (state) {
388     case fbs::SettingState::DISABLED:
389       *chreSettingEnabled = false;
390       break;
391     case fbs::SettingState::ENABLED:
392       *chreSettingEnabled = true;
393       break;
394     default:
395       LOGE("Unknown state %" PRIu8, static_cast<uint8_t>(state));
396       success = false;
397   }
398 
399   return success;
400 }
401 
402 }  // namespace chre
403