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/host_messages_generated.h"
24
25 using flatbuffers::FlatBufferBuilder;
26 using flatbuffers::Offset;
27 using flatbuffers::Vector;
28
29 namespace chre {
30
31 // This is similar to getStringFromByteVector in host_protocol_host.h. Ensure
32 // that method's implementation is kept in sync with this.
getStringFromByteVector(const flatbuffers::Vector<int8_t> * vec)33 const char *getStringFromByteVector(const flatbuffers::Vector<int8_t> *vec) {
34 constexpr int8_t kNullChar = static_cast<int8_t>('\0');
35 const char *str = nullptr;
36
37 // Check that the vector is present, non-empty, and null-terminated
38 if (vec != nullptr && vec->size() > 0 && (*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 = static_cast<const fbs::NanoappMessage *>(
58 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 = static_cast<const fbs::LoadNanoappRequest *>(
78 container->message());
79 const flatbuffers::Vector<uint8_t> *appBinary = request->app_binary();
80 const char *appBinaryFilename = getStringFromByteVector(
81 request->app_binary_file_name());
82 HostMessageHandlers::handleLoadNanoappRequest(
83 hostClientId, request->transaction_id(), request->app_id(),
84 request->app_version(), request->target_api_version(),
85 appBinary->data(), appBinary->size(), appBinaryFilename,
86 request->fragment_id(), request->total_app_size());
87 break;
88 }
89
90 case fbs::ChreMessage::UnloadNanoappRequest: {
91 const auto *request = static_cast<const fbs::UnloadNanoappRequest *>(
92 container->message());
93 HostMessageHandlers::handleUnloadNanoappRequest(
94 hostClientId, request->transaction_id(), request->app_id(),
95 request->allow_system_nanoapp_unload());
96 break;
97 }
98
99 case fbs::ChreMessage::TimeSyncMessage: {
100 const auto *request = static_cast<const fbs::TimeSyncMessage *>(
101 container->message());
102 HostMessageHandlers::handleTimeSyncMessage(request->offset());
103 break;
104 }
105
106 case fbs::ChreMessage::DebugDumpRequest:
107 HostMessageHandlers::handleDebugDumpRequest(hostClientId);
108 break;
109
110 default:
111 LOGW("Got invalid/unexpected message type %" PRIu8,
112 static_cast<uint8_t>(container->message_type()));
113 success = false;
114 }
115 }
116
117 return success;
118 }
119
encodeHubInfoResponse(FlatBufferBuilder & 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)120 void HostProtocolChre::encodeHubInfoResponse(
121 FlatBufferBuilder& builder, const char *name, const char *vendor,
122 const char *toolchain, uint32_t legacyPlatformVersion,
123 uint32_t legacyToolchainVersion, float peakMips, float stoppedPower,
124 float sleepPower, float peakPower, uint32_t maxMessageLen,
125 uint64_t platformId, uint32_t version, uint16_t hostClientId) {
126 auto nameOffset = addStringAsByteVector(builder, name);
127 auto vendorOffset = addStringAsByteVector(builder, vendor);
128 auto toolchainOffset = addStringAsByteVector(builder, toolchain);
129
130 auto response = fbs::CreateHubInfoResponse(
131 builder, nameOffset, vendorOffset, toolchainOffset, legacyPlatformVersion,
132 legacyToolchainVersion, peakMips, stoppedPower, sleepPower, peakPower,
133 maxMessageLen, platformId, version);
134 finalize(builder, fbs::ChreMessage::HubInfoResponse, response.Union(),
135 hostClientId);
136 }
137
addNanoappListEntry(FlatBufferBuilder & builder,DynamicVector<Offset<fbs::NanoappListEntry>> & offsetVector,uint64_t appId,uint32_t appVersion,bool enabled,bool isSystemNanoapp)138 void HostProtocolChre::addNanoappListEntry(
139 FlatBufferBuilder& builder,
140 DynamicVector<Offset<fbs::NanoappListEntry>>& offsetVector,
141 uint64_t appId, uint32_t appVersion, bool enabled, bool isSystemNanoapp) {
142 auto offset = fbs::CreateNanoappListEntry(
143 builder, appId, appVersion, enabled, isSystemNanoapp);
144 if (!offsetVector.push_back(offset)) {
145 LOGE("Couldn't push nanoapp list entry offset!");
146 }
147 }
148
finishNanoappListResponse(FlatBufferBuilder & builder,DynamicVector<Offset<fbs::NanoappListEntry>> & offsetVector,uint16_t hostClientId)149 void HostProtocolChre::finishNanoappListResponse(
150 FlatBufferBuilder& builder,
151 DynamicVector<Offset<fbs::NanoappListEntry>>& offsetVector,
152 uint16_t hostClientId) {
153 auto vectorOffset = builder.CreateVector<Offset<fbs::NanoappListEntry>>(
154 offsetVector);
155 auto response = fbs::CreateNanoappListResponse(builder, vectorOffset);
156 finalize(builder, fbs::ChreMessage::NanoappListResponse, response.Union(),
157 hostClientId);
158 }
159
encodeLoadNanoappResponse(flatbuffers::FlatBufferBuilder & builder,uint16_t hostClientId,uint32_t transactionId,bool success,uint32_t fragmentId)160 void HostProtocolChre::encodeLoadNanoappResponse(
161 flatbuffers::FlatBufferBuilder& builder, uint16_t hostClientId,
162 uint32_t transactionId, bool success, uint32_t fragmentId) {
163 auto response = fbs::CreateLoadNanoappResponse(builder, transactionId,
164 success, fragmentId);
165 finalize(builder, fbs::ChreMessage::LoadNanoappResponse, response.Union(),
166 hostClientId);
167 }
168
encodeUnloadNanoappResponse(flatbuffers::FlatBufferBuilder & builder,uint16_t hostClientId,uint32_t transactionId,bool success)169 void HostProtocolChre::encodeUnloadNanoappResponse(
170 flatbuffers::FlatBufferBuilder& builder, uint16_t hostClientId,
171 uint32_t transactionId, bool success) {
172 auto response = fbs::CreateUnloadNanoappResponse(builder, transactionId,
173 success);
174 finalize(builder, fbs::ChreMessage::UnloadNanoappResponse, response.Union(),
175 hostClientId);
176 }
177
encodeLogMessages(flatbuffers::FlatBufferBuilder & builder,const char * logBuffer,size_t bufferSize)178 void HostProtocolChre::encodeLogMessages(
179 flatbuffers::FlatBufferBuilder& builder, const char *logBuffer,
180 size_t bufferSize) {
181 auto logBufferOffset = builder.CreateVector(
182 reinterpret_cast<const int8_t *>(logBuffer), bufferSize);
183 auto message = fbs::CreateLogMessage(builder, logBufferOffset);
184 finalize(builder, fbs::ChreMessage::LogMessage, message.Union());
185 }
186
encodeDebugDumpData(flatbuffers::FlatBufferBuilder & builder,uint16_t hostClientId,const char * debugStr,size_t debugStrSize)187 void HostProtocolChre::encodeDebugDumpData(
188 flatbuffers::FlatBufferBuilder& builder, uint16_t hostClientId,
189 const char *debugStr, size_t debugStrSize) {
190 auto debugStrOffset = builder.CreateVector(
191 reinterpret_cast<const int8_t *>(debugStr), debugStrSize);
192 auto message = fbs::CreateDebugDumpData(builder, debugStrOffset);
193 finalize(builder, fbs::ChreMessage::DebugDumpData, message.Union(),
194 hostClientId);
195 }
196
encodeDebugDumpResponse(flatbuffers::FlatBufferBuilder & builder,uint16_t hostClientId,bool success,uint32_t dataCount)197 void HostProtocolChre::encodeDebugDumpResponse(
198 flatbuffers::FlatBufferBuilder& builder, uint16_t hostClientId,
199 bool success, uint32_t dataCount) {
200 auto response = fbs::CreateDebugDumpResponse(builder, success, dataCount);
201 finalize(builder, fbs::ChreMessage::DebugDumpResponse, response.Union(),
202 hostClientId);
203 }
204
encodeTimeSyncRequest(flatbuffers::FlatBufferBuilder & builder)205 void HostProtocolChre::encodeTimeSyncRequest(
206 flatbuffers::FlatBufferBuilder& builder) {
207 auto request = fbs::CreateTimeSyncRequest(builder);
208 finalize(builder, fbs::ChreMessage::TimeSyncRequest, request.Union());
209 }
210
encodeLowPowerMicAccessRequest(flatbuffers::FlatBufferBuilder & builder)211 void HostProtocolChre::encodeLowPowerMicAccessRequest(
212 flatbuffers::FlatBufferBuilder& builder) {
213 auto request = fbs::CreateLowPowerMicAccessRequest(builder);
214 finalize(builder, fbs::ChreMessage::LowPowerMicAccessRequest,
215 request.Union());
216 }
217
encodeLowPowerMicAccessRelease(flatbuffers::FlatBufferBuilder & builder)218 void HostProtocolChre::encodeLowPowerMicAccessRelease(
219 flatbuffers::FlatBufferBuilder& builder) {
220 auto request = fbs::CreateLowPowerMicAccessRelease(builder);
221 finalize(builder, fbs::ChreMessage::LowPowerMicAccessRelease,
222 request.Union());
223 }
224
225 } // namespace chre
226