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