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