Skip to content

Commit 293e498

Browse files
Gordon SetoChromium LUCI CQ
authored andcommitted
[CrOS Bluetooth] Create BluetoothPowerController.
Create BluetoothPowerController to manage setting the Bluetooth adapter state, saving the state to prefs, and applying the pref on device startup or user login. The logic in this class is largely taken from the BluetoothPowerController in ash/system/bluetooth, except CrosBluetoothConfig APIs are used instead of BluetoothAdapter and ash-specific SessionManager methods are replaced with UserManager equivalents. For design doc, see go/cros-bluetooth-revamp-power-controller. Bug: 1010321 Change-Id: I17c6e1a03d6368c8caf74e69f78b4e28cae37892 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3263257 Commit-Queue: Gordon Seto <gordonseto@google.com> Reviewed-by: Kyle Horimoto <khorimoto@chromium.org> Reviewed-by: Xiyuan Xia <xiyuan@chromium.org> Reviewed-by: Chad Duffin <chadduffin@chromium.org> Cr-Commit-Position: refs/heads/main@{#940471}
1 parent d7362e0 commit 293e498

13 files changed

+672
-2
lines changed

chromeos/services/bluetooth_config/BUILD.gn

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ static_library("bluetooth_config") {
1010
"adapter_state_controller.h",
1111
"adapter_state_controller_impl.cc",
1212
"adapter_state_controller_impl.h",
13+
"bluetooth_power_controller.h",
14+
"bluetooth_power_controller_impl.cc",
15+
"bluetooth_power_controller_impl.h",
1316
"cros_bluetooth_config.cc",
1417
"cros_bluetooth_config.h",
1518
"device_cache.cc",
@@ -45,6 +48,7 @@ static_library("bluetooth_config") {
4548
]
4649

4750
deps = [
51+
"//ash/constants",
4852
"//base",
4953
"//chromeos/services/bluetooth_config/public/cpp",
5054
"//chromeos/services/bluetooth_config/public/mojom",
@@ -86,6 +90,8 @@ static_library("test_support") {
8690
"fake_adapter_state_controller.h",
8791
"fake_bluetooth_discovery_delegate.cc",
8892
"fake_bluetooth_discovery_delegate.h",
93+
"fake_bluetooth_power_controller.cc",
94+
"fake_bluetooth_power_controller.h",
8995
"fake_device_cache.cc",
9096
"fake_device_cache.h",
9197
"fake_device_name_manager.cc",
@@ -112,6 +118,7 @@ static_library("test_support") {
112118
":bluetooth_config",
113119
":in_process_bluetooth_config",
114120
"//base",
121+
"//chromeos/services/bluetooth_config/public/cpp",
115122
"//chromeos/services/bluetooth_config/public/mojom",
116123
"//components/session_manager/core",
117124
"//device/bluetooth",
@@ -124,6 +131,7 @@ source_set("unit_tests") {
124131

125132
sources = [
126133
"adapter_state_controller_impl_unittest.cc",
134+
"bluetooth_power_controller_impl_unittest.cc",
127135
"cros_bluetooth_config_unittest.cc",
128136
"device_cache_impl_unittest.cc",
129137
"device_conversion_util_unittest.cc",
@@ -137,6 +145,7 @@ source_set("unit_tests") {
137145
deps = [
138146
":bluetooth_config",
139147
":test_support",
148+
"//ash/constants",
140149
"//base",
141150
"//base/test:test_support",
142151
"//components/session_manager/core",
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
include_rules = [
2+
"+ash/constants",
23
"+components/device_event_log",
3-
"+components/user_manager",
44
"+components/session_manager/core",
55
"+components/sync_preferences/testing_pref_service_syncable.h",
6+
"+components/user_manager",
67
"+device/bluetooth",
78
"+mojo/public",
89
]

chromeos/services/bluetooth_config/adapter_state_controller.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ namespace chromeos {
1111
namespace bluetooth_config {
1212

1313
// Controls the state of the Bluetooth adapter and serves as the source of truth
14-
// for the adapter's current state.
14+
// for the adapter's current state. This class modifies the Bluetooth adapter
15+
// directly and should only be used by classes that do not wish to persist the
16+
// adapter state to prefs. For classes that do wish to persist the adapter state
17+
// to prefs, such as those processing incoming user requests,
18+
// BluetoothPowerController should be used instead.
1519
class AdapterStateController {
1620
public:
1721
class Observer : public base::CheckedObserver {
@@ -30,6 +34,9 @@ class AdapterStateController {
3034

3135
// Turns Bluetooth on or off. If Bluetooth is unavailable or already in the
3236
// desired state, this function is a no-op.
37+
// This does not save to |enabled| to prefs. If |enabled| is wished to be
38+
// saved to prefs, BluetoothPowerController::SetBluetoothEnabledState() should
39+
// be used instead.
3340
virtual void SetBluetoothEnabledState(bool enabled) = 0;
3441

3542
void AddObserver(Observer* observer);

chromeos/services/bluetooth_config/adapter_state_controller_impl.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ void AdapterStateControllerImpl::AttemptSetEnabled(bool enabled) {
103103
weak_ptr_factory_.GetWeakPtr(), enabled),
104104
base::BindOnce(&AdapterStateControllerImpl::OnSetPoweredError,
105105
weak_ptr_factory_.GetWeakPtr(), enabled));
106+
// TODO(gordonseto): Add power metric here.
106107

107108
// State has changed to kEnabling or kDisabling; notify observers.
108109
NotifyAdapterStateChanged();
@@ -118,6 +119,7 @@ void AdapterStateControllerImpl::OnSetPoweredSuccess(bool enabled) {
118119
void AdapterStateControllerImpl::OnSetPoweredError(bool enabled) {
119120
BLUETOOTH_LOG(ERROR) << "Error attempting to "
120121
<< (enabled ? "enable" : "disable") << " Bluetooth";
122+
// TODO(gordonseto): Add power metric here.
121123
in_progress_state_change_ = PowerStateChange::kNoChange;
122124

123125
// State is no longer kEnabling or kDisabling; notify observers.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2021 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef CHROMEOS_SERVICES_BLUETOOTH_CONFIG_BLUETOOTH_POWER_CONTROLLER_H_
6+
#define CHROMEOS_SERVICES_BLUETOOTH_CONFIG_BLUETOOTH_POWER_CONTROLLER_H_
7+
8+
class PrefService;
9+
10+
namespace chromeos {
11+
namespace bluetooth_config {
12+
13+
// Sets the Bluetooth power state and saves the state to prefs. Also initializes
14+
// the Bluetooth power state during system startup and user session startup.
15+
//
16+
// Classes that wish to set the Bluetooth adapter state and save that value to
17+
// prefs should use this class. Classes that do not want to persist the state to
18+
// prefs should use AdapterStateController instead.
19+
class BluetoothPowerController {
20+
public:
21+
virtual ~BluetoothPowerController() = default;
22+
23+
// Changes the Bluetooth power setting to |enabled|, persisting |enabled| to
24+
// user prefs if a user is logged in. If no user is logged in, the pref is
25+
// persisted to local state.
26+
virtual void SetBluetoothEnabledState(bool enabled) = 0;
27+
28+
// Sets the PrefServices used to save and retrieve the Bluetooth power state.
29+
virtual void SetPrefs(PrefService* primary_profile_prefs_,
30+
PrefService* local_state) = 0;
31+
};
32+
33+
} // namespace bluetooth_config
34+
} // namespace chromeos
35+
36+
#endif // CHROMEOS_SERVICES_BLUETOOTH_CONFIG_BLUETOOTH_POWER_CONTROLLER_H_
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// Copyright 2021 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "chromeos/services/bluetooth_config/bluetooth_power_controller_impl.h"
6+
7+
#include "ash/constants/ash_pref_names.h"
8+
#include "chromeos/services/bluetooth_config/public/cpp/cros_bluetooth_config_util.h"
9+
#include "components/device_event_log/device_event_log.h"
10+
#include "components/prefs/pref_registry_simple.h"
11+
#include "components/prefs/pref_service.h"
12+
#include "components/user_manager/user_manager.h"
13+
14+
namespace chromeos {
15+
namespace bluetooth_config {
16+
namespace {
17+
18+
// Decides whether to apply Bluetooth setting based on user type.
19+
// Returns true if the user type represents a human individual, currently this
20+
// includes: regular, child, supervised, or active directory. The other types
21+
// do not represent human account so those account should follow system-wide
22+
// Bluetooth setting instead.
23+
bool ShouldApplyUserBluetoothSetting(user_manager::UserType user_type) {
24+
return user_type == user_manager::USER_TYPE_REGULAR ||
25+
user_type == user_manager::USER_TYPE_CHILD ||
26+
user_type == user_manager::USER_TYPE_ACTIVE_DIRECTORY;
27+
}
28+
29+
} // namespace
30+
31+
// static
32+
void BluetoothPowerControllerImpl::RegisterLocalStatePrefs(
33+
PrefRegistrySimple* registry) {
34+
registry->RegisterBooleanPref(prefs::kSystemBluetoothAdapterEnabled,
35+
/*default_value=*/false);
36+
}
37+
38+
// static
39+
void BluetoothPowerControllerImpl::RegisterProfilePrefs(
40+
PrefRegistrySimple* registry) {
41+
registry->RegisterBooleanPref(prefs::kUserBluetoothAdapterEnabled,
42+
/*default_value=*/false);
43+
}
44+
45+
BluetoothPowerControllerImpl::BluetoothPowerControllerImpl(
46+
AdapterStateController* adapter_state_controller)
47+
: adapter_state_controller_(adapter_state_controller) {}
48+
49+
BluetoothPowerControllerImpl::~BluetoothPowerControllerImpl() = default;
50+
51+
void BluetoothPowerControllerImpl::SetBluetoothEnabledState(bool enabled) {
52+
if (primary_profile_prefs_) {
53+
BLUETOOTH_LOG(EVENT) << "Saving Bluetooth power state of " << enabled
54+
<< " to user prefs.";
55+
56+
primary_profile_prefs_->SetBoolean(ash::prefs::kUserBluetoothAdapterEnabled,
57+
enabled);
58+
} else if (local_state_) {
59+
BLUETOOTH_LOG(EVENT) << "Saving Bluetooth power state of " << enabled
60+
<< " to local state.";
61+
62+
local_state_->SetBoolean(ash::prefs::kSystemBluetoothAdapterEnabled,
63+
enabled);
64+
} else {
65+
BLUETOOTH_LOG(ERROR)
66+
<< "SetBluetoothEnabledState() called before preferences were set";
67+
}
68+
SetAdapterState(enabled);
69+
}
70+
71+
void BluetoothPowerControllerImpl::SetPrefs(PrefService* primary_profile_prefs,
72+
PrefService* local_state) {
73+
InitLocalStatePrefService(local_state);
74+
InitPrimaryUserPrefService(primary_profile_prefs);
75+
}
76+
77+
void BluetoothPowerControllerImpl::InitLocalStatePrefService(
78+
PrefService* local_state) {
79+
// Return early if |local_state_| has already been initialized or
80+
// |local_state| is invalid.
81+
if (local_state_ || !local_state)
82+
return;
83+
84+
local_state_ = local_state;
85+
86+
// Apply the local state pref if no user has logged in (still in login
87+
// screen).
88+
if (!user_manager::UserManager::Get()->GetActiveUser())
89+
ApplyBluetoothLocalStatePref();
90+
}
91+
92+
void BluetoothPowerControllerImpl::ApplyBluetoothLocalStatePref() {
93+
if (local_state_->FindPreference(prefs::kSystemBluetoothAdapterEnabled)
94+
->IsDefaultValue()) {
95+
// If the device has not had the local state Bluetooth pref, set the pref
96+
// according to whatever the current Bluetooth power is.
97+
BLUETOOTH_LOG(EVENT) << "Saving current power state of "
98+
<< adapter_state_controller_->GetAdapterState()
99+
<< " to local state.";
100+
SaveCurrentPowerStateToPrefs(local_state_,
101+
prefs::kSystemBluetoothAdapterEnabled);
102+
return;
103+
}
104+
105+
bool enabled =
106+
local_state_->GetBoolean(prefs::kSystemBluetoothAdapterEnabled);
107+
BLUETOOTH_LOG(EVENT) << "Applying local state pref Bluetooth power: "
108+
<< enabled;
109+
SetAdapterState(enabled);
110+
}
111+
112+
void BluetoothPowerControllerImpl::InitPrimaryUserPrefService(
113+
PrefService* primary_profile_prefs) {
114+
primary_profile_prefs_ = primary_profile_prefs;
115+
if (!primary_profile_prefs_) {
116+
return;
117+
}
118+
119+
DCHECK_EQ(user_manager::UserManager::Get()->GetActiveUser(),
120+
user_manager::UserManager::Get()->GetPrimaryUser());
121+
122+
if (!has_attempted_apply_primary_user_pref_) {
123+
ApplyBluetoothPrimaryUserPref();
124+
has_attempted_apply_primary_user_pref_ = true;
125+
}
126+
}
127+
128+
void BluetoothPowerControllerImpl::ApplyBluetoothPrimaryUserPref() {
129+
absl::optional<user_manager::UserType> user_type =
130+
user_manager::UserManager::Get()->GetActiveUser()->GetType();
131+
132+
// Apply the Bluetooth pref only for regular users (i.e. users representing
133+
// a human individual). We don't want to apply Bluetooth pref for other users
134+
// e.g. kiosk, guest etc. For non-human users, Bluetooth power should be left
135+
// to the current power state.
136+
if (!user_type || !ShouldApplyUserBluetoothSetting(*user_type)) {
137+
BLUETOOTH_LOG(EVENT) << "Not applying primary user pref because user has "
138+
"no type or is not a regular user.";
139+
return;
140+
}
141+
142+
if (!primary_profile_prefs_
143+
->FindPreference(prefs::kUserBluetoothAdapterEnabled)
144+
->IsDefaultValue()) {
145+
bool enabled =
146+
primary_profile_prefs_->GetBoolean(prefs::kUserBluetoothAdapterEnabled);
147+
BLUETOOTH_LOG(EVENT) << "Applying primary user pref Bluetooth power: "
148+
<< enabled;
149+
SetAdapterState(enabled);
150+
return;
151+
}
152+
153+
// If the user has not had the Bluetooth pref yet, set the user pref
154+
// according to whatever the current Bluetooth power is, except for
155+
// new users (first login on the device) always set the new pref to true.
156+
if (user_manager::UserManager::Get()->IsCurrentUserNew()) {
157+
BLUETOOTH_LOG(EVENT) << "Setting Bluetooth power to enabled for new user.";
158+
SetBluetoothEnabledState(true);
159+
return;
160+
}
161+
162+
BLUETOOTH_LOG(EVENT) << "Saving current power state of "
163+
<< adapter_state_controller_->GetAdapterState()
164+
<< " to user prefs.";
165+
SaveCurrentPowerStateToPrefs(primary_profile_prefs_,
166+
prefs::kUserBluetoothAdapterEnabled);
167+
}
168+
169+
void BluetoothPowerControllerImpl::SetAdapterState(bool enabled) {
170+
BLUETOOTH_LOG(EVENT) << "Setting adapter state to "
171+
<< (enabled ? "enabled " : "disabled");
172+
adapter_state_controller_->SetBluetoothEnabledState(enabled);
173+
}
174+
175+
void BluetoothPowerControllerImpl::SaveCurrentPowerStateToPrefs(
176+
PrefService* prefs,
177+
const char* pref_name) {
178+
prefs->SetBoolean(pref_name,
179+
IsBluetoothEnabledOrEnabling(
180+
adapter_state_controller_->GetAdapterState()));
181+
}
182+
183+
} // namespace bluetooth_config
184+
} // namespace chromeos
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2021 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef CHROMEOS_SERVICES_BLUETOOTH_CONFIG_BLUETOOTH_POWER_CONTROLLER_IMPL_H_
6+
#define CHROMEOS_SERVICES_BLUETOOTH_CONFIG_BLUETOOTH_POWER_CONTROLLER_IMPL_H_
7+
8+
#include "chromeos/services/bluetooth_config/bluetooth_power_controller.h"
9+
10+
#include "chromeos/services/bluetooth_config/adapter_state_controller.h"
11+
#include "components/user_manager/user_type.h"
12+
13+
class PrefRegistrySimple;
14+
15+
namespace chromeos {
16+
namespace bluetooth_config {
17+
18+
// Concrete BluetoothPowerController implementation that uses prefs to save and
19+
// apply the Bluetooth power state.
20+
class BluetoothPowerControllerImpl : public BluetoothPowerController {
21+
public:
22+
static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
23+
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
24+
25+
explicit BluetoothPowerControllerImpl(
26+
AdapterStateController* adapter_state_controller);
27+
~BluetoothPowerControllerImpl() override;
28+
29+
private:
30+
// BluetoothPowerController:
31+
void SetBluetoothEnabledState(bool enabled) override;
32+
void SetPrefs(PrefService* primary_profile_prefs,
33+
PrefService* local_state) override;
34+
35+
void InitLocalStatePrefService(PrefService* local_state);
36+
37+
// At login screen startup, applies the local state Bluetooth power setting
38+
// or sets the default pref value if the device doesn't have the setting yet.
39+
void ApplyBluetoothLocalStatePref();
40+
41+
void InitPrimaryUserPrefService(PrefService* primary_profile_prefs);
42+
43+
// At primary user session startup, applies the user's Bluetooth power setting
44+
// or sets the default pref value if the user doesn't have the setting yet.
45+
void ApplyBluetoothPrimaryUserPref();
46+
47+
// Sets the Bluetooth power state.
48+
void SetAdapterState(bool enabled);
49+
50+
// Saves to prefs the current Bluetooth power state.
51+
void SaveCurrentPowerStateToPrefs(PrefService* prefs, const char* pref_name);
52+
53+
// Remembers whether we have ever attempted to apply the primary user's
54+
// Bluetooth setting. If this variable is true, we will ignore any active
55+
// user change event since we know that the primary user's Bluetooth setting
56+
// has been attempted to be applied.
57+
bool has_attempted_apply_primary_user_pref_ = false;
58+
59+
PrefService* primary_profile_prefs_ = nullptr;
60+
PrefService* local_state_ = nullptr;
61+
62+
AdapterStateController* adapter_state_controller_;
63+
};
64+
65+
} // namespace bluetooth_config
66+
} // namespace chromeos
67+
68+
#endif // CHROMEOS_SERVICES_BLUETOOTH_CONFIG_BLUETOOTH_POWER_CONTROLLER_IMPL_H_

0 commit comments

Comments
 (0)