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