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