wifi(hidl): Modify the SAR power levels interface

Modifying the interface used to lower the tx power level for meeting SAR
requirements based on recommendation from the nexus hardware team. The
previous interface passed in a single power value in dBm for meeting SAR
requirements. However, the SAR requirements are more complex than that.
Based on the connection mode (802.11 a,b,g,n,ac) and the number of
streams that are active (MIMO), the SAR power levels are very
different. Using the previous interface would mean that we will have to
use the lowest power level among all the connection modes to meet the SAR
requirements. This would however result in us lowering the power much
more than needed (~2 dBm) for many connection modes.
Instead, we're switching to a more generic interface where the framework
informs the wifi chip that we're entering a special tx power mode scenario
(today, there is only 1 for voice call). The chip can then lookup the
extensive table of power levels for different connection modes which are
pre-populated by the OEM's in the BDF file to set the power level (depending
on the scenario framework sends and the active connection mode).

Bug: 62437848
Test: Manual tests
Change-Id: I5ee3f0d2c130958dbeb352e3b5ad9407f432624f
This commit is contained in:
Roshan Pius 2017-07-25 08:48:08 -07:00
parent 5614b96de5
commit 735ff43197
10 changed files with 83 additions and 53 deletions

View file

@ -219,4 +219,4 @@ bb7c96762d0aa3ddb874c8815bacdd3cbc8fb87ea2f82b928bc29e24a3593055 android.hardwar
c3354ab0d381a236c12dc486ad4b6bec28c979d26748b4661f12ede36f392808 android.hardware.wifi.offload@1.0::IOffloadCallback
b18caefefcc765092412285d776234fcf213b73bdf07ae1b67a5f71b2d2464e3 android.hardware.wifi.offload@1.0::types
c26473e2e4a00af43e28a0ddf9002e5062a7d0940429e5efb6e5513a8abcb75c android.hardware.wifi@1.1::IWifi
bfcf4856c7b6c66ebc56785ed3e5d181b7be859c2add672497a843b024518737 android.hardware.wifi@1.1::IWifiChip
b056e1defab4071584214584057d0bc73a613081bf1152590549649d4582c13c android.hardware.wifi@1.1::IWifiChip

View file

@ -1,5 +1,5 @@
/*
* Copyright 2016 The Android Open Source Project
* Copyright 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.
@ -44,24 +44,40 @@ interface IWifiChip extends @1.0::IWifiChip {
};
/**
* API to set TX power limit.
* This is used for meeting SAR requirements while making VOIP calls for
* example.
*
* @param powerInDbm Power level in dBm.
* @return status WifiStatus of the operation.
* Possible status codes:
* |WifiStatusCode.SUCCESS|,
* |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
* |WifiStatusCode.ERROR_NOT_SUPPORTED|,
* |WifiStatusCode.NOT_AVAILABLE|,
* |WifiStatusCode.UNKNOWN|
* List of preset wifi radio TX power levels for different scenarios.
* The actual power values (typically varies based on the channel,
* 802.11 connection type, number of MIMO streams, etc) for each scenario
* is defined by the OEM as a BDF file since it varies for each wifi chip
* vendor and device.
*/
setTxPowerLimit(int32_t powerInDbm) generates (WifiStatus status);
enum TxPowerScenario : uint32_t {
VOICE_CALL = 0,
};
/**
* API to reset TX power limit.
* This is used to set the power back to default values.
* API to select one of the preset TX power scenarios.
*
* The framework must invoke this method with the appropriate scenario to let
* the wifi chip change it's transmitting power levels.
* OEM's should define various power profiles for each of the scenarios
* above (defined in |TxPowerScenario|).
*
* @param scenario One of the preselected scenarios defined in
* |TxPowerScenario|.
* @return status WifiStatus of the operation.
* Possible status codes:
* |WifiStatusCode.SUCCESS|,
* |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
* |WifiStatusCode.ERROR_NOT_SUPPORTED|,
* |WifiStatusCode.NOT_AVAILABLE|,
* |WifiStatusCode.UNKNOWN|
*/
selectTxPowerScenario(TxPowerScenario scenario) generates (WifiStatus status);
/**
* API to reset TX power levels.
* This is used to indicate the end of the previously selected TX power
* scenario and let the wifi chip fall back to the default power values.
*
* @return status WifiStatus of the operation.
* Possible status codes:
@ -71,5 +87,5 @@ interface IWifiChip extends @1.0::IWifiChip {
* |WifiStatusCode.NOT_AVAILABLE|,
* |WifiStatusCode.UNKNOWN|
*/
resetTxPowerLimit() generates (WifiStatus status);
resetTxPowerScenario() generates (WifiStatus status);
};

View file

@ -17,9 +17,6 @@
#include <android-base/logging.h>
#include <utils/SystemClock.h>
#include <android/hardware/wifi/1.0/IWifiChip.h>
#include <android/hardware/wifi/1.1/IWifiChip.h>
#include "hidl_struct_util.h"
namespace android {
@ -260,6 +257,15 @@ bool convertLegacyWakeReasonStatsToHidl(
return true;
}
legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
V1_1::IWifiChip::TxPowerScenario hidl_scenario) {
switch (hidl_scenario) {
case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL:
return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL;
};
CHECK(false);
}
bool convertLegacyFeaturesToHidlStaCapabilities(
uint32_t legacy_feature_set,
uint32_t legacy_logger_feature_set,

View file

@ -20,6 +20,8 @@
#include <vector>
#include <android/hardware/wifi/1.0/types.h>
#include <android/hardware/wifi/1.0/IWifiChip.h>
#include <android/hardware/wifi/1.1/IWifiChip.h>
#include "wifi_legacy_hal.h"
@ -51,6 +53,8 @@ bool convertLegacyVectorOfDebugRingBufferStatusToHidl(
bool convertLegacyWakeReasonStatsToHidl(
const legacy_hal::WakeReasonStats& legacy_stats,
WifiDebugHostWakeReasonStats* hidl_stats);
legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
V1_1::IWifiChip::TxPowerScenario hidl_scenario);
// STA iface conversion methods.
bool convertLegacyFeaturesToHidlStaCapabilities(

View file

@ -343,20 +343,20 @@ Return<void> WifiChip::enableDebugErrorAlerts(
enable);
}
Return<void> WifiChip::setTxPowerLimit(
int32_t powerInDbm, setTxPowerLimit_cb hidl_status_cb) {
Return<void> WifiChip::selectTxPowerScenario(
TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) {
return validateAndCall(this,
WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::setTxPowerLimitInternal,
&WifiChip::selectTxPowerScenarioInternal,
hidl_status_cb,
powerInDbm);
scenario);
}
Return<void> WifiChip::resetTxPowerLimit(
resetTxPowerLimit_cb hidl_status_cb) {
Return<void> WifiChip::resetTxPowerScenario(
resetTxPowerScenario_cb hidl_status_cb) {
return validateAndCall(this,
WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::resetTxPowerLimitInternal,
&WifiChip::resetTxPowerScenarioInternal,
hidl_status_cb);
}
@ -824,13 +824,14 @@ WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) {
return createWifiStatusFromLegacyError(legacy_status);
}
WifiStatus WifiChip::setTxPowerLimitInternal(int32_t powerInDbm) {
auto legacy_status = legacy_hal_.lock()->setTxPowerLimit(powerInDbm);
WifiStatus WifiChip::selectTxPowerScenarioInternal(TxPowerScenario scenario) {
auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
return createWifiStatusFromLegacyError(legacy_status);
}
WifiStatus WifiChip::resetTxPowerLimitInternal() {
auto legacy_status = legacy_hal_.lock()->resetTxPowerLimit();
WifiStatus WifiChip::resetTxPowerScenarioInternal() {
auto legacy_status = legacy_hal_.lock()->resetTxPowerScenario();
return createWifiStatusFromLegacyError(legacy_status);
}

View file

@ -126,9 +126,11 @@ class WifiChip : public V1_1::IWifiChip {
getDebugHostWakeReasonStats_cb hidl_status_cb) override;
Return<void> enableDebugErrorAlerts(
bool enable, enableDebugErrorAlerts_cb hidl_status_cb) override;
Return<void> setTxPowerLimit(
int32_t powerInDbm, setTxPowerLimit_cb hidl_status_cb) override;
Return<void> resetTxPowerLimit(resetTxPowerLimit_cb hidl_status_cb) override;
Return<void> selectTxPowerScenario(
TxPowerScenario scenario,
selectTxPowerScenario_cb hidl_status_cb) override;
Return<void> resetTxPowerScenario(
resetTxPowerScenario_cb hidl_status_cb) override;
private:
void invalidateAndRemoveAllIfaces();
@ -180,8 +182,8 @@ class WifiChip : public V1_1::IWifiChip {
std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
getDebugHostWakeReasonStatsInternal();
WifiStatus enableDebugErrorAlertsInternal(bool enable);
WifiStatus setTxPowerLimitInternal(int32_t powerInDbm);
WifiStatus resetTxPowerLimitInternal();
WifiStatus selectTxPowerScenarioInternal(TxPowerScenario scenario);
WifiStatus resetTxPowerScenarioInternal();
WifiStatus handleChipConfiguration(ChipModeId mode_id);
WifiStatus registerDebugRingBufferCallback();

View file

@ -752,13 +752,13 @@ wifi_error WifiLegacyHal::setScanningMacOui(const std::array<uint8_t, 3>& oui) {
oui_internal.data());
}
wifi_error WifiLegacyHal::setTxPowerLimit(int32_t tx_level_dbm) {
return global_func_table_.wifi_set_tx_power_limit(wlan_interface_handle_,
tx_level_dbm);
wifi_error WifiLegacyHal::selectTxPowerScenario(wifi_power_scenario scenario) {
return global_func_table_.wifi_select_tx_power_scenario(
wlan_interface_handle_, scenario);
}
wifi_error WifiLegacyHal::resetTxPowerLimit() {
return global_func_table_.wifi_reset_tx_power_limit(wlan_interface_handle_);
wifi_error WifiLegacyHal::resetTxPowerScenario() {
return global_func_table_.wifi_reset_tx_power_scenario(wlan_interface_handle_);
}
std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet() {

View file

@ -205,8 +205,8 @@ class WifiLegacyHal {
uint32_t period_in_ms);
wifi_error stopSendingOffloadedPacket(uint32_t cmd_id);
wifi_error setScanningMacOui(const std::array<uint8_t, 3>& oui);
wifi_error setTxPowerLimit(int32_t tx_level_dbm);
wifi_error resetTxPowerLimit();
wifi_error selectTxPowerScenario(wifi_power_scenario scenario);
wifi_error resetTxPowerScenario();
// Logger/debug functions.
std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet();
wifi_error startPktFateMonitoring();

View file

@ -132,8 +132,8 @@ bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) {
populateStubFor(&hal_fn->wifi_get_roaming_capabilities);
populateStubFor(&hal_fn->wifi_enable_firmware_roaming);
populateStubFor(&hal_fn->wifi_configure_roaming);
populateStubFor(&hal_fn->wifi_set_tx_power_limit);
populateStubFor(&hal_fn->wifi_reset_tx_power_limit);
populateStubFor(&hal_fn->wifi_select_tx_power_scenario);
populateStubFor(&hal_fn->wifi_reset_tx_power_scenario);
return true;
}
} // namespace legacy_hal

View file

@ -37,7 +37,8 @@ using ::android::hardware::wifi::V1_1::IWifiChip;
using ::android::hardware::wifi::V1_0::IWifiStaIface;
namespace {
constexpr int32_t kFakePowerInDbm = -56;
constexpr IWifiChip::TxPowerScenario kFakePowerScenario =
IWifiChip::TxPowerScenario::VOICE_CALL;
}; //namespace
/**
@ -66,12 +67,12 @@ class WifiChipHidlTest : public ::testing::VtsHalHidlTargetTestBase {
};
/*
* SetTxPowerLimit
* SelectTxPowerScenario
*/
TEST_F(WifiChipHidlTest, SetTxPowerLimit) {
TEST_F(WifiChipHidlTest, SelectTxPowerScenario) {
uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
const auto& status =
HIDL_INVOKE(wifi_chip_, setTxPowerLimit, kFakePowerInDbm);
HIDL_INVOKE(wifi_chip_, selectTxPowerScenario, kFakePowerScenario);
if (caps & IWifiChip::ChipCapabilityMask::SET_TX_POWER_LIMIT) {
EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
} else {
@ -80,12 +81,12 @@ TEST_F(WifiChipHidlTest, SetTxPowerLimit) {
}
/*
* SetTxPowerLimit
* ResetTxPowerScenario
*/
TEST_F(WifiChipHidlTest, ResetTxPowerLimit) {
TEST_F(WifiChipHidlTest, ResetTxPowerScenario) {
uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
const auto& status =
HIDL_INVOKE(wifi_chip_, resetTxPowerLimit);
HIDL_INVOKE(wifi_chip_, resetTxPowerScenario);
if (caps & IWifiChip::ChipCapabilityMask::SET_TX_POWER_LIMIT) {
EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
} else {