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#include "chre_interface.h" 17 18#include <android-base/logging.h> 19 20#include <chrono> 21 22#include "chre_host/host_protocol_host.h" 23 24using android::chre::getStringFromByteVector; 25using android::chre::HostProtocolHost; 26using flatbuffers::FlatBufferBuilder; 27 28namespace chre_constants = android::hardware::wifi::offload::V1_0::implementation::chre_constants; 29 30namespace fbs = ::chre::fbs; 31 32namespace android { 33namespace hardware { 34namespace wifi { 35namespace offload { 36namespace V1_0 { 37namespace implementation { 38 39SocketCallbacks::SocketCallbacks(ChreInterface* parent) : mParent(parent) { 40} 41 42void SocketCallbacks::onMessageReceived(const void* data, size_t length) { 43 LOG(VERBOSE) << "Message received from CHRE socket"; 44 if (!HostProtocolHost::decodeMessageFromChre(data, length, *this)) { 45 LOG(WARNING) << "Failed to decode message"; 46 } 47} 48 49void SocketCallbacks::onConnected() { 50 LOG(INFO) << "Connected to CHRE socket"; 51 mParent->reportConnectionEvent(ChreInterfaceCallbacks::CONNECTED); 52} 53 54void SocketCallbacks::onConnectionAborted() { 55 LOG(WARNING) << "Connection to CHRE socket Aborted"; 56 mParent->reportConnectionEvent(ChreInterfaceCallbacks::CONNECTION_ABORT); 57} 58 59void SocketCallbacks::onDisconnected() { 60 LOG(WARNING) << "Disconnected from CHRE socket"; 61 mParent->reportConnectionEvent(ChreInterfaceCallbacks::DISCONNECTED); 62} 63 64void SocketCallbacks::handleNanoappMessage(const fbs::NanoappMessageT& message) { 65 LOG(VERBOSE) << "handleNanoappMessage from appId: " << message.app_id; 66 LOG(VERBOSE) << "HostEndPoint: " << message.host_endpoint; 67 if (message.app_id == chre_constants::kWifiOffloadNanoAppId) { 68 mParent->handleMessage(message.message_type, message.message.data(), message.message.size()); 69 } 70} 71 72void SocketCallbacks::handleHubInfoResponse(const fbs::HubInfoResponseT& response) { 73 LOG(VERBOSE) << "Hub Info response"; 74 LOG(VERBOSE) << "Hub Info name: " << getStringFromByteVector(response.name); 75 LOG(VERBOSE) << "Version : " << response.chre_platform_version; 76 LOG(VERBOSE) << "Legacy Platform Version: " << response.platform_version; 77 LOG(VERBOSE) << "Legacy Toolchain Version: " << response.toolchain_version; 78 LOG(VERBOSE) << "Peak Mips: " << response.peak_mips; 79 LOG(VERBOSE) << "Stopped Power: " << response.stopped_power; 80 LOG(VERBOSE) << "Sleep Power: " << response.sleep_power; 81 LOG(VERBOSE) << "Peak Power: " << response.peak_power; 82 LOG(VERBOSE) << "Platform ID: " << response.platform_id; 83 LOG(VERBOSE) << "Vendor : " << getStringFromByteVector(response.vendor); 84 LOG(VERBOSE) << "Toolchain : " << getStringFromByteVector(response.toolchain); 85 LOG(VERBOSE) << "maxMessageLen : " << response.max_msg_len; 86 if (response.max_msg_len < chre_constants::kMaxMessageLen) { 87 LOG(WARNING) << "Incorrect max message length"; 88 } 89} 90 91void SocketCallbacks::handleNanoappListResponse(const fbs::NanoappListResponseT& response) { 92 LOG(VERBOSE) << "handleNanoAppListResponse"; 93 for (const std::unique_ptr<fbs::NanoappListEntryT>& nanoapp : response.nanoapps) { 94 if (nanoapp == nullptr) { 95 continue; 96 } 97 if (nanoapp->app_id == chre_constants::kWifiOffloadNanoAppId && nanoapp->enabled) { 98 LOG(INFO) << "Wifi Offload Nano app found"; 99 LOG(INFO) << "Version: " << nanoapp->version; 100 break; 101 } 102 } 103} 104 105void SocketCallbacks::handleLoadNanoappResponse(const fbs::LoadNanoappResponseT& response) { 106 LOG(VERBOSE) << "Load Nano app response"; 107 LOG(VERBOSE) << "Transaction ID: " << response.transaction_id; 108 LOG(VERBOSE) << "Status: " << response.success; 109} 110 111void SocketCallbacks::handleUnloadNanoappResponse(const fbs::UnloadNanoappResponseT& response) { 112 LOG(VERBOSE) << "Unload Nano app response"; 113 LOG(VERBOSE) << "Transaction ID: " << response.transaction_id; 114 LOG(VERBOSE) << "Status: " << response.success; 115} 116 117ChreInterface::ChreInterface(ChreInterfaceCallbacks* callback) 118 : mSocketCallbacks(new SocketCallbacks(this)), mServerCallbacks(callback), 119 mSocketConnected(false) { 120 if (!mClient.connectInBackground(chre_constants::kSocketName, mSocketCallbacks)) { 121 LOG(ERROR) << "Offload HAL is not connected to Chre"; 122 } 123} 124 125ChreInterface::~ChreInterface() { 126 mClient.disconnect(); 127} 128 129bool ChreInterface::isConnected() { 130 std::lock_guard<std::mutex> lock(mChreInterfaceLock); 131 return mSocketConnected; 132} 133 134void ChreInterface::reportConnectionEvent(ChreInterfaceCallbacks::ConnectionEvent event) { 135 bool connectionStatus = false; 136 switch (event) { 137 case ChreInterfaceCallbacks::ConnectionEvent::CONNECTED: 138 connectionStatus = true; 139 if (!getHubInfo() || !getNanoAppList()) { 140 LOG(WARNING) << "Unable to get platform and nano app info"; 141 } 142 break; 143 case ChreInterfaceCallbacks::ConnectionEvent::DISCONNECTED: 144 case ChreInterfaceCallbacks::ConnectionEvent::CONNECTION_ABORT: 145 break; 146 default: 147 LOG(WARNING) << "Invalid connection event recieved"; 148 return; 149 } 150 { 151 std::lock_guard<std::mutex> lock(mChreInterfaceLock); 152 mSocketConnected = connectionStatus; 153 } 154 mServerCallbacks->handleConnectionEvents(event); 155} 156 157bool ChreInterface::sendCommandToApp(uint32_t messageType, const std::vector<uint8_t>& message) { 158 FlatBufferBuilder builder(chre_constants::kMaxMessageLen); 159 void* messageData = nullptr; 160 size_t messageDataLen = message.size(); 161 if (messageDataLen > 0) { 162 messageData = (void*)message.data(); 163 } 164 HostProtocolHost::encodeNanoappMessage(builder, chre_constants::kWifiOffloadNanoAppId, 165 messageType, 0, messageData, messageDataLen); 166 if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) { 167 LOG(WARNING) << "Failed to send message to Nano app"; 168 return false; 169 } 170 LOG(VERBOSE) << "Command sent " << messageType; 171 return true; 172} 173 174void ChreInterface::handleMessage(uint32_t messageType, const void* messageData, 175 size_t messageDataLen) { 176 const uint8_t* messageBuf = reinterpret_cast<const uint8_t*>(messageData); 177 std::vector<uint8_t> message(messageBuf, messageBuf + messageDataLen); 178 mServerCallbacks->handleMessage(messageType, message); 179} 180 181bool ChreInterface::getHubInfo() { 182 LOG(VERBOSE) << "getHubInfo"; 183 184 FlatBufferBuilder builder(chre_constants::kHubInfoRequestBufLen); 185 HostProtocolHost::encodeHubInfoRequest(builder); 186 if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) { 187 LOG(WARNING) << "Failed to send Hub Info request"; 188 return false; 189 } 190 return true; 191} 192 193bool ChreInterface::getNanoAppList() { 194 LOG(VERBOSE) << "getNanoAppList"; 195 FlatBufferBuilder builder(chre_constants::kNanoAppListRequestBufLen); 196 HostProtocolHost::encodeNanoappListRequest(builder); 197 198 if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) { 199 LOG(WARNING) << "Unable to send Nano app List request"; 200 return false; 201 } 202 return true; 203} 204} // namespace implementation 205} // namespace V1_0 206} // namespace offload 207} // namespace wifi 208} // namespace hardware 209} // namespace android 210