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_