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_host/host_protocol_host.h"
18
19 #include <inttypes.h>
20 #include <string.h>
21
22 #include "chre_host/log.h"
23
24 using flatbuffers::FlatBufferBuilder;
25 using flatbuffers::Offset;
26
27 // Aliased for consistency with the way these symbols are referenced in
28 // CHRE-side code
29 namespace fbs = ::chre::fbs;
30
31 namespace android {
32 namespace chre {
33
34 // This is similar to getStringFromByteVector in host_protocol_chre.h. Ensure
35 // that method's implementation is kept in sync with this.
getStringFromByteVector(const std::vector<int8_t> & vec)36 const char *getStringFromByteVector(const std::vector<int8_t> &vec) {
37 constexpr int8_t kNullChar = static_cast<int8_t>('\0');
38 const char *str = nullptr;
39
40 // Check that the vector is present, non-empty, and null-terminated
41 if (vec.size() > 0 && vec[vec.size() - 1] == kNullChar) {
42 str = reinterpret_cast<const char *>(vec.data());
43 }
44
45 return str;
46 }
47
decodeMessageFromChre(const void * message,size_t messageLen,IChreMessageHandlers & handlers)48 bool HostProtocolHost::decodeMessageFromChre(const void *message,
49 size_t messageLen,
50 IChreMessageHandlers &handlers) {
51 bool success = verifyMessage(message, messageLen);
52 if (success) {
53 std::unique_ptr<fbs::MessageContainerT> container =
54 fbs::UnPackMessageContainer(message);
55 fbs::ChreMessageUnion &msg = container->message;
56
57 switch (container->message.type) {
58 case fbs::ChreMessage::NanoappMessage:
59 handlers.handleNanoappMessage(*msg.AsNanoappMessage());
60 break;
61
62 case fbs::ChreMessage::HubInfoResponse:
63 handlers.handleHubInfoResponse(*msg.AsHubInfoResponse());
64 break;
65
66 case fbs::ChreMessage::NanoappListResponse:
67 handlers.handleNanoappListResponse(*msg.AsNanoappListResponse());
68 break;
69
70 case fbs::ChreMessage::LoadNanoappResponse:
71 handlers.handleLoadNanoappResponse(*msg.AsLoadNanoappResponse());
72 break;
73
74 case fbs::ChreMessage::UnloadNanoappResponse:
75 handlers.handleUnloadNanoappResponse(*msg.AsUnloadNanoappResponse());
76 break;
77
78 case fbs::ChreMessage::DebugDumpData:
79 handlers.handleDebugDumpData(*msg.AsDebugDumpData());
80 break;
81
82 case fbs::ChreMessage::DebugDumpResponse:
83 handlers.handleDebugDumpResponse(*msg.AsDebugDumpResponse());
84 break;
85
86 case fbs::ChreMessage::SelfTestResponse:
87 handlers.handleSelfTestResponse(*msg.AsSelfTestResponse());
88 break;
89
90 default:
91 LOGW("Got invalid/unexpected message type %" PRIu8,
92 static_cast<uint8_t>(msg.type));
93 success = false;
94 }
95 }
96
97 return success;
98 }
99
encodeHubInfoRequest(FlatBufferBuilder & builder)100 void HostProtocolHost::encodeHubInfoRequest(FlatBufferBuilder &builder) {
101 auto request = fbs::CreateHubInfoRequest(builder);
102 finalize(builder, fbs::ChreMessage::HubInfoRequest, request.Union());
103 }
104
encodeDebugConfiguration(FlatBufferBuilder & builder)105 void HostProtocolHost::encodeDebugConfiguration(FlatBufferBuilder &builder) {
106 #ifdef CHRE_HEALTH_MONITOR_CHECK_CRASH
107 auto request = fbs::CreateDebugConfiguration(builder, true);
108 #else
109 auto request = fbs::CreateDebugConfiguration(builder, false);
110 #endif // CHRE_HEALTH_MONITOR_CHECK_CRASH
111 finalize(builder, fbs::ChreMessage::DebugConfiguration, request.Union());
112 }
113
encodeFragmentedLoadNanoappRequest(flatbuffers::FlatBufferBuilder & builder,const FragmentedLoadRequest & request,bool respondBeforeStart)114 void HostProtocolHost::encodeFragmentedLoadNanoappRequest(
115 flatbuffers::FlatBufferBuilder &builder,
116 const FragmentedLoadRequest &request, bool respondBeforeStart) {
117 encodeLoadNanoappRequestForBinary(
118 builder, request.transactionId, request.appId, request.appVersion,
119 request.appFlags, request.targetApiVersion, request.binary,
120 request.fragmentId, request.appTotalSizeBytes, respondBeforeStart);
121 }
122
encodeNanoappListRequest(FlatBufferBuilder & builder)123 void HostProtocolHost::encodeNanoappListRequest(FlatBufferBuilder &builder) {
124 auto request = fbs::CreateNanoappListRequest(builder);
125 finalize(builder, fbs::ChreMessage::NanoappListRequest, request.Union());
126 }
127
encodeUnloadNanoappRequest(FlatBufferBuilder & builder,uint32_t transactionId,uint64_t appId,bool allowSystemNanoappUnload)128 void HostProtocolHost::encodeUnloadNanoappRequest(
129 FlatBufferBuilder &builder, uint32_t transactionId, uint64_t appId,
130 bool allowSystemNanoappUnload) {
131 auto request = fbs::CreateUnloadNanoappRequest(builder, transactionId, appId,
132 allowSystemNanoappUnload);
133 finalize(builder, fbs::ChreMessage::UnloadNanoappRequest, request.Union());
134 }
135
encodeTimeSyncMessage(FlatBufferBuilder & builder,int64_t offset)136 void HostProtocolHost::encodeTimeSyncMessage(FlatBufferBuilder &builder,
137 int64_t offset) {
138 auto request = fbs::CreateTimeSyncMessage(builder, offset);
139 finalize(builder, fbs::ChreMessage::TimeSyncMessage, request.Union());
140 }
141
encodeDebugDumpRequest(FlatBufferBuilder & builder)142 void HostProtocolHost::encodeDebugDumpRequest(FlatBufferBuilder &builder) {
143 auto request = fbs::CreateDebugDumpRequest(builder);
144 finalize(builder, fbs::ChreMessage::DebugDumpRequest, request.Union());
145 }
146
extractHostClientIdAndType(const void * message,size_t messageLen,uint16_t * hostClientId,::chre::fbs::ChreMessage * messageType)147 bool HostProtocolHost::extractHostClientIdAndType(
148 const void *message, size_t messageLen, uint16_t *hostClientId,
149 ::chre::fbs::ChreMessage *messageType) {
150 bool success = false;
151 if (hostClientId != nullptr && messageType != nullptr) {
152 success = verifyMessage(message, messageLen);
153
154 if (success) {
155 const fbs::MessageContainer *container =
156 fbs::GetMessageContainer(message);
157 // host_addr guaranteed to be non-null via verifyMessage (it's a required
158 // field)
159 *hostClientId = container->host_addr()->client_id();
160 *messageType = container->message_type();
161 }
162 }
163
164 return success;
165 }
166
mutateHostClientId(void * message,size_t messageLen,uint16_t hostClientId)167 bool HostProtocolHost::mutateHostClientId(void *message, size_t messageLen,
168 uint16_t hostClientId) {
169 bool success = verifyMessage(message, messageLen);
170
171 if (!success) {
172 LOGE("Message verification failed - can't mutate host ID");
173 } else {
174 fbs::MessageContainer *container = fbs::GetMutableMessageContainer(message);
175 // host_addr guaranteed to be non-null via verifyMessage (it's a required
176 // field)
177 container->mutable_host_addr()->mutate_client_id(hostClientId);
178 success = true;
179 }
180
181 return success;
182 }
183
encodeLoadNanoappRequestForBinary(FlatBufferBuilder & builder,uint32_t transactionId,uint64_t appId,uint32_t appVersion,uint32_t appFlags,uint32_t targetApiVersion,const std::vector<uint8_t> & nanoappBinary,uint32_t fragmentId,size_t appTotalSizeBytes,bool respondBeforeStart)184 void HostProtocolHost::encodeLoadNanoappRequestForBinary(
185 FlatBufferBuilder &builder, uint32_t transactionId, uint64_t appId,
186 uint32_t appVersion, uint32_t appFlags, uint32_t targetApiVersion,
187 const std::vector<uint8_t> &nanoappBinary, uint32_t fragmentId,
188 size_t appTotalSizeBytes, bool respondBeforeStart) {
189 auto appBinary = builder.CreateVector(nanoappBinary);
190 auto request = fbs::CreateLoadNanoappRequest(
191 builder, transactionId, appId, appVersion, targetApiVersion, appBinary,
192 fragmentId, appTotalSizeBytes, 0 /* app_binary_file_name */, appFlags,
193 respondBeforeStart);
194 finalize(builder, fbs::ChreMessage::LoadNanoappRequest, request.Union());
195 }
196
encodeLoadNanoappRequestForFile(flatbuffers::FlatBufferBuilder & builder,uint32_t transactionId,uint64_t appId,uint32_t appVersion,uint32_t targetApiVersion,const char * nanoappBinaryName)197 void HostProtocolHost::encodeLoadNanoappRequestForFile(
198 flatbuffers::FlatBufferBuilder &builder, uint32_t transactionId,
199 uint64_t appId, uint32_t appVersion, uint32_t targetApiVersion,
200 const char *nanoappBinaryName) {
201 const std::vector<uint8_t> emptyAppBinary;
202 auto appBinary = builder.CreateVector(emptyAppBinary);
203 auto appBinaryName = addStringAsByteVector(builder, nanoappBinaryName);
204 auto request = fbs::CreateLoadNanoappRequest(
205 builder, transactionId, appId, appVersion, targetApiVersion, appBinary,
206 0 /* fragmentId */, 0 /* appTotalSizeBytes */, appBinaryName);
207 finalize(builder, fbs::ChreMessage::LoadNanoappRequest, request.Union());
208 }
209
encodeSettingChangeNotification(flatbuffers::FlatBufferBuilder & builder,::chre::fbs::Setting setting,::chre::fbs::SettingState newState)210 void HostProtocolHost::encodeSettingChangeNotification(
211 flatbuffers::FlatBufferBuilder &builder, ::chre::fbs::Setting setting,
212 ::chre::fbs::SettingState newState) {
213 auto notification =
214 fbs::CreateSettingChangeMessage(builder, setting, newState);
215 finalize(builder, fbs::ChreMessage::SettingChangeMessage,
216 notification.Union());
217 }
218
encodeSelfTestRequest(flatbuffers::FlatBufferBuilder & builder)219 void HostProtocolHost::encodeSelfTestRequest(
220 flatbuffers::FlatBufferBuilder &builder) {
221 auto request = fbs::CreateSelfTestRequest(builder);
222 finalize(builder, fbs::ChreMessage::SelfTestRequest, request.Union());
223 }
224
encodeHostEndpointConnected(flatbuffers::FlatBufferBuilder & builder,uint16_t hostEndpointId,uint8_t type,const std::string & packageName,const std::string & attributionTag)225 void HostProtocolHost::encodeHostEndpointConnected(
226 flatbuffers::FlatBufferBuilder &builder, uint16_t hostEndpointId,
227 uint8_t type, const std::string &packageName,
228 const std::string &attributionTag) {
229 std::vector<int8_t> packageNameVec(packageName.begin(), packageName.end());
230 packageNameVec.push_back('\0');
231 std::vector<int8_t> attributionTagVec(attributionTag.begin(),
232 attributionTag.end());
233 attributionTagVec.push_back('\0');
234
235 auto message = fbs::CreateHostEndpointConnectedDirect(
236 builder, hostEndpointId, type, &packageNameVec, &attributionTagVec);
237 finalize(builder, fbs::ChreMessage::HostEndpointConnected, message.Union());
238 }
239
encodeHostEndpointDisconnected(flatbuffers::FlatBufferBuilder & builder,uint16_t hostEndpointId)240 void HostProtocolHost::encodeHostEndpointDisconnected(
241 flatbuffers::FlatBufferBuilder &builder, uint16_t hostEndpointId) {
242 auto message = fbs::CreateHostEndpointDisconnected(builder, hostEndpointId);
243 finalize(builder, fbs::ChreMessage::HostEndpointDisconnected,
244 message.Union());
245 }
246
encodeNanconfigurationUpdate(flatbuffers::FlatBufferBuilder & builder,bool nanEnabled)247 void HostProtocolHost::encodeNanconfigurationUpdate(
248 flatbuffers::FlatBufferBuilder &builder, bool nanEnabled) {
249 auto message = fbs::CreateNanConfigurationUpdate(builder, nanEnabled);
250 finalize(builder, fbs::ChreMessage::NanConfigurationUpdate, message.Union());
251 }
252
encodePulseRequest(FlatBufferBuilder & builder)253 void HostProtocolHost::encodePulseRequest(FlatBufferBuilder &builder) {
254 auto message = fbs::CreatePulseRequest(builder);
255 finalize(builder, fbs::ChreMessage::PulseRequest, message.Union());
256 }
257
258 } // namespace chre
259 } // namespace android
260