| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/quick_pair/scanning/scanner_broker_impl.h" |
| |
| #include <memory> |
| |
| #include "ash/quick_pair/common/device.h" |
| #include "ash/quick_pair/common/protocol.h" |
| #include "ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner.h" |
| #include "ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_impl.h" |
| #include "ash/quick_pair/scanning/fast_pair/fast_pair_not_discoverable_scanner.h" |
| #include "ash/quick_pair/scanning/fast_pair/fast_pair_not_discoverable_scanner_impl.h" |
| #include "ash/session/session_controller_impl.h" |
| #include "ash/shell.h" |
| #include "base/check.h" |
| #include "base/functional/bind.h" |
| #include "base/functional/callback.h" |
| #include "chromeos/ash/services/quick_pair/quick_pair_process_manager.h" |
| #include "components/cross_device/logging/logging.h" |
| #include "device/bluetooth/bluetooth_adapter_factory.h" |
| |
| namespace { |
| |
| bool ShouldNotDiscoverableScanningBeEnabled(ash::LoginStatus status) { |
| switch (status) { |
| case ash::LoginStatus::NOT_LOGGED_IN: |
| case ash::LoginStatus::LOCKED: |
| case ash::LoginStatus::KIOSK_APP: |
| case ash::LoginStatus::GUEST: |
| case ash::LoginStatus::PUBLIC: |
| return false; |
| case ash::LoginStatus::USER: |
| case ash::LoginStatus::CHILD: |
| default: |
| return true; |
| } |
| } |
| |
| } // namespace |
| |
| namespace ash { |
| namespace quick_pair { |
| |
| ScannerBrokerImpl::ScannerBrokerImpl(QuickPairProcessManager* process_manager) |
| : process_manager_(process_manager) { |
| DCHECK(process_manager_); |
| device::BluetoothAdapterFactory::Get()->GetAdapter(base::BindOnce( |
| &ScannerBrokerImpl::OnGetAdapter, weak_pointer_factory_.GetWeakPtr())); |
| } |
| |
| ScannerBrokerImpl::~ScannerBrokerImpl() = default; |
| |
| void ScannerBrokerImpl::OnGetAdapter( |
| scoped_refptr<device::BluetoothAdapter> adapter) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| adapter_ = adapter; |
| |
| if (start_scanning_on_adapter_callbacks_.empty()) |
| return; |
| |
| CD_LOG(VERBOSE, Feature::FP) << __func__ << ": Running saved callbacks."; |
| |
| for (auto& callback : start_scanning_on_adapter_callbacks_) |
| std::move(callback).Run(); |
| |
| start_scanning_on_adapter_callbacks_.clear(); |
| } |
| |
| void ScannerBrokerImpl::AddObserver(Observer* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void ScannerBrokerImpl::RemoveObserver(Observer* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| void ScannerBrokerImpl::StartScanning(Protocol protocol) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| CD_LOG(VERBOSE, Feature::FP) << __func__ << ": protocol=" << protocol; |
| |
| if (!adapter_) { |
| CD_LOG(VERBOSE, Feature::FP) |
| << __func__ << ": No adapter yet, saving callback for later."; |
| |
| start_scanning_on_adapter_callbacks_.push_back( |
| base::BindOnce(&ScannerBrokerImpl::StartScanning, |
| weak_pointer_factory_.GetWeakPtr(), protocol)); |
| return; |
| } |
| |
| switch (protocol) { |
| case Protocol::kFastPairInitial: |
| case Protocol::kFastPairRetroactive: |
| case Protocol::kFastPairSubsequent: |
| StartFastPairScanning(); |
| break; |
| } |
| } |
| |
| void ScannerBrokerImpl::StopScanning(Protocol protocol) { |
| CD_LOG(VERBOSE, Feature::FP) << __func__ << ": protocol=" << protocol; |
| |
| switch (protocol) { |
| case Protocol::kFastPairInitial: |
| case Protocol::kFastPairRetroactive: |
| case Protocol::kFastPairSubsequent: |
| StopFastPairScanning(); |
| break; |
| } |
| } |
| |
| void ScannerBrokerImpl::StartFastPairScanning() { |
| DCHECK(!fast_pair_discoverable_scanner_); |
| DCHECK(!fast_pair_not_discoverable_scanner_); |
| DCHECK(adapter_); |
| |
| CD_LOG(VERBOSE, Feature::FP) << "Starting Fast Pair Scanning."; |
| |
| fast_pair_scanner_ = base::MakeRefCounted<FastPairScannerImpl>(); |
| |
| fast_pair_discoverable_scanner_ = |
| FastPairDiscoverableScannerImpl::Factory::Create( |
| fast_pair_scanner_, adapter_, |
| base::BindRepeating(&ScannerBrokerImpl::NotifyDeviceFound, |
| weak_pointer_factory_.GetWeakPtr()), |
| base::BindRepeating(&ScannerBrokerImpl::NotifyDeviceLost, |
| weak_pointer_factory_.GetWeakPtr())); |
| |
| // If there is no signed in user, don't instantiate the not discoverable |
| // scanner, but observe login events in case that we get logged in later on. |
| if (!ShouldNotDiscoverableScanningBeEnabled( |
| Shell::Get()->session_controller()->login_status())) { |
| CD_LOG(VERBOSE, Feature::FP) |
| << __func__ << ": No logged in user to enable not discoverable scanner"; |
| |
| // Observe log in events in the case the login was delayed if we aren't |
| // observing already. |
| if (!shell_observation_.IsObserving()) |
| shell_observation_.Observe(Shell::Get()->session_controller()); |
| |
| return; |
| } |
| |
| fast_pair_not_discoverable_scanner_ = |
| FastPairNotDiscoverableScannerImpl::Factory::Create( |
| fast_pair_scanner_, adapter_, |
| base::BindRepeating(&ScannerBrokerImpl::NotifyDeviceFound, |
| weak_pointer_factory_.GetWeakPtr()), |
| base::BindRepeating(&ScannerBrokerImpl::NotifyDeviceLost, |
| weak_pointer_factory_.GetWeakPtr())); |
| } |
| |
| void ScannerBrokerImpl::OnLoginStatusChanged(LoginStatus login_status) { |
| if (!ShouldNotDiscoverableScanningBeEnabled(login_status) || |
| !fast_pair_scanner_ || !adapter_ || |
| fast_pair_not_discoverable_scanner_.get()) { |
| return; |
| } |
| |
| CD_LOG(VERBOSE, Feature::FP) |
| << __func__ << ": Logged in user, instantiate not discoverable scanner"; |
| |
| fast_pair_not_discoverable_scanner_ = |
| FastPairNotDiscoverableScannerImpl::Factory::Create( |
| fast_pair_scanner_, adapter_, |
| base::BindRepeating(&ScannerBrokerImpl::NotifyDeviceFound, |
| weak_pointer_factory_.GetWeakPtr()), |
| base::BindRepeating(&ScannerBrokerImpl::NotifyDeviceLost, |
| weak_pointer_factory_.GetWeakPtr())); |
| } |
| |
| void ScannerBrokerImpl::StopFastPairScanning() { |
| fast_pair_discoverable_scanner_.reset(); |
| fast_pair_not_discoverable_scanner_.reset(); |
| fast_pair_scanner_.reset(); |
| shell_observation_.Reset(); |
| CD_LOG(VERBOSE, Feature::FP) << "Stopping Fast Pair Scanning."; |
| } |
| |
| void ScannerBrokerImpl::NotifyDeviceFound(scoped_refptr<Device> device) { |
| CD_LOG(INFO, Feature::FP) |
| << __func__ << ": device.metadata_id=" << device->metadata_id(); |
| |
| for (auto& observer : observers_) { |
| observer.OnDeviceFound(device); |
| } |
| } |
| |
| void ScannerBrokerImpl::NotifyDeviceLost(scoped_refptr<Device> device) { |
| CD_LOG(INFO, Feature::FP) |
| << __func__ << ": device.metadata_id=" << device->metadata_id(); |
| |
| for (auto& observer : observers_) { |
| observer.OnDeviceLost(device); |
| } |
| } |
| |
| void ScannerBrokerImpl::OnDevicePaired(scoped_refptr<Device> device) { |
| if (fast_pair_scanner_) |
| fast_pair_scanner_->OnDevicePaired(device); |
| } |
| |
| } // namespace quick_pair |
| } // namespace ash |