wifi: Helper functions for invoking hidl cont callbacks am: 5647665827 am: 1ab8395a21

am: 8a9ab30d5c

Change-Id: I04bc3b3c5138e4ba6830a50967556caecf4118fc
This commit is contained in:
Roshan Pius
2016-11-17 01:12:30 +00:00
committed by android-build-merger
4 changed files with 192 additions and 44 deletions

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2016 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 HIDL_RETURN_UTIL_H_
#define HIDL_RETURN_UTIL_H_
#include "wifi_status_util.h"
namespace android {
namespace hardware {
namespace wifi {
namespace V1_0 {
namespace implementation {
namespace hidl_return_util {
/**
* These utility functions are used to invoke a method on the provided
* HIDL interface object.
* These functions checks if the provided HIDL interface object is valid.
* a) if valid, Invokes the corresponding internal implementation function of
* the HIDL method. It then invokes the HIDL continuation callback with
* the status and any returned values.
* b) if invalid, invokes the HIDL continuation callback with the
* provided error status and default values.
*/
// Use for HIDL methods which return only an instance of WifiStatus.
template <typename ObjT, typename WorkFuncT, typename... Args>
Return<void> validateAndCall(
ObjT* obj,
WifiStatusCode status_code_if_invalid,
WorkFuncT&& work,
const std::function<void(const WifiStatus&)>& hidl_cb,
Args&&... args) {
if (obj->isValid()) {
hidl_cb((obj->*work)(std::forward<Args>(args)...));
} else {
hidl_cb(createWifiStatus(status_code_if_invalid));
}
return Void();
}
// Use for HIDL methods which return instance of WifiStatus and a single return
// value.
template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
Return<void> validateAndCall(
ObjT* obj,
WifiStatusCode status_code_if_invalid,
WorkFuncT&& work,
const std::function<void(const WifiStatus&, ReturnT)>& hidl_cb,
Args&&... args) {
if (obj->isValid()) {
const auto& ret_pair = (obj->*work)(std::forward<Args>(args)...);
const WifiStatus& status = std::get<0>(ret_pair);
const auto& ret_value = std::get<1>(ret_pair);
hidl_cb(status, ret_value);
} else {
hidl_cb(createWifiStatus(status_code_if_invalid),
typename std::remove_reference<ReturnT>::type());
}
return Void();
}
// Use for HIDL methods which return instance of WifiStatus and 2 return
// values.
template <typename ObjT,
typename WorkFuncT,
typename ReturnT1,
typename ReturnT2,
typename... Args>
Return<void> validateAndCall(
ObjT* obj,
WifiStatusCode status_code_if_invalid,
WorkFuncT&& work,
const std::function<void(const WifiStatus&, ReturnT1, ReturnT2)>& hidl_cb,
Args&&... args) {
if (obj->isValid()) {
const auto& ret_tuple = (obj->*work)(std::forward<Args>(args)...);
const WifiStatus& status = std::get<0>(ret_tuple);
const auto& ret_value1 = std::get<1>(ret_tuple);
const auto& ret_value2 = std::get<2>(ret_tuple);
hidl_cb(status, ret_value1, ret_value2);
} else {
hidl_cb(createWifiStatus(status_code_if_invalid),
typename std::remove_reference<ReturnT1>::type(),
typename std::remove_reference<ReturnT2>::type());
}
return Void();
}
} // namespace hidl_util
} // namespace implementation
} // namespace V1_0
} // namespace wifi
} // namespace hardware
} // namespace android
#endif // HIDL_RETURN_UTIL_H_

View File

@@ -14,11 +14,10 @@
* limitations under the License.
*/
#include "wifi.h"
#include <android-base/logging.h>
#include "wifi_chip.h"
#include "hidl_return_util.h"
#include "wifi.h"
#include "wifi_status_util.h"
namespace {
@@ -31,15 +30,24 @@ namespace hardware {
namespace wifi {
namespace V1_0 {
namespace implementation {
using hidl_return_util::validateAndCall;
Wifi::Wifi()
: legacy_hal_(new WifiLegacyHal()), run_state_(RunState::STOPPED) {}
bool Wifi::isValid() {
// This object is always valid.
return true;
}
Return<void> Wifi::registerEventCallback(
const sp<IWifiEventCallback>& event_callback) {
// TODO(b/31632518): remove the callback when the client is destroyed
event_callbacks_.emplace_back(event_callback);
return Void();
const sp<IWifiEventCallback>& event_callback,
registerEventCallback_cb hidl_status_cb) {
return validateAndCall(this,
WifiStatusCode::ERROR_UNKNOWN,
&Wifi::registerEventCallbackInternal,
hidl_status_cb,
event_callback);
}
Return<bool> Wifi::isStarted() {
@@ -47,22 +55,53 @@ Return<bool> Wifi::isStarted() {
}
Return<void> Wifi::start(start_cb hidl_status_cb) {
return validateAndCall(this,
WifiStatusCode::ERROR_UNKNOWN,
&Wifi::startInternal,
hidl_status_cb);
}
Return<void> Wifi::stop(stop_cb hidl_status_cb) {
return validateAndCall(
this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal, hidl_status_cb);
}
Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
return validateAndCall(this,
WifiStatusCode::ERROR_UNKNOWN,
&Wifi::getChipIdsInternal,
hidl_status_cb);
}
Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) {
return validateAndCall(this,
WifiStatusCode::ERROR_UNKNOWN,
&Wifi::getChipInternal,
hidl_status_cb,
chip_id);
}
WifiStatus Wifi::registerEventCallbackInternal(
const sp<IWifiEventCallback>& event_callback) {
// TODO(b/31632518): remove the callback when the client is destroyed
event_callbacks_.emplace_back(event_callback);
return createWifiStatus(WifiStatusCode::SUCCESS);
}
WifiStatus Wifi::startInternal() {
if (run_state_ == RunState::STARTED) {
hidl_status_cb(createWifiStatus(WifiStatusCode::SUCCESS));
return Void();
return createWifiStatus(WifiStatusCode::SUCCESS);
} else if (run_state_ == RunState::STOPPING) {
hidl_status_cb(createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
"HAL is stopping"));
return Void();
return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
"HAL is stopping");
}
LOG(INFO) << "Starting HAL";
wifi_error legacy_status = legacy_hal_->start();
if (legacy_status != WIFI_SUCCESS) {
LOG(ERROR) << "Failed to start Wifi HAL";
hidl_status_cb(
createWifiStatusFromLegacyError(legacy_status, "Failed to start HAL"));
return Void();
return createWifiStatusFromLegacyError(legacy_status,
"Failed to start HAL");
}
// Create the chip instance once the HAL is started.
@@ -73,18 +112,15 @@ Return<void> Wifi::start(start_cb hidl_status_cb) {
LOG(ERROR) << "Failed to invoke onStart callback";
};
}
hidl_status_cb(createWifiStatus(WifiStatusCode::SUCCESS));
return Void();
return createWifiStatus(WifiStatusCode::SUCCESS);
}
Return<void> Wifi::stop(stop_cb hidl_status_cb) {
WifiStatus Wifi::stopInternal() {
if (run_state_ == RunState::STOPPED) {
hidl_status_cb(createWifiStatus(WifiStatusCode::SUCCESS));
return Void();
return createWifiStatus(WifiStatusCode::SUCCESS);
} else if (run_state_ == RunState::STOPPING) {
hidl_status_cb(createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
"HAL is stopping"));
return Void();
return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
"HAL is stopping");
}
LOG(INFO) << "Stopping HAL";
@@ -109,33 +145,28 @@ Return<void> Wifi::stop(stop_cb hidl_status_cb) {
for (const auto& callback : event_callbacks_) {
callback->onFailure(wifi_status);
}
hidl_status_cb(wifi_status);
return Void();
return wifi_status;
}
hidl_status_cb(createWifiStatus(WifiStatusCode::SUCCESS));
return Void();
return createWifiStatus(WifiStatusCode::SUCCESS);
}
Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
std::pair<WifiStatus, std::vector<ChipId>> Wifi::getChipIdsInternal() {
std::vector<ChipId> chip_ids;
if (chip_.get()) {
chip_ids.emplace_back(kChipId);
}
hidl_vec<ChipId> hidl_data;
hidl_data.setToExternal(chip_ids.data(), chip_ids.size());
hidl_status_cb(hidl_data);
return Void();
return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)};
}
Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) {
if (chip_.get() && chip_id == kChipId) {
hidl_status_cb(chip_);
} else {
hidl_status_cb(nullptr);
std::pair<WifiStatus, sp<IWifiChip>> Wifi::getChipInternal(ChipId chip_id) {
if (!chip_.get()) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_STARTED), nullptr};
}
return Void();
if (chip_id != kChipId) {
return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
}
return {createWifiStatus(WifiStatusCode::SUCCESS), chip_};
}
} // namespace implementation
} // namespace V1_0
} // namespace wifi

View File

@@ -39,9 +39,12 @@ class Wifi : public IWifi {
public:
Wifi();
bool isValid();
// HIDL methods exposed.
Return<void> registerEventCallback(
const sp<IWifiEventCallback>& event_callback) override;
const sp<IWifiEventCallback>& event_callback,
registerEventCallback_cb hidl_status_cb) override;
Return<bool> isStarted() override;
Return<void> start(start_cb hidl_status_cb) override;
Return<void> stop(stop_cb hidl_status_cb) override;
@@ -51,6 +54,14 @@ class Wifi : public IWifi {
private:
enum class RunState { STOPPED, STARTED, STOPPING };
// Corresponding worker functions for the HIDL methods.
WifiStatus registerEventCallbackInternal(
const sp<IWifiEventCallback>& event_callback);
WifiStatus startInternal();
WifiStatus stopInternal();
std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
std::pair<WifiStatus, sp<IWifiChip>> getChipInternal(ChipId chip_id);
// Instance is created in this root level |IWifi| HIDL interface object
// and shared with all the child HIDL interface objects.
std::shared_ptr<WifiLegacyHal> legacy_hal_;

View File

@@ -50,10 +50,7 @@ std::string legacyErrorToString(wifi_error error) {
WifiStatus createWifiStatus(WifiStatusCode code,
const std::string& description) {
WifiStatus result;
result.code = code;
result.description = description.data();
return result;
return {code, description};
}
WifiStatus createWifiStatus(WifiStatusCode code) {