910e62b5创建于 1月15日历史提交
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "device/bluetooth/dbus/bluez_dbus_manager.h"

#include <memory>
#include <utility>

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/system/sys_info.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "chromeos/constants/chromeos_features.h"
#include "dbus/bus.h"
#include "dbus/dbus_statistics.h"
#include "dbus/message.h"
#include "dbus/object_manager.h"
#include "dbus/object_proxy.h"
#include "device/base/features.h"
#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
#include "device/bluetooth/dbus/bluetooth_admin_policy_client.h"
#include "device/bluetooth/dbus/bluetooth_advertisement_monitor_manager_client.h"
#include "device/bluetooth/dbus/bluetooth_agent_manager_client.h"
#include "device/bluetooth/dbus/bluetooth_battery_client.h"
#include "device/bluetooth/dbus/bluetooth_debug_manager_client.h"
#include "device/bluetooth/dbus/bluetooth_device_client.h"
#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h"
#include "device/bluetooth/dbus/bluetooth_gatt_descriptor_client.h"
#include "device/bluetooth/dbus/bluetooth_gatt_manager_client.h"
#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
#include "device/bluetooth/dbus/bluetooth_input_client.h"
#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h"
#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
#include "device/bluetooth/floss/floss_dbus_client.h"
#include "device/bluetooth/floss/floss_manager_client.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace bluez {

static BluezDBusManager* g_bluez_dbus_manager = nullptr;
static bool g_using_bluez_dbus_manager_for_testing = false;

BluezDBusManager::BluezDBusManager(dbus::Bus* bus, bool use_dbus_fakes)
    : bus_(bus),
      object_manager_support_known_(false),
      object_manager_supported_(false) {
  // On Chrome OS, Bluez might not be ready by the time we initialize the
  // BluezDBusManager so we initialize the clients anyway.
  bool should_check_object_manager = true;
#if BUILDFLAG(IS_CHROMEOS)
  should_check_object_manager = false;
#endif  // BUILDFLAG(IS_CHROMEOS)

  if (!use_dbus_fakes) {
    // Wait for the Floss Manager to be available
    GetSystemBus()
        ->GetObjectProxy(floss::kManagerService, dbus::ObjectPath("/"))
        ->WaitForServiceToBeAvailable(
            base::BindOnce(&BluezDBusManager::OnFlossManagerServiceAvailable,
                           weak_ptr_factory_.GetWeakPtr()));
  }

  if (!should_check_object_manager || use_dbus_fakes) {
    client_bundle_ =
        std::make_unique<BluetoothDBusClientBundle>(use_dbus_fakes);
    InitializeClients();
    object_manager_supported_ = true;
    object_manager_support_known_ = true;
    return;
  }

  CHECK(GetSystemBus()) << "Can't initialize real clients without DBus.";
  dbus::MethodCall method_call(dbus::kObjectManagerInterface,
                               dbus::kObjectManagerGetManagedObjects);
  GetSystemBus()
      ->GetObjectProxy(
          bluez_object_manager::kBluezObjectManagerServiceName,
          dbus::ObjectPath(
              bluetooth_object_manager::kBluetoothObjectManagerServicePath))
      ->CallMethodWithErrorResponse(
          &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
          base::BindOnce(&BluezDBusManager::OnObjectManagerResponse,
                         weak_ptr_factory_.GetWeakPtr()));
}

BluezDBusManager::~BluezDBusManager() {
  // Delete all D-Bus clients before shutting down the system bus.
  client_bundle_.reset();
}

dbus::Bus* bluez::BluezDBusManager::GetSystemBus() {
  return bus_;
}

void BluezDBusManager::CallWhenObjectManagerSupportIsKnown(
    base::OnceClosure callback) {
  object_manager_support_known_callback_ = std::move(callback);
}

BluetoothAdapterClient* bluez::BluezDBusManager::GetBluetoothAdapterClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_adapter_client();
}

BluetoothAdminPolicyClient*
bluez::BluezDBusManager::GetBluetoothAdminPolicyClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_admin_policy_client();
}

BluetoothAdvertisementMonitorManagerClient*
bluez::BluezDBusManager::GetBluetoothAdvertisementMonitorManagerClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_advertisement_monitor_manager_client();
}

BluetoothLEAdvertisingManagerClient*
bluez::BluezDBusManager::GetBluetoothLEAdvertisingManagerClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_le_advertising_manager_client();
}

BluetoothAgentManagerClient*
bluez::BluezDBusManager::GetBluetoothAgentManagerClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_agent_manager_client();
}

BluetoothDebugManagerClient*
bluez::BluezDBusManager::GetBluetoothDebugManagerClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_debug_manager_client();
}

BluetoothBatteryClient* bluez::BluezDBusManager::GetBluetoothBatteryClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_battery_client();
}

BluetoothDeviceClient* bluez::BluezDBusManager::GetBluetoothDeviceClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_device_client();
}

BluetoothGattCharacteristicClient*
bluez::BluezDBusManager::GetBluetoothGattCharacteristicClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_gatt_characteristic_client();
}

BluetoothGattDescriptorClient*
bluez::BluezDBusManager::GetBluetoothGattDescriptorClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_gatt_descriptor_client();
}

BluetoothGattManagerClient*
bluez::BluezDBusManager::GetBluetoothGattManagerClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_gatt_manager_client();
}

BluetoothGattServiceClient*
bluez::BluezDBusManager::GetBluetoothGattServiceClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_gatt_service_client();
}

BluetoothInputClient* bluez::BluezDBusManager::GetBluetoothInputClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_input_client();
}

BluetoothProfileManagerClient*
bluez::BluezDBusManager::GetBluetoothProfileManagerClient() {
  DCHECK(object_manager_support_known_);
  return client_bundle_->bluetooth_profile_manager_client();
}

void BluezDBusManager::OnObjectManagerResponse(
    dbus::Response* response,
    dbus::ErrorResponse* error_response) {
  if (response) {
    DVLOG(1) << "Bluetooth supported. Initializing clients.";
    object_manager_supported_ = true;

    client_bundle_ =
        std::make_unique<BluetoothDBusClientBundle>(false /* use_fakes */);
    InitializeClients();
  } else {
    DVLOG(1) << "Bluetooth not supported.";
    object_manager_supported_ = false;
    // We don't initialize clients since the clients need ObjectManager.
  }

  object_manager_support_known_ = true;
  if (object_manager_support_known_callback_) {
    std::move(object_manager_support_known_callback_).Run();
  }
}

void BluezDBusManager::OnFlossManagerServiceAvailable(bool is_available) {
  if (!is_available) {
    LOG(WARNING) << "Floss manager service not available, cannot set Floss "
                    "enable/disable.";
    return;
  }

  // Make sure that Floss manager daemon is in agreement with Chrome about the
  // state of Floss enable/disable.
  dbus::MethodCall floss_method_call(dbus::kObjectManagerInterface,
                                     dbus::kObjectManagerGetManagedObjects);
  GetSystemBus()
      ->GetObjectProxy(floss::kManagerService, dbus::ObjectPath("/"))
      ->CallMethodWithErrorResponse(
          &floss_method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
          base::BindOnce(&BluezDBusManager::OnFlossObjectManagerResponse,
                         weak_ptr_factory_.GetWeakPtr()));
}

void BluezDBusManager::OnFlossObjectManagerResponse(
    dbus::Response* response,
    dbus::ErrorResponse* error_response) {
  if (response) {
    DVLOG(1) << "Floss manager present. Making sure Floss is enabled/disabled.";
    floss_manager_client_ = floss::FlossManagerClient::Create();
    floss_manager_client_->Init(GetSystemBus(), floss::kManagerInterface,
                                /*adapter_index=*/0, base::Version(),
                                base::DoNothing());
  } else {
    LOG(WARNING)
        << "Floss manager not present, cannot set Floss enable/disable.";
  }
}

void BluezDBusManager::InitializeClients() {
  std::string bluetooth_service_name =
      bluez_object_manager::kBluezObjectManagerServiceName;
  client_bundle_->bluetooth_adapter_client()->Init(GetSystemBus(),
                                                   bluetooth_service_name);
  client_bundle_->bluetooth_admin_policy_client()->Init(GetSystemBus(),
                                                        bluetooth_service_name);
#if BUILDFLAG(IS_CHROMEOS)
  client_bundle_->bluetooth_advertisement_monitor_manager_client()->Init(
      GetSystemBus(), bluetooth_service_name);
#endif  // BUILDFLAG(IS_CHROMEOS)
  client_bundle_->bluetooth_agent_manager_client()->Init(
      GetSystemBus(), bluetooth_service_name);
  client_bundle_->bluetooth_device_client()->Init(GetSystemBus(),
                                                  bluetooth_service_name);
  client_bundle_->bluetooth_gatt_characteristic_client()->Init(
      GetSystemBus(), bluetooth_service_name);
  client_bundle_->bluetooth_gatt_descriptor_client()->Init(
      GetSystemBus(), bluetooth_service_name);
  client_bundle_->bluetooth_gatt_manager_client()->Init(GetSystemBus(),
                                                        bluetooth_service_name);
  client_bundle_->bluetooth_gatt_service_client()->Init(GetSystemBus(),
                                                        bluetooth_service_name);
  client_bundle_->bluetooth_input_client()->Init(GetSystemBus(),
                                                 bluetooth_service_name);
  client_bundle_->bluetooth_le_advertising_manager_client()->Init(
      GetSystemBus(), bluetooth_service_name);
  client_bundle_->bluetooth_profile_manager_client()->Init(
      GetSystemBus(), bluetooth_service_name);
  client_bundle_->bluetooth_debug_manager_client()->Init(
      GetSystemBus(), bluetooth_service_name);
  client_bundle_->bluetooth_battery_client()->Init(GetSystemBus(),
                                                   bluetooth_service_name);
}

// static
void BluezDBusManager::Initialize(dbus::Bus* system_bus) {
  // If we initialize BluezDBusManager twice we may also be shutting it down
  // early; do not allow that.
  if (g_using_bluez_dbus_manager_for_testing) {
    return;
  }

  CHECK(!g_bluez_dbus_manager);

  CHECK(system_bus);
  CreateGlobalInstance(system_bus, /*use_stubs=*/false);
}

void BluezDBusManager::InitializeFake() {
  if (g_using_bluez_dbus_manager_for_testing) {
    return;
  }
  CHECK(!g_bluez_dbus_manager);
  CreateGlobalInstance(nullptr, /*use_stubs=*/true);
}

// static
std::unique_ptr<BluezDBusManagerSetter>
bluez::BluezDBusManager::GetSetterForTesting() {
  if (!g_using_bluez_dbus_manager_for_testing) {
    g_using_bluez_dbus_manager_for_testing = true;
    CreateGlobalInstance(nullptr, /*use_stubs=*/true);
  }

  return base::WrapUnique(new BluezDBusManagerSetter());
}

// static
void BluezDBusManager::CreateGlobalInstance(dbus::Bus* bus, bool use_stubs) {
  CHECK(!g_bluez_dbus_manager);
  g_bluez_dbus_manager = new BluezDBusManager(bus, use_stubs);
}

// static
bool BluezDBusManager::IsInitialized() {
  return g_bluez_dbus_manager != nullptr;
}

// static
void BluezDBusManager::Shutdown() {
  // Ensure that we only shutdown BluezDBusManager once.
  CHECK(g_bluez_dbus_manager);
  BluezDBusManager* dbus_manager = g_bluez_dbus_manager;
  g_bluez_dbus_manager = nullptr;
  delete dbus_manager;

  g_using_bluez_dbus_manager_for_testing = false;
  DVLOG(1) << "BluezDBusManager Shutdown completed";
}

// static
BluezDBusManager* bluez::BluezDBusManager::Get() {
  CHECK(g_bluez_dbus_manager)
      << "bluez::BluezDBusManager::Get() called before Initialize()";
  return g_bluez_dbus_manager;
}

BluezDBusManagerSetter::BluezDBusManagerSetter() = default;

BluezDBusManagerSetter::~BluezDBusManagerSetter() = default;

void BluezDBusManagerSetter::SetBluetoothAdapterClient(
    std::unique_ptr<BluetoothAdapterClient> client) {
  bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_adapter_client_ =
      std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothAdminPolicyClient(
    std::unique_ptr<BluetoothAdminPolicyClient> client) {
  bluez::BluezDBusManager::Get()
      ->client_bundle_->bluetooth_admin_policy_client_ = std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothAdvertisementMonitorManagerClient(
    std::unique_ptr<BluetoothAdvertisementMonitorManagerClient> client) {
  bluez::BluezDBusManager::Get()
      ->client_bundle_->bluetooth_advertisement_monitor_manager_client_ =
      std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothLEAdvertisingManagerClient(
    std::unique_ptr<BluetoothLEAdvertisingManagerClient> client) {
  bluez::BluezDBusManager::Get()
      ->client_bundle_->bluetooth_le_advertising_manager_client_ =
      std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothAgentManagerClient(
    std::unique_ptr<BluetoothAgentManagerClient> client) {
  bluez::BluezDBusManager::Get()
      ->client_bundle_->bluetooth_agent_manager_client_ = std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothBatteryClient(
    std::unique_ptr<BluetoothBatteryClient> client) {
  bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_battery_client_ =
      std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothDebugManagerClient(
    std::unique_ptr<BluetoothDebugManagerClient> client) {
  bluez::BluezDBusManager::Get()
      ->client_bundle_->bluetooth_debug_manager_client_ = std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothDeviceClient(
    std::unique_ptr<BluetoothDeviceClient> client) {
  bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_device_client_ =
      std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothGattCharacteristicClient(
    std::unique_ptr<BluetoothGattCharacteristicClient> client) {
  bluez::BluezDBusManager::Get()
      ->client_bundle_->bluetooth_gatt_characteristic_client_ =
      std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothGattDescriptorClient(
    std::unique_ptr<BluetoothGattDescriptorClient> client) {
  bluez::BluezDBusManager::Get()
      ->client_bundle_->bluetooth_gatt_descriptor_client_ = std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothGattManagerClient(
    std::unique_ptr<BluetoothGattManagerClient> client) {
  bluez::BluezDBusManager::Get()
      ->client_bundle_->bluetooth_gatt_manager_client_ = std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothGattServiceClient(
    std::unique_ptr<BluetoothGattServiceClient> client) {
  bluez::BluezDBusManager::Get()
      ->client_bundle_->bluetooth_gatt_service_client_ = std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothInputClient(
    std::unique_ptr<BluetoothInputClient> client) {
  bluez::BluezDBusManager::Get()->client_bundle_->bluetooth_input_client_ =
      std::move(client);
}

void BluezDBusManagerSetter::SetBluetoothProfileManagerClient(
    std::unique_ptr<BluetoothProfileManagerClient> client) {
  bluez::BluezDBusManager::Get()
      ->client_bundle_->bluetooth_profile_manager_client_ = std::move(client);
}

}  // namespace bluez