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