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