chromium/chromeos/ash/services/bluetooth_config/bluetooth_device_status_notifier_impl.h

// 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.

#ifndef CHROMEOS_ASH_SERVICES_BLUETOOTH_CONFIG_BLUETOOTH_DEVICE_STATUS_NOTIFIER_IMPL_H_
#define CHROMEOS_ASH_SERVICES_BLUETOOTH_CONFIG_BLUETOOTH_DEVICE_STATUS_NOTIFIER_IMPL_H_

#include <unordered_map>

#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chromeos/ash/services/bluetooth_config/bluetooth_device_status_notifier.h"
#include "chromeos/ash/services/bluetooth_config/device_cache.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "device/bluetooth/bluetooth_adapter.h"

namespace device {
class BluetoothDevice;
}  // namespace device

namespace ash::bluetooth_config {

// Concrete BluetoothDeviceStatusNotifier implementation. Uses DeviceCache to
// observe for device list changes in order to notify when a device is newly
// paired, connected or disconnected.
class BluetoothDeviceStatusNotifierImpl
    : public BluetoothDeviceStatusNotifier,
      public DeviceCache::Observer,
      public chromeos::PowerManagerClient::Observer {
 public:
  BluetoothDeviceStatusNotifierImpl(
      scoped_refptr<device::BluetoothAdapter> bluetooth_adapter,
      DeviceCache* device_cache,
      chromeos::PowerManagerClient* power_manager_client);
  ~BluetoothDeviceStatusNotifierImpl() override;

 private:
  friend class BluetoothDeviceStatusNotifierImplTest;

  // Time period after the Chromebook has awoken from being suspended where
  // observers are not notified of devices that have changed their connection
  // status from connected to disconnected.
  static const base::TimeDelta kSuspendCooldownTimeout;

  // DeviceCache::Observer:
  void OnPairedDevicesListChanged() override;

  // chromeos::PowerManagerClient::Observer:
  void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
  void SuspendDone(base::TimeDelta sleep_duration) override;

  // Checks the paired device list to find if a device has been newly paired.
  // Notifies observers on the device state change.
  void CheckForDeviceStateChange();

  void OnSuspendCooldownTimeout();

  // Checks if device with id |device_id| is connected using a nearby share
  // connection.
  bool IsNearbyConnectionsDevice(const device::BluetoothDevice& device_id);

  // Returns a |BluetoothDevice| corresponding to |device_id|.
  device::BluetoothDevice* FindDevice(const std::string& device_id);

  // Paired devices map, maps a device id with its corresponding device
  // properties.
  std::unordered_map<std::string, mojom::PairedBluetoothDevicePropertiesPtr>
      devices_id_to_properties_map_;

  // Flag indicating that the Chromebook is currently suspended or was suspended
  // less than |kSuspendCooldownTimeout| ago.
  bool did_recently_suspend_ = false;

  // Timer that starts once the Chromebook has awoken from being suspended that
  // expires after |kSuspendCooldownTimeout|.
  base::OneShotTimer suspend_cooldown_timer_;

  scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_;
  raw_ptr<DeviceCache> device_cache_;

  raw_ptr<chromeos::PowerManagerClient> power_manager_client_;

  base::ScopedObservation<DeviceCache, DeviceCache::Observer>
      device_cache_observation_{this};

  base::ScopedObservation<chromeos::PowerManagerClient,
                          chromeos::PowerManagerClient::Observer>
      power_manager_client_observation_{this};
};

}  // namespace ash::bluetooth_config

#endif  // CHROMEOS_ASH_SERVICES_BLUETOOTH_CONFIG_BLUETOOTH_DEVICE_STATUS_NOTIFIER_IMPL_H_