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 namespace {
35
36 /**
37 * Checks that a string encapsulated as a byte vector is null-terminated, and
38 * if it is, returns a pointer to the vector's data. Otherwise returns null.
39 *
40 * @param vec Target vector, can be null
41 *
42 * @return Pointer to the vector's data, or null
43 */
getStringFromByteVector(const flatbuffers::Vector<int8_t> * vec)44 const char *getStringFromByteVector(const flatbuffers::Vector<int8_t> *vec) {
45 constexpr int8_t kNullChar = 0;
46 const char *str = nullptr;
47
48 // Check that the vector is present, non-empty, and null-terminated
49 if (vec != nullptr && vec->size() > 0
50 && (*vec)[vec->size() - 1] == kNullChar) {
51 str = reinterpret_cast<const char *>(vec->data());
52 }
53
54 return str;
55 }
56
57 } // anonymous namespace
58
decodeMessageFromChre(const void * message,size_t messageLen,IChreMessageHandlers & handlers)59 bool HostProtocolHost::decodeMessageFromChre(
60 const void *message, size_t messageLen, IChreMessageHandlers& handlers) {
61 bool success = verifyMessage(message, messageLen);
62 if (success) {
63 const fbs::MessageContainer *container = fbs::GetMessageContainer(message);
64
65 switch (container->message_type()) {
66 case fbs::ChreMessage::NanoappMessage: {
67 const auto *nanoappMsg = static_cast<const fbs::NanoappMessage *>(
68 container->message());
69 // Required field; verifier ensures that this is not null (though it
70 // may be empty)
71 const flatbuffers::Vector<uint8_t> *msgData = nanoappMsg->message();
72 handlers.handleNanoappMessage(
73 nanoappMsg->app_id(), nanoappMsg->message_type(),
74 nanoappMsg->host_endpoint(), msgData->data(), msgData->size());
75 break;
76 }
77
78 case fbs::ChreMessage::HubInfoResponse: {
79 const auto *resp = static_cast<const fbs::HubInfoResponse *>(
80 container->message());
81
82 const char *name = getStringFromByteVector(resp->name());
83 const char *vendor = getStringFromByteVector(resp->vendor());
84 const char *toolchain = getStringFromByteVector(resp->toolchain());
85
86 handlers.handleHubInfoResponse(
87 name, vendor, toolchain, resp->platform_version(),
88 resp->toolchain_version(), resp->peak_mips(), resp->stopped_power(),
89 resp->sleep_power(), resp->peak_power(), resp->max_msg_len(),
90 resp->platform_id(), resp->chre_platform_version());
91 break;
92 }
93
94 case fbs::ChreMessage::NanoappListResponse: {
95 const auto *resp = static_cast<const fbs::NanoappListResponse *>(
96 container->message());
97 fbs::NanoappListResponseT response;
98 resp->UnPackTo(&response);
99 handlers.handleNanoappListResponse(response);
100 break;
101 }
102
103 case fbs::ChreMessage::LoadNanoappResponse: {
104 const auto *resp = static_cast<const fbs::LoadNanoappResponse *>(
105 container->message());
106 fbs::LoadNanoappResponseT response;
107 resp->UnPackTo(&response);
108 handlers.handleLoadNanoappResponse(response);
109 break;
110 }
111
112 default:
113 LOGW("Got invalid/unexpected message type %" PRIu8,
114 static_cast<uint8_t>(container->message_type()));
115 success = false;
116 }
117 }
118
119 return success;
120 }
121
encodeHubInfoRequest(FlatBufferBuilder & builder)122 void HostProtocolHost::encodeHubInfoRequest(FlatBufferBuilder& builder) {
123 auto request = fbs::CreateHubInfoRequest(builder);
124 finalize(builder, fbs::ChreMessage::HubInfoRequest, request.Union());
125 }
126
encodeLoadNanoappRequest(FlatBufferBuilder & builder,uint32_t transactionId,uint64_t appId,uint32_t appVersion,uint32_t targetApiVersion,const std::vector<uint8_t> & nanoappBinary)127 void HostProtocolHost::encodeLoadNanoappRequest(
128 FlatBufferBuilder& builder, uint32_t transactionId, uint64_t appId,
129 uint32_t appVersion, uint32_t targetApiVersion,
130 const std::vector<uint8_t>& nanoappBinary) {
131 auto appBinary = builder.CreateVector(nanoappBinary);
132 auto request = fbs::CreateLoadNanoappRequest(
133 builder, transactionId, appId, appVersion, targetApiVersion, appBinary);
134 finalize(builder, fbs::ChreMessage::LoadNanoappRequest, request.Union());
135 }
136
encodeNanoappListRequest(FlatBufferBuilder & builder)137 void HostProtocolHost::encodeNanoappListRequest(FlatBufferBuilder& builder) {
138 auto request = fbs::CreateNanoappListRequest(builder);
139 finalize(builder, fbs::ChreMessage::NanoappListRequest, request.Union());
140 }
141
extractHostClientId(const void * message,size_t messageLen,uint16_t * hostClientId)142 bool HostProtocolHost::extractHostClientId(const void *message,
143 size_t messageLen,
144 uint16_t *hostClientId) {
145 bool success = verifyMessage(message, messageLen);
146
147 if (success && hostClientId != nullptr) {
148 const fbs::MessageContainer *container = fbs::GetMessageContainer(message);
149 // host_addr guaranteed to be non-null via verifyMessage (it's a required
150 // field)
151 *hostClientId = container->host_addr()->client_id();
152 success = true;
153 }
154
155 return success;
156 }
157
mutateHostClientId(void * message,size_t messageLen,uint16_t hostClientId)158 bool HostProtocolHost::mutateHostClientId(void *message, size_t messageLen,
159 uint16_t hostClientId) {
160 bool success = verifyMessage(message, messageLen);
161
162 if (!success) {
163 LOGE("Message verification failed - can't mutate host ID");
164 } else {
165 fbs::MessageContainer *container = fbs::GetMutableMessageContainer(message);
166 // host_addr guaranteed to be non-null via verifyMessage (it's a required
167 // field)
168 container->mutable_host_addr()->mutate_client_id(hostClientId);
169 success = true;
170 }
171
172 return success;
173 }
174
175 } // namespace chre
176 } // namespace android
177