From 29a90c0b97baf0142b0193bc006c33bd4a02da2e Mon Sep 17 00:00:00 2001 From: Sohani Rao Date: Tue, 9 May 2017 14:07:32 -0700 Subject: [PATCH] Offload HAL Service: Interface to CHRE platform Wraps around CHRE socket to provide an interface for service implementation to interact with the CHRE socket. Implements callbacks and corresponding host specific wrappers to interpret messages send by the nano app. Bug: 32842314 Test: VTS Change-Id: I8f40a6d5aa6fcb946213225ba6bb1ff355b85f06 --- sepolicy/hal_wifi_offload_default.te | 3 + wifi_offload/Android.bp | 7 +- ...droid.hardware.wifi.offload@1.0-service.rc | 2 +- wifi_offload/chre_interface.cpp | 182 ++++++++++++++++++ wifi_offload/chre_interface.h | 86 +++++++++ 5 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 sepolicy/hal_wifi_offload_default.te create mode 100644 wifi_offload/chre_interface.cpp create mode 100644 wifi_offload/chre_interface.h diff --git a/sepolicy/hal_wifi_offload_default.te b/sepolicy/hal_wifi_offload_default.te new file mode 100644 index 00000000..00df6a73 --- /dev/null +++ b/sepolicy/hal_wifi_offload_default.te @@ -0,0 +1,3 @@ +# Allow Wifi Offload HAL to communicate with daemon via socket +allow hal_wifi_offload_default chre:unix_stream_socket connectto; +allow hal_wifi_offload_default chre_socket:sock_file write; diff --git a/wifi_offload/Android.bp b/wifi_offload/Android.bp index e55b60e2..646994d4 100644 --- a/wifi_offload/Android.bp +++ b/wifi_offload/Android.bp @@ -17,7 +17,11 @@ cc_binary { name: "android.hardware.wifi.offload@1.0-service", relative_install_path: "hw", init_rc: ["android.hardware.wifi.offload@1.0-service.rc"], - srcs: ["Offload.cpp", "service.cpp", "chre_constants.cpp"], + srcs: ["Offload.cpp", + "service.cpp", + "chre_constants.cpp", + "chre_interface.cpp", + ], cflags: ["-Wall", "-Wextra"], shared_libs: [ "libbase", @@ -27,6 +31,7 @@ cc_binary { "libutils", "android.hardware.wifi.offload@1.0", ], + static_libs: ["chre_client"], proprietary: true, } diff --git a/wifi_offload/android.hardware.wifi.offload@1.0-service.rc b/wifi_offload/android.hardware.wifi.offload@1.0-service.rc index f90d63ff..84e03911 100644 --- a/wifi_offload/android.hardware.wifi.offload@1.0-service.rc +++ b/wifi_offload/android.hardware.wifi.offload@1.0-service.rc @@ -1,4 +1,4 @@ service offload-hal-1-0 /vendor/bin/hw/android.hardware.wifi.offload@1.0-service class hal user wifi - group wifi + group wifi system diff --git a/wifi_offload/chre_interface.cpp b/wifi_offload/chre_interface.cpp new file mode 100644 index 00000000..140cceb7 --- /dev/null +++ b/wifi_offload/chre_interface.cpp @@ -0,0 +1,182 @@ +/* + * 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 + +#include + +#include "chre_host/host_protocol_host.h" + +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(uint64_t appId, uint32_t messageType, + uint16_t hostEndpoint, const void* messageData, + size_t messageDataLen) { + LOG(VERBOSE) << "handleNanoappMessage from appId: " << appId; + LOG(VERBOSE) << "HostEndPoint: " << hostEndpoint; + if (appId == chre_constants::kWifiOffloadNanoAppId) { + mParent->handleMessage(messageType, messageData, messageDataLen); + } +} + +void SocketCallbacks::handleHubInfoResponse(const char* name, const char* vendor, + const char* toolchain, uint32_t legacyPlatformVersion, + uint32_t legacyToolchainVersion, float peakMips, + float stoppedPower, float sleepPower, float peakPower, + uint32_t maxMessageLen, uint64_t platformId, + uint32_t version) { + LOG(VERBOSE) << "Hub Info response"; + LOG(VERBOSE) << "Hub Info name: " << name; + LOG(VERBOSE) << "Version : " << version; + LOG(VERBOSE) << "Legacy Platform Version: " << legacyPlatformVersion; + LOG(VERBOSE) << "Legacy Toolchain Version: " << legacyToolchainVersion; + LOG(VERBOSE) << "Peak Mips: " << peakMips; + LOG(VERBOSE) << "Stopped Power: " << stoppedPower; + LOG(VERBOSE) << "Sleep Power: " << sleepPower; + LOG(VERBOSE) << "Peak Power: " << peakPower; + LOG(VERBOSE) << "Platform ID: " << platformId; + LOG(VERBOSE) << "Vendor : " << vendor; + LOG(VERBOSE) << "Toolchain : " << toolchain; + LOG(VERBOSE) << "maxMessageLen : " << maxMessageLen; + if (maxMessageLen < chre_constants::kMaxMessageLen) { + LOG(WARNING) << "Incorrect max message length"; + } +} + +void SocketCallbacks::handleNanoappListResponse(const fbs::NanoappListResponseT& response) { + LOG(VERBOSE) << "handleNanoAppListResponse"; + for (const std::unique_ptr& 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) { + if (!mClient.connectInBackground(chre_constants::kSocketName, mSocketCallbacks)) { + LOG(ERROR) << "Offload HAL is not connected to Chre"; + } +} + +ChreInterface::~ChreInterface() { + mClient.disconnect(); +} + +bool ChreInterface::isConnected() { + return mClient.isConnected(); +} + +void ChreInterface::reportConnectionEvent(ChreInterfaceCallbacks::ConnectionEvent event) { + switch (event) { + case ChreInterfaceCallbacks::ConnectionEvent::CONNECTED: + break; + case ChreInterfaceCallbacks::ConnectionEvent::DISCONNECTED: + break; + case ChreInterfaceCallbacks::ConnectionEvent::CONNECTION_ABORT: + break; + default: + LOG(WARNING) << "Invalid connection event recieved"; + return; + } + mServerCallbacks->handleConnectionEvents(event); +} + +bool ChreInterface::sendCommandToApp(uint32_t messageType, const std::vector& 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(messageData); + std::vector message(messageBuf, messageBuf + messageDataLen); + mServerCallbacks->handleMessage(messageType, message); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace offload +} // namespace wifi +} // namespace hardware +} // namespace android diff --git a/wifi_offload/chre_interface.h b/wifi_offload/chre_interface.h new file mode 100644 index 00000000..0b6fa589 --- /dev/null +++ b/wifi_offload/chre_interface.h @@ -0,0 +1,86 @@ +/* + * 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. + */ +#ifndef WIFI_OFFLOAD_CHRE_INTERFACE_H_ +#define WIFI_OFFLOAD_CHRE_INTERFACE_H_ + +#include "chre_constants.h" +#include "chre_host/host_protocol_host.h" +#include "chre_host/socket_client.h" +#include "chre_interface_callbacks.h" + +namespace android { +namespace hardware { +namespace wifi { +namespace offload { +namespace V1_0 { +namespace implementation { + +class ChreInterface; + +class SocketCallbacks + : public ::android::chre::SocketClient::ICallbacks, + public ::android::chre::IChreMessageHandlers { + public: + SocketCallbacks(ChreInterface* parent); + void onMessageReceived(const void* data, size_t length) override; + void onConnected() override; + void onConnectionAborted() override; + void onDisconnected() override; + void handleNanoappMessage(uint64_t appId, uint32_t messageType, uint16_t hostEndpoint, + const void* messageData, size_t messageDataLen) override; + void handleHubInfoResponse(const char* name, const char* vendor, const char* toolchain, + uint32_t legacyPlatformVersion, uint32_t legacyToolchainVersion, + float peakMips, float stoppedPower, float sleepPower, + float peakPower, uint32_t maxMessageLen, uint64_t platformId, + uint32_t version) override; + void handleNanoappListResponse(const ::chre::fbs::NanoappListResponseT& response) override; + void handleLoadNanoappResponse(const ::chre::fbs::LoadNanoappResponseT& response) override; + void handleUnloadNanoappResponse(const ::chre::fbs::UnloadNanoappResponseT& response) override; + + private: + ChreInterface* mParent; +}; + +class ChreInterface { + public: + ChreInterface(ChreInterfaceCallbacks* callback); + ~ChreInterface(); + /* Return the status of socket connection */ + bool isConnected(); + /* Send a message to the Nano app, returns true if send successful */ + bool sendCommandToApp(uint32_t messageType, const std::vector& message); + /* Connected or connection restart handling method */ + void reportConnectionEvent(ChreInterfaceCallbacks::ConnectionEvent /* event */); + /* Requests Hub Information, returns true if Hub Info request was sent */ + bool getHubInfo(); + /* Request list of Nano apps, returns true if Nano app List request was sent */ + bool getNanoAppList(); + /* Invoked by the socket callbacks when a message is recieved from Nano app */ + void handleMessage(uint32_t messageType, const void* messageData, size_t messageDataLen); + + private: + ::android::chre::SocketClient mClient; + sp mSocketCallbacks; + ChreInterfaceCallbacks* mServerCallbacks; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace offload +} // namespace wifi +} // namespace hardware +} // namespace android +#endif // WIFI_OFFLOAD_CHRE_INTERFACE_H_