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