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