blob: 2f76776e4d229e18503d167ddb21bd515b94fab6 [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "power_manager/powerd/policy/wifi_controller.h"
#include "power_manager/common/prefs.h"
#include <base/check.h>
#include <base/check_op.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
namespace power_manager {
namespace policy {
const char WifiController::kUdevSubsystem[] = "net";
const char WifiController::kUdevDevtype[] = "wlan";
WifiController::WifiController() = default;
WifiController::~WifiController() {
if (udev_)
udev_->RemoveSubsystemObserver(kUdevSubsystem, this);
}
void WifiController::Init(Delegate* delegate,
PrefsInterface* prefs,
system::UdevInterface* udev,
TabletMode tablet_mode) {
DCHECK(delegate);
DCHECK(prefs);
DCHECK(udev);
delegate_ = delegate;
udev_ = udev;
tablet_mode_ = tablet_mode;
prefs->GetBool(kSetWifiTransmitPowerForTabletModePref,
&set_transmit_power_for_tablet_mode_);
prefs->GetBool(kSetWifiTransmitPowerForProximityPref,
&set_transmit_power_for_proximity_);
prefs->GetString(kWifiTransmitPowerModeForStaticDevicePref,
&transmit_power_mode_for_static_device_);
LOG(INFO) << "WifiController::Init: "
<< base::StringPrintf(
"%s=%d, %s=%d, %s=%s",
kSetWifiTransmitPowerForTabletModePref,
set_transmit_power_for_tablet_mode_,
kSetWifiTransmitPowerForProximityPref,
set_transmit_power_for_proximity_,
kWifiTransmitPowerModeForStaticDevicePref,
transmit_power_mode_for_static_device_.c_str());
if (set_transmit_power_for_tablet_mode_ &&
!transmit_power_mode_for_static_device_.empty()) {
LOG(FATAL) << "Invalid configuration: both "
<< kSetWifiTransmitPowerForTabletModePref << " and "
<< kWifiTransmitPowerModeForStaticDevicePref << " pref set";
}
// Update power input source based on prefs.
if (set_transmit_power_for_tablet_mode_) {
update_power_input_source_ = UpdatePowerInputSource::TABLET_MODE;
} else if (set_transmit_power_for_proximity_) {
// This is handled by WifiController::ProximitySensorDetected.
} else if (!transmit_power_mode_for_static_device_.empty()) {
static_mode_ = StaticModeFromString(transmit_power_mode_for_static_device_);
if (static_mode_ != StaticMode::UNSUPPORTED) {
update_power_input_source_ = UpdatePowerInputSource::STATIC_MODE;
} else {
LOG(WARNING) << "Invalid configuration: "
<< kWifiTransmitPowerModeForStaticDevicePref << '='
<< transmit_power_mode_for_static_device_;
}
}
udev_->AddSubsystemObserver(kUdevSubsystem, this);
UpdateTransmitPower();
}
void WifiController::HandleTabletModeChange(TabletMode mode) {
if (tablet_mode_ == mode)
return;
tablet_mode_ = mode;
UpdateTransmitPower();
}
void WifiController::HandleRegDomainChange(WifiRegDomain domain) {
if (wifi_reg_domain_ == domain)
return;
wifi_reg_domain_ = domain;
UpdateTransmitPower();
}
void WifiController::ProximitySensorDetected(UserProximity value) {
if (!set_transmit_power_for_proximity_)
return;
update_power_input_source_ = UpdatePowerInputSource::PROXIMITY;
LOG(INFO) << "Wifi power will be handled by proximity sensor";
HandleProximityChange(value);
}
void WifiController::HandleProximityChange(UserProximity proximity) {
if (proximity_ == proximity)
return;
proximity_ = proximity;
UpdateTransmitPower();
}
void WifiController::OnUdevEvent(const system::UdevEvent& event) {
DCHECK_EQ(event.device_info.subsystem, kUdevSubsystem);
if (event.action == system::UdevEvent::Action::ADD &&
event.device_info.devtype == kUdevDevtype)
UpdateTransmitPower();
}
void WifiController::UpdateTransmitPower() {
switch (update_power_input_source_) {
case UpdatePowerInputSource::TABLET_MODE:
UpdateTransmitPowerForTabletMode();
break;
case UpdatePowerInputSource::PROXIMITY:
UpdateTransmitPowerForProximity();
break;
case UpdatePowerInputSource::STATIC_MODE:
UpdateTransmitPowerForStaticMode();
break;
case UpdatePowerInputSource::NONE:
break;
}
}
void WifiController::UpdateTransmitPowerForStaticMode() {
switch (static_mode_) {
case StaticMode::UNSUPPORTED:
break;
case StaticMode::HIGH_TRANSMIT_POWER:
delegate_->SetWifiTransmitPower(RadioTransmitPower::HIGH,
wifi_reg_domain_);
break;
case StaticMode::LOW_TRANSMIT_POWER:
delegate_->SetWifiTransmitPower(RadioTransmitPower::LOW,
wifi_reg_domain_);
break;
}
}
void WifiController::UpdateTransmitPowerForTabletMode() {
switch (tablet_mode_) {
case TabletMode::UNSUPPORTED:
break;
case TabletMode::ON:
delegate_->SetWifiTransmitPower(RadioTransmitPower::LOW,
wifi_reg_domain_);
break;
case TabletMode::OFF:
delegate_->SetWifiTransmitPower(RadioTransmitPower::HIGH,
wifi_reg_domain_);
break;
}
}
void WifiController::UpdateTransmitPowerForProximity() {
switch (proximity_) {
case UserProximity::UNKNOWN:
break;
case UserProximity::NEAR:
delegate_->SetWifiTransmitPower(RadioTransmitPower::LOW,
wifi_reg_domain_);
break;
case UserProximity::FAR:
delegate_->SetWifiTransmitPower(RadioTransmitPower::HIGH,
wifi_reg_domain_);
break;
}
}
} // namespace policy
} // namespace power_manager