/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "chre_interface.h" #include <android-base/logging.h> #include <chrono> #include "chre_host/host_protocol_host.h" using android::chre::getStringFromByteVector; using android::chre::HostProtocolHost; using flatbuffers::FlatBufferBuilder; namespace chre_constants = android::hardware::wifi::offload::V1_0::implementation::chre_constants; namespace fbs = ::chre::fbs; namespace android { namespace hardware { namespace wifi { namespace offload { namespace V1_0 { namespace implementation { SocketCallbacks::SocketCallbacks(ChreInterface* parent) : mParent(parent) { } void SocketCallbacks::onMessageReceived(const void* data, size_t length) { LOG(VERBOSE) << "Message received from CHRE socket"; if (!HostProtocolHost::decodeMessageFromChre(data, length, *this)) { LOG(WARNING) << "Failed to decode message"; } } void SocketCallbacks::onConnected() { LOG(INFO) << "Connected to CHRE socket"; mParent->reportConnectionEvent(ChreInterfaceCallbacks::CONNECTED); } void SocketCallbacks::onConnectionAborted() { LOG(WARNING) << "Connection to CHRE socket Aborted"; mParent->reportConnectionEvent(ChreInterfaceCallbacks::CONNECTION_ABORT); } void SocketCallbacks::onDisconnected() { LOG(WARNING) << "Disconnected from CHRE socket"; mParent->reportConnectionEvent(ChreInterfaceCallbacks::DISCONNECTED); } void SocketCallbacks::handleNanoappMessage(const fbs::NanoappMessageT& message) { LOG(VERBOSE) << "handleNanoappMessage from appId: " << message.app_id; LOG(VERBOSE) << "HostEndPoint: " << message.host_endpoint; if (message.app_id == chre_constants::kWifiOffloadNanoAppId) { mParent->handleMessage(message.message_type, message.message.data(), message.message.size()); } } void SocketCallbacks::handleHubInfoResponse(const fbs::HubInfoResponseT& response) { LOG(VERBOSE) << "Hub Info response"; LOG(VERBOSE) << "Hub Info name: " << getStringFromByteVector(response.name); LOG(VERBOSE) << "Version : " << response.chre_platform_version; LOG(VERBOSE) << "Legacy Platform Version: " << response.platform_version; LOG(VERBOSE) << "Legacy Toolchain Version: " << response.toolchain_version; LOG(VERBOSE) << "Peak Mips: " << response.peak_mips; LOG(VERBOSE) << "Stopped Power: " << response.stopped_power; LOG(VERBOSE) << "Sleep Power: " << response.sleep_power; LOG(VERBOSE) << "Peak Power: " << response.peak_power; LOG(VERBOSE) << "Platform ID: " << response.platform_id; LOG(VERBOSE) << "Vendor : " << getStringFromByteVector(response.vendor); LOG(VERBOSE) << "Toolchain : " << getStringFromByteVector(response.toolchain); LOG(VERBOSE) << "maxMessageLen : " << response.max_msg_len; if (response.max_msg_len < chre_constants::kMaxMessageLen) { LOG(WARNING) << "Incorrect max message length"; } } void SocketCallbacks::handleNanoappListResponse(const fbs::NanoappListResponseT& response) { LOG(VERBOSE) << "handleNanoAppListResponse"; for (const std::unique_ptr<fbs::NanoappListEntryT>& nanoapp : response.nanoapps) { if (nanoapp == nullptr) { continue; } if (nanoapp->app_id == chre_constants::kWifiOffloadNanoAppId && nanoapp->enabled) { LOG(INFO) << "Wifi Offload Nano app found"; LOG(INFO) << "Version: " << nanoapp->version; break; } } } void SocketCallbacks::handleLoadNanoappResponse(const fbs::LoadNanoappResponseT& response) { LOG(VERBOSE) << "Load Nano app response"; LOG(VERBOSE) << "Transaction ID: " << response.transaction_id; LOG(VERBOSE) << "Status: " << response.success; } void SocketCallbacks::handleUnloadNanoappResponse(const fbs::UnloadNanoappResponseT& response) { LOG(VERBOSE) << "Unload Nano app response"; LOG(VERBOSE) << "Transaction ID: " << response.transaction_id; LOG(VERBOSE) << "Status: " << response.success; } ChreInterface::ChreInterface(ChreInterfaceCallbacks* callback) : mSocketCallbacks(new SocketCallbacks(this)), mServerCallbacks(callback), mSocketConnected(false) { if (!mClient.connectInBackground(chre_constants::kSocketName, mSocketCallbacks)) { LOG(ERROR) << "Offload HAL is not connected to Chre"; } } ChreInterface::~ChreInterface() { mClient.disconnect(); } bool ChreInterface::isConnected() { std::lock_guard<std::mutex> lock(mChreInterfaceLock); return mSocketConnected; } void ChreInterface::reportConnectionEvent(ChreInterfaceCallbacks::ConnectionEvent event) { bool connectionStatus = false; switch (event) { case ChreInterfaceCallbacks::ConnectionEvent::CONNECTED: connectionStatus = true; if (!getHubInfo() || !getNanoAppList()) { LOG(WARNING) << "Unable to get platform and nano app info"; } break; case ChreInterfaceCallbacks::ConnectionEvent::DISCONNECTED: case ChreInterfaceCallbacks::ConnectionEvent::CONNECTION_ABORT: break; default: LOG(WARNING) << "Invalid connection event recieved"; return; } { std::lock_guard<std::mutex> lock(mChreInterfaceLock); mSocketConnected = connectionStatus; } mServerCallbacks->handleConnectionEvents(event); } bool ChreInterface::sendCommandToApp(uint32_t messageType, const std::vector<uint8_t>& message) { FlatBufferBuilder builder(chre_constants::kMaxMessageLen); void* messageData = nullptr; size_t messageDataLen = message.size(); if (messageDataLen > 0) { messageData = (void*)message.data(); } HostProtocolHost::encodeNanoappMessage(builder, chre_constants::kWifiOffloadNanoAppId, messageType, 0, messageData, messageDataLen); if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) { LOG(WARNING) << "Failed to send message to Nano app"; return false; } LOG(VERBOSE) << "Command sent " << messageType; return true; } void ChreInterface::handleMessage(uint32_t messageType, const void* messageData, size_t messageDataLen) { const uint8_t* messageBuf = reinterpret_cast<const uint8_t*>(messageData); std::vector<uint8_t> message(messageBuf, messageBuf + messageDataLen); mServerCallbacks->handleMessage(messageType, message); } bool ChreInterface::getHubInfo() { LOG(VERBOSE) << "getHubInfo"; FlatBufferBuilder builder(chre_constants::kHubInfoRequestBufLen); HostProtocolHost::encodeHubInfoRequest(builder); if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) { LOG(WARNING) << "Failed to send Hub Info request"; return false; } return true; } bool ChreInterface::getNanoAppList() { LOG(VERBOSE) << "getNanoAppList"; FlatBufferBuilder builder(chre_constants::kNanoAppListRequestBufLen); HostProtocolHost::encodeNanoappListRequest(builder); if (!mClient.sendMessage(builder.GetBufferPointer(), builder.GetSize())) { LOG(WARNING) << "Unable to send Nano app List request"; return false; } return true; } } // namespace implementation } // namespace V1_0 } // namespace offload } // namespace wifi } // namespace hardware } // namespace android