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