bluetooth_power_controller.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. // Copyright 2017 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. #include "ash/system/bluetooth/bluetooth_power_controller.h"
  5. #include <memory>
  6. #include "ash/constants/ash_pref_names.h"
  7. #include "ash/session/session_controller_impl.h"
  8. #include "ash/shell.h"
  9. #include "base/bind.h"
  10. #include "base/threading/thread_task_runner_handle.h"
  11. #include "components/device_event_log/device_event_log.h"
  12. #include "components/prefs/pref_registry_simple.h"
  13. #include "components/prefs/pref_service.h"
  14. #include "device/bluetooth/bluetooth_adapter_factory.h"
  15. #include "device/bluetooth/chromeos/bluetooth_utils.h"
  16. namespace ash {
  17. // The delay between bluez started and bluez power initialized. This number is
  18. // determined empirically: most of the time bluez takes less than 200 ms to
  19. // initialize power, so taking 1000 ms has enough time buffer for worst cases.
  20. const int kBluetoothInitializationDelay = 1000;
  21. BluetoothPowerController::BluetoothPowerController(PrefService* local_state)
  22. : local_state_(local_state) {
  23. device::BluetoothAdapterFactory::Get()->GetAdapter(
  24. base::BindOnce(&BluetoothPowerController::InitializeOnAdapterReady,
  25. weak_ptr_factory_.GetWeakPtr()));
  26. Shell::Get()->session_controller()->AddObserver(this);
  27. // AppLaunchTest.TestQuickLaunch fails under target=linux due to
  28. // |local_state_| being nullptr.
  29. if (local_state_) {
  30. StartWatchingLocalStatePrefsChanges();
  31. DCHECK(!Shell::Get()->session_controller()->IsActiveUserSessionStarted());
  32. // Apply the local state pref since no user has logged in (still in login
  33. // screen).
  34. ApplyBluetoothLocalStatePref();
  35. }
  36. }
  37. BluetoothPowerController::~BluetoothPowerController() {
  38. if (bluetooth_adapter_)
  39. bluetooth_adapter_->RemoveObserver(this);
  40. Shell::Get()->session_controller()->RemoveObserver(this);
  41. }
  42. void BluetoothPowerController::SetBluetoothEnabled(bool enabled) {
  43. if (active_user_pref_service_) {
  44. active_user_pref_service_->SetBoolean(prefs::kUserBluetoothAdapterEnabled,
  45. enabled);
  46. } else if (local_state_) {
  47. local_state_->SetBoolean(prefs::kSystemBluetoothAdapterEnabled, enabled);
  48. } else {
  49. DLOG(ERROR)
  50. << "active user and local state pref service cannot both be null";
  51. }
  52. }
  53. // static
  54. void BluetoothPowerController::RegisterLocalStatePrefs(
  55. PrefRegistrySimple* registry) {
  56. registry->RegisterBooleanPref(prefs::kSystemBluetoothAdapterEnabled, false);
  57. }
  58. // static
  59. void BluetoothPowerController::RegisterProfilePrefs(
  60. PrefRegistrySimple* registry) {
  61. registry->RegisterBooleanPref(prefs::kUserBluetoothAdapterEnabled, false);
  62. }
  63. void BluetoothPowerController::StartWatchingActiveUserPrefsChanges() {
  64. DCHECK(active_user_pref_service_);
  65. DCHECK(Shell::Get()->session_controller()->IsUserPrimary());
  66. active_user_pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
  67. active_user_pref_change_registrar_->Init(active_user_pref_service_);
  68. active_user_pref_change_registrar_->Add(
  69. prefs::kUserBluetoothAdapterEnabled,
  70. base::BindRepeating(
  71. &BluetoothPowerController::OnBluetoothPowerActiveUserPrefChanged,
  72. base::Unretained(this)));
  73. }
  74. void BluetoothPowerController::StartWatchingLocalStatePrefsChanges() {
  75. DCHECK(local_state_);
  76. local_state_pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
  77. local_state_pref_change_registrar_->Init(local_state_);
  78. local_state_pref_change_registrar_->Add(
  79. prefs::kSystemBluetoothAdapterEnabled,
  80. base::BindRepeating(
  81. &BluetoothPowerController::OnBluetoothPowerLocalStatePrefChanged,
  82. base::Unretained(this)));
  83. }
  84. void BluetoothPowerController::StopWatchingActiveUserPrefsChanges() {
  85. active_user_pref_change_registrar_.reset();
  86. }
  87. void BluetoothPowerController::OnBluetoothPowerActiveUserPrefChanged() {
  88. DCHECK(active_user_pref_service_);
  89. BLUETOOTH_LOG(EVENT) << "Active user bluetooth power pref changed";
  90. SetBluetoothPower(active_user_pref_service_->GetBoolean(
  91. prefs::kUserBluetoothAdapterEnabled));
  92. }
  93. void BluetoothPowerController::OnBluetoothPowerLocalStatePrefChanged() {
  94. DCHECK(local_state_);
  95. BLUETOOTH_LOG(EVENT) << "Local state bluetooth power pref changed";
  96. SetBluetoothPower(
  97. local_state_->GetBoolean(prefs::kSystemBluetoothAdapterEnabled));
  98. }
  99. void BluetoothPowerController::SetPrimaryUserBluetoothPowerSetting(
  100. bool enabled) {
  101. // This method should only be called when the primary user is the active user.
  102. CHECK(Shell::Get()->session_controller()->IsUserPrimary());
  103. active_user_pref_service_->SetBoolean(prefs::kUserBluetoothAdapterEnabled,
  104. enabled);
  105. }
  106. void BluetoothPowerController::InitializeOnAdapterReady(
  107. scoped_refptr<device::BluetoothAdapter> adapter) {
  108. bluetooth_adapter_ = std::move(adapter);
  109. bluetooth_adapter_->AddObserver(this);
  110. bool adapter_present = bluetooth_adapter_->IsPresent();
  111. BLUETOOTH_LOG(EVENT) << "Bluetooth adapter ready, IsPresent = "
  112. << adapter_present;
  113. if (adapter_present)
  114. TriggerRunPendingBluetoothTasks();
  115. }
  116. void BluetoothPowerController::OnActiveUserPrefServiceChanged(
  117. PrefService* pref_service) {
  118. active_user_pref_service_ = pref_service;
  119. // Only listen to primary user's pref changes since non-primary users
  120. // are not able to change bluetooth pref.
  121. if (!Shell::Get()->session_controller()->IsUserPrimary()) {
  122. StopWatchingActiveUserPrefsChanges();
  123. return;
  124. }
  125. StartWatchingActiveUserPrefsChanges();
  126. // Apply the bluetooth pref only for regular users (i.e. users representing
  127. // a human individual). We don't want to apply bluetooth pref for other users
  128. // e.g. kiosk, guest etc. For non-human users, bluetooth power should be left
  129. // to the current power state.
  130. if (!is_primary_user_bluetooth_applied_) {
  131. ApplyBluetoothPrimaryUserPref();
  132. is_primary_user_bluetooth_applied_ = true;
  133. }
  134. }
  135. void BluetoothPowerController::AdapterPresentChanged(
  136. device::BluetoothAdapter* adapter,
  137. bool present) {
  138. BLUETOOTH_LOG(EVENT) << "Bluetooth adapter present changed = " << present;
  139. if (present) {
  140. // If adapter->IsPresent() has just changed from false to true, this means
  141. // that bluez has just started but not yet finished power initialization,
  142. // so we should not start any bluetooth tasks until bluez power
  143. // initialization is done. Since there is no signal from bluez when that
  144. // happens, this adds a bit delay before triggering pending bluetooth tasks.
  145. //
  146. // TODO(sonnysasaka): Replace this delay hack with a signal from bluez when
  147. // it has "initialized" signal in the future (http://crbug.com/765390).
  148. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  149. FROM_HERE,
  150. base::BindOnce(
  151. &BluetoothPowerController::TriggerRunPendingBluetoothTasks,
  152. weak_ptr_factory_.GetWeakPtr()),
  153. base::Milliseconds(kBluetoothInitializationDelay));
  154. }
  155. }
  156. void BluetoothPowerController::ApplyBluetoothPrimaryUserPref() {
  157. absl::optional<user_manager::UserType> user_type =
  158. Shell::Get()->session_controller()->GetUserType();
  159. if (!user_type || !ShouldApplyUserBluetoothSetting(*user_type)) {
  160. // Do not apply bluetooth setting if user is not of the allowed types.
  161. return;
  162. }
  163. DCHECK(Shell::Get()->session_controller()->IsUserPrimary());
  164. PrefService* prefs = active_user_pref_service_;
  165. if (!prefs->FindPreference(prefs::kUserBluetoothAdapterEnabled)
  166. ->IsDefaultValue()) {
  167. bool enabled = prefs->GetBoolean(prefs::kUserBluetoothAdapterEnabled);
  168. BLUETOOTH_LOG(EVENT) << "Applying primary user pref bluetooth power: "
  169. << enabled;
  170. SetBluetoothPower(enabled);
  171. return;
  172. }
  173. // If the user has not had the bluetooth pref yet, set the user pref
  174. // according to whatever the current bluetooth power is, except for
  175. // new users (first login on the device) always set the new pref to true.
  176. if (Shell::Get()->session_controller()->IsUserFirstLogin()) {
  177. prefs->SetBoolean(prefs::kUserBluetoothAdapterEnabled, true);
  178. } else {
  179. SavePrefValue(prefs, prefs::kUserBluetoothAdapterEnabled);
  180. }
  181. }
  182. void BluetoothPowerController::ApplyBluetoothLocalStatePref() {
  183. if (local_state_->FindPreference(prefs::kSystemBluetoothAdapterEnabled)
  184. ->IsDefaultValue()) {
  185. // If the device has not had the local state bluetooth pref, set the pref
  186. // according to whatever the current bluetooth power is.
  187. SavePrefValue(local_state_, prefs::kSystemBluetoothAdapterEnabled);
  188. } else {
  189. bool enabled =
  190. local_state_->GetBoolean(prefs::kSystemBluetoothAdapterEnabled);
  191. BLUETOOTH_LOG(EVENT) << "Applying local state pref bluetooth power: "
  192. << enabled;
  193. SetBluetoothPower(enabled);
  194. }
  195. }
  196. void BluetoothPowerController::SetBluetoothPower(bool enabled) {
  197. if (pending_bluetooth_power_target_.has_value()) {
  198. // There is already a pending bluetooth power change request, so don't
  199. // enqueue a new SetPowered operation but rather change the target power.
  200. pending_bluetooth_power_target_ = enabled;
  201. return;
  202. }
  203. pending_bluetooth_power_target_ = enabled;
  204. RunBluetoothTaskWhenAdapterReady(
  205. base::BindOnce(&BluetoothPowerController::SetBluetoothPowerOnAdapterReady,
  206. weak_ptr_factory_.GetWeakPtr()));
  207. }
  208. void BluetoothPowerController::SetBluetoothPowerOnAdapterReady() {
  209. DCHECK(pending_bluetooth_power_target_.has_value());
  210. bool enabled = pending_bluetooth_power_target_.value();
  211. pending_bluetooth_power_target_.reset();
  212. device::PoweredStateOperation power_operation =
  213. enabled ? device::PoweredStateOperation::kEnable
  214. : device::PoweredStateOperation::kDisable;
  215. bluetooth_adapter_->SetPowered(
  216. enabled,
  217. base::BindOnce(&BluetoothPowerController::OnSetBluetoothPower,
  218. weak_ptr_factory_.GetWeakPtr(), power_operation,
  219. /*success=*/true),
  220. base::BindOnce(&BluetoothPowerController::OnSetBluetoothPower,
  221. weak_ptr_factory_.GetWeakPtr(), power_operation,
  222. /*success=*/false));
  223. device::RecordPoweredState(enabled);
  224. }
  225. void BluetoothPowerController::RunBluetoothTaskWhenAdapterReady(
  226. BluetoothTask task) {
  227. pending_bluetooth_tasks_.push(std::move(task));
  228. TriggerRunPendingBluetoothTasks();
  229. }
  230. void BluetoothPowerController::TriggerRunPendingBluetoothTasks() {
  231. if (pending_tasks_busy_)
  232. return;
  233. pending_tasks_busy_ = true;
  234. RunNextPendingBluetoothTask();
  235. }
  236. void BluetoothPowerController::RunNextPendingBluetoothTask() {
  237. if (!bluetooth_adapter_ || !bluetooth_adapter_->IsPresent() ||
  238. pending_bluetooth_tasks_.empty()) {
  239. // Stop running pending tasks if either adapter becomes not present or
  240. // all the pending tasks have been run.
  241. pending_tasks_busy_ = false;
  242. return;
  243. }
  244. BluetoothTask task = std::move(pending_bluetooth_tasks_.front());
  245. pending_bluetooth_tasks_.pop();
  246. std::move(task).Run();
  247. }
  248. void BluetoothPowerController::SavePrefValue(PrefService* prefs,
  249. const char* pref_name) {
  250. RunBluetoothTaskWhenAdapterReady(
  251. base::BindOnce(&BluetoothPowerController::SavePrefValueOnAdapterReady,
  252. weak_ptr_factory_.GetWeakPtr(), prefs, pref_name));
  253. }
  254. void BluetoothPowerController::SavePrefValueOnAdapterReady(
  255. PrefService* prefs,
  256. const char* pref_name) {
  257. prefs->SetBoolean(pref_name, bluetooth_adapter_->IsPowered());
  258. RunNextPendingBluetoothTask();
  259. }
  260. bool BluetoothPowerController::ShouldApplyUserBluetoothSetting(
  261. user_manager::UserType user_type) const {
  262. return user_type == user_manager::USER_TYPE_REGULAR ||
  263. user_type == user_manager::USER_TYPE_CHILD ||
  264. user_type == user_manager::USER_TYPE_ACTIVE_DIRECTORY;
  265. }
  266. void BluetoothPowerController::OnSetBluetoothPower(
  267. device::PoweredStateOperation power_operation,
  268. bool success) {
  269. device::RecordPoweredStateOperationResult(power_operation, success);
  270. // Always run the next pending task after SetPowered completes regardless
  271. // of whether there was an error.
  272. RunNextPendingBluetoothTask();
  273. }
  274. } // namespace ash