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