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