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 25namespace chre { 26 27//! Used to pass the client ID through the user data pointer in deferCallback 28union HostClientIdCallbackData { 29 uint16_t hostClientId; 30 void *ptr; 31}; 32 33static_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 */ 42void 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 */ 53template<typename T> 54void 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 */ 77void 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 */ 91void 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 115void 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 */ 142void 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 */ 157void 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 */ 168void 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 */ 178void handleDebugDumpRequest(uint16_t hostClientId) { 179 LOGD("handleDebugDumpRequest"); 180} 181 182bool 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