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/android/host_link.h"
18
19 #include "chre/core/event_loop_manager.h"
20 #include "chre/platform/shared/host_protocol_common.h"
21 #include "chre/util/macros.h"
22 #include "chre_api/chre/version.h"
23 #include "chre_host/host_messages_generated.h"
24
25 namespace chre {
26
27 //! Used to pass the client ID through the user data pointer in deferCallback
28 union HostClientIdCallbackData {
29 uint16_t hostClientId;
30 void *ptr;
31 };
32
33 static_assert(sizeof(uint16_t) <= sizeof(void*),
34 "Pointer must at least fit a u16 for passing the host client ID");
35
36 /**
37 * Assigns a vector the contents of a C-style, null-terminated string.
38 *
39 * @param vector The vector to assign with the contents of a string.
40 * @param str The string to assign.
41 */
setVectorToString(std::vector<int8_t> * vector,const char * str)42 void setVectorToString(std::vector<int8_t> *vector, const char *str) {
43 *vector = std::vector<int8_t>(str, str + strlen(str));
44 }
45
46 /**
47 * Sends a message to the host given a hostClientId.
48 *
49 * @param message The message to send to the host.
50 * @param hostClientId The host who made the original request for which this is
51 * a reply.
52 */
53 template<typename T>
sendFlatbufferToHost(T & message,uint16_t hostClientId)54 void sendFlatbufferToHost(T& message, uint16_t hostClientId) {
55 static_assert(
56 fbs::ChreMessageTraits<typename T::TableType>::enum_value
57 != fbs::ChreMessage::NONE,
58 "Only works for message types supported by ChreMessageUnion");
59
60 fbs::MessageContainerT container;
61 container.message.Set(std::move(message));
62 container.host_addr.reset(new fbs::HostAddress(hostClientId));
63
64 flatbuffers::FlatBufferBuilder builder;
65 auto containerOffset = CreateMessageContainer(builder, &container, nullptr);
66 builder.Finish(containerOffset);
67
68 SocketServerSingleton::get()->sendToClientById(
69 builder.GetBufferPointer(), builder.GetSize(), hostClientId);
70 }
71
72 /**
73 * Handles a message directed to a nanoapp from the system.
74 *
75 * @param message The message to deliver to a nanoapp.
76 */
handleNanoappMessage(const fbs::NanoappMessageT & message)77 void handleNanoappMessage(const fbs::NanoappMessageT& message) {
78 LOGD("handleNanoappMessage");
79 HostCommsManager& manager =
80 EventLoopManagerSingleton::get()->getHostCommsManager();
81 manager.sendMessageToNanoappFromHost(
82 message.app_id, message.message_type, message.host_endpoint,
83 message.message.data(), message.message.size());
84 }
85
86 /**
87 * Handles a request for information about this context hub instance.
88 *
89 * @param hostClientId The client ID on the host making the request.
90 */
handleHubInfoRequest(uint16_t hostClientId)91 void handleHubInfoRequest(uint16_t hostClientId) {
92 LOGD("handleHubInfoRequest");
93 fbs::HubInfoResponseT response;
94 setVectorToString(&response.name, "CHRE on Android");
95 setVectorToString(&response.vendor, "Google");
96 setVectorToString(&response.toolchain, "Android NDK API 26 (clang "
97 STRINGIFY(__clang_major__) "."
98 STRINGIFY(__clang_minor__) "."
99 STRINGIFY(__clang_patchlevel__) ")");
100 response.platform_version = 0;
101 response.toolchain_version = ((__clang_major__ & 0xFF) << 24) |
102 ((__clang_minor__ & 0xFF) << 16) |
103 (__clang_patchlevel__ & 0xFFFF);
104 response.peak_mips = 1000;
105 response.stopped_power = 1000;
106 response.sleep_power = 1000;
107 response.peak_power = 10000;
108 response.max_msg_len = CHRE_MESSAGE_TO_HOST_MAX_SIZE;
109 response.platform_id = chreGetPlatformId();
110 response.chre_platform_version = chreGetVersion();
111
112 sendFlatbufferToHost(response, hostClientId);
113 }
114
constructNanoappListCallback(uint16_t,void * cookie)115 void constructNanoappListCallback(uint16_t /*eventType*/, void *cookie) {
116 HostClientIdCallbackData clientIdCbData;
117 clientIdCbData.ptr = cookie;
118
119 auto nanoappAddCallback = [](const Nanoapp *nanoapp, void *data) {
120 auto response = static_cast<fbs::NanoappListResponseT *>(data);
121 auto nanoappListEntry =
122 std::unique_ptr<fbs::NanoappListEntryT>(new fbs::NanoappListEntryT());
123 nanoappListEntry->app_id = nanoapp->getAppId();
124 nanoappListEntry->version = nanoapp->getAppVersion();
125 nanoappListEntry->enabled = true;
126 nanoappListEntry->is_system = nanoapp->isSystemNanoapp();
127 response->nanoapps.push_back(std::move(nanoappListEntry));
128 };
129
130 fbs::NanoappListResponseT response;
131 EventLoop& eventLoop = EventLoopManagerSingleton::get()->getEventLoop();
132 eventLoop.forEachNanoapp(nanoappAddCallback, &response);
133
134 sendFlatbufferToHost(response, clientIdCbData.hostClientId);
135 }
136
137 /**
138 * Handles a request from the host for a list of nanoapps.
139 *
140 * @param hostClientId The client ID on the host making the request.
141 */
handleNanoappListRequest(uint16_t hostClientId)142 void handleNanoappListRequest(uint16_t hostClientId) {
143 LOGD("handleNanoappListRequest");
144 HostClientIdCallbackData cbData = {};
145 cbData.hostClientId = hostClientId;
146 EventLoopManagerSingleton::get()->deferCallback(
147 SystemCallbackType::NanoappListResponse, cbData.ptr,
148 constructNanoappListCallback);
149 }
150
151 /**
152 * Handles a request to load a nanoapp.
153 *
154 * @param hostClientId The client ID on the host making the request.
155 * @param loadRequest The details of the nanoapp load request.
156 */
handleLoadNanoappRequest(uint16_t hostClientId,const fbs::LoadNanoappRequestT & loadRequest)157 void handleLoadNanoappRequest(
158 uint16_t hostClientId, const fbs::LoadNanoappRequestT& loadRequest) {
159 LOGD("handleLoadNanoappRequest");
160 }
161
162 /**
163 * Handles a request to unload a nanoapp.
164 *
165 * @param hostClientId The client ID on the host making the request.
166 * @param unloadRequest The details of the nanoapp unload request.
167 */
handleUnloadNanoappRequest(uint16_t hostClientId,const fbs::UnloadNanoappRequestT & unloadRequest)168 void handleUnloadNanoappRequest(
169 uint16_t hostClientId, const fbs::UnloadNanoappRequestT& unloadRequest) {
170 LOGD("handleUnloadNanoappRequest");
171 }
172
173 /**
174 * Handles a request for a debug dump.
175 *
176 * @param hostClientId The client OD on the host making the request.
177 */
handleDebugDumpRequest(uint16_t hostClientId)178 void handleDebugDumpRequest(uint16_t hostClientId) {
179 LOGD("handleDebugDumpRequest");
180 }
181
handleMessageFromHost(void * message,size_t length)182 bool handleMessageFromHost(void *message, size_t length) {
183 bool success = HostProtocolCommon::verifyMessage(message, length);
184 if (success) {
185 fbs::MessageContainerT container;
186 fbs::GetMessageContainer(message)->UnPackTo(&container);
187 uint16_t hostClientId = container.host_addr->client_id();
188 switch (container.message.type) {
189 case fbs::ChreMessage::NanoappMessage:
190 handleNanoappMessage(*container.message.AsNanoappMessage());
191 break;
192
193 case fbs::ChreMessage::HubInfoRequest:
194 handleHubInfoRequest(hostClientId);
195 break;
196
197 case fbs::ChreMessage::NanoappListRequest:
198 handleNanoappListRequest(hostClientId);
199 break;
200
201 case fbs::ChreMessage::LoadNanoappRequest:
202 handleLoadNanoappRequest(hostClientId,
203 *container.message.AsLoadNanoappRequest());
204 break;
205
206 case fbs::ChreMessage::UnloadNanoappRequest:
207 handleUnloadNanoappRequest(hostClientId,
208 *container.message.AsUnloadNanoappRequest());
209 break;
210
211 case fbs::ChreMessage::DebugDumpRequest:
212 handleDebugDumpRequest(hostClientId);
213 break;
214
215 default:
216 LOGW("Got invalid/unexpected message type %" PRIu8,
217 static_cast<uint8_t>(container.message.type));
218 success = false;
219 }
220 }
221
222 return success;
223 }
224
225 } // namespace chre
226