// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chromeos/dbus/dbus_thread_manager.h" #include "base/command_line.h" #include "base/sys_info.h" #include "base/threading/thread.h" #include "chromeos/chromeos_switches.h" #include "chromeos/dbus/bluetooth_adapter_client.h" #include "chromeos/dbus/bluetooth_agent_manager_client.h" #include "chromeos/dbus/bluetooth_device_client.h" #include "chromeos/dbus/bluetooth_gatt_characteristic_client.h" #include "chromeos/dbus/bluetooth_gatt_descriptor_client.h" #include "chromeos/dbus/bluetooth_gatt_manager_client.h" #include "chromeos/dbus/bluetooth_gatt_service_client.h" #include "chromeos/dbus/bluetooth_input_client.h" #include "chromeos/dbus/bluetooth_profile_manager_client.h" #include "chromeos/dbus/cras_audio_client.h" #include "chromeos/dbus/cros_disks_client.h" #include "chromeos/dbus/cryptohome_client.h" #include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/dbus_client_bundle.h" #include "chromeos/dbus/debug_daemon_client.h" #include "chromeos/dbus/easy_unlock_client.h" #include "chromeos/dbus/gsm_sms_client.h" #include "chromeos/dbus/image_burner_client.h" #include "chromeos/dbus/introspectable_client.h" #include "chromeos/dbus/lorgnette_manager_client.h" #include "chromeos/dbus/modem_messaging_client.h" #include "chromeos/dbus/nfc_adapter_client.h" #include "chromeos/dbus/nfc_device_client.h" #include "chromeos/dbus/nfc_manager_client.h" #include "chromeos/dbus/nfc_record_client.h" #include "chromeos/dbus/nfc_tag_client.h" #include "chromeos/dbus/permission_broker_client.h" #include "chromeos/dbus/power_manager_client.h" #include "chromeos/dbus/power_policy_controller.h" #include "chromeos/dbus/session_manager_client.h" #include "chromeos/dbus/shill_device_client.h" #include "chromeos/dbus/shill_ipconfig_client.h" #include "chromeos/dbus/shill_manager_client.h" #include "chromeos/dbus/shill_profile_client.h" #include "chromeos/dbus/shill_service_client.h" #include "chromeos/dbus/sms_client.h" #include "chromeos/dbus/system_clock_client.h" #include "chromeos/dbus/update_engine_client.h" #include "dbus/bus.h" #include "dbus/dbus_statistics.h" namespace chromeos { static DBusThreadManager* g_dbus_thread_manager = NULL; static bool g_using_dbus_thread_manager_for_testing = false; DBusThreadManager::DBusThreadManager(scoped_ptr<DBusClientBundle> client_bundle) : client_bundle_(client_bundle.Pass()) { dbus::statistics::Initialize(); if (client_bundle_->IsUsingAnyRealClient()) { // At least one real DBusClient is used. // Create the D-Bus thread. base::Thread::Options thread_options; thread_options.message_loop_type = base::MessageLoop::TYPE_IO; dbus_thread_.reset(new base::Thread("D-Bus thread")); dbus_thread_->StartWithOptions(thread_options); // Create the connection to the system bus. dbus::Bus::Options system_bus_options; system_bus_options.bus_type = dbus::Bus::SYSTEM; system_bus_options.connection_type = dbus::Bus::PRIVATE; system_bus_options.dbus_task_runner = dbus_thread_->message_loop_proxy(); system_bus_ = new dbus::Bus(system_bus_options); } // TODO(crbug.com/345586): Move PowerPolicyController out of // DBusThreadManager. power_policy_controller_.reset(new PowerPolicyController); } DBusThreadManager::~DBusThreadManager() { // PowerPolicyController's destructor depends on PowerManagerClient. power_policy_controller_.reset(); // Delete all D-Bus clients before shutting down the system bus. client_bundle_.reset(); // Shut down the bus. During the browser shutdown, it's ok to shut down // the bus synchronously. if (system_bus_.get()) system_bus_->ShutdownOnDBusThreadAndBlock(); // Stop the D-Bus thread. if (dbus_thread_) dbus_thread_->Stop(); dbus::statistics::Shutdown(); if (!g_dbus_thread_manager) return; // Called form Shutdown() or local test instance. // There should never be both a global instance and a local instance. CHECK(this == g_dbus_thread_manager); if (g_using_dbus_thread_manager_for_testing) { g_dbus_thread_manager = NULL; g_using_dbus_thread_manager_for_testing = false; VLOG(1) << "DBusThreadManager destroyed"; } else { LOG(FATAL) << "~DBusThreadManager() called outside of Shutdown()"; } } dbus::Bus* DBusThreadManager::GetSystemBus() { return system_bus_.get(); } BluetoothAdapterClient* DBusThreadManager::GetBluetoothAdapterClient() { return client_bundle_->bluetooth_adapter_client(); } BluetoothAgentManagerClient* DBusThreadManager::GetBluetoothAgentManagerClient() { return client_bundle_->bluetooth_agent_manager_client(); } BluetoothDeviceClient* DBusThreadManager::GetBluetoothDeviceClient() { return client_bundle_->bluetooth_device_client(); } BluetoothGattCharacteristicClient* DBusThreadManager::GetBluetoothGattCharacteristicClient() { return client_bundle_->bluetooth_gatt_characteristic_client(); } BluetoothGattDescriptorClient* DBusThreadManager::GetBluetoothGattDescriptorClient() { return client_bundle_->bluetooth_gatt_descriptor_client(); } BluetoothGattManagerClient* DBusThreadManager::GetBluetoothGattManagerClient() { return client_bundle_->bluetooth_gatt_manager_client(); } BluetoothGattServiceClient* DBusThreadManager::GetBluetoothGattServiceClient() { return client_bundle_->bluetooth_gatt_service_client(); } BluetoothInputClient* DBusThreadManager::GetBluetoothInputClient() { return client_bundle_->bluetooth_input_client(); } BluetoothProfileManagerClient* DBusThreadManager::GetBluetoothProfileManagerClient() { return client_bundle_->bluetooth_profile_manager_client(); } CrasAudioClient* DBusThreadManager::GetCrasAudioClient() { return client_bundle_->cras_audio_client(); } CrosDisksClient* DBusThreadManager::GetCrosDisksClient() { return client_bundle_->cros_disks_client(); } CryptohomeClient* DBusThreadManager::GetCryptohomeClient() { return client_bundle_->cryptohome_client(); } DebugDaemonClient* DBusThreadManager::GetDebugDaemonClient() { return client_bundle_->debug_daemon_client(); } EasyUnlockClient* DBusThreadManager::GetEasyUnlockClient() { return client_bundle_->easy_unlock_client(); } LorgnetteManagerClient* DBusThreadManager::GetLorgnetteManagerClient() { return client_bundle_->lorgnette_manager_client(); } ShillDeviceClient* DBusThreadManager::GetShillDeviceClient() { return client_bundle_->shill_device_client(); } ShillIPConfigClient* DBusThreadManager::GetShillIPConfigClient() { return client_bundle_->shill_ipconfig_client(); } ShillManagerClient* DBusThreadManager::GetShillManagerClient() { return client_bundle_->shill_manager_client(); } ShillServiceClient* DBusThreadManager::GetShillServiceClient() { return client_bundle_->shill_service_client(); } ShillProfileClient* DBusThreadManager::GetShillProfileClient() { return client_bundle_->shill_profile_client(); } GsmSMSClient* DBusThreadManager::GetGsmSMSClient() { return client_bundle_->gsm_sms_client(); } ImageBurnerClient* DBusThreadManager::GetImageBurnerClient() { return client_bundle_->image_burner_client(); } IntrospectableClient* DBusThreadManager::GetIntrospectableClient() { return client_bundle_->introspectable_client(); } ModemMessagingClient* DBusThreadManager::GetModemMessagingClient() { return client_bundle_->modem_messaging_client(); } NfcAdapterClient* DBusThreadManager::GetNfcAdapterClient() { return client_bundle_->nfc_adapter_client(); } NfcDeviceClient* DBusThreadManager::GetNfcDeviceClient() { return client_bundle_->nfc_device_client(); } NfcManagerClient* DBusThreadManager::GetNfcManagerClient() { return client_bundle_->nfc_manager_client(); } NfcRecordClient* DBusThreadManager::GetNfcRecordClient() { return client_bundle_->nfc_record_client(); } NfcTagClient* DBusThreadManager::GetNfcTagClient() { return client_bundle_->nfc_tag_client(); } PermissionBrokerClient* DBusThreadManager::GetPermissionBrokerClient() { return client_bundle_->permission_broker_client(); } PowerManagerClient* DBusThreadManager::GetPowerManagerClient() { return client_bundle_->power_manager_client(); } SessionManagerClient* DBusThreadManager::GetSessionManagerClient() { return client_bundle_->session_manager_client(); } SMSClient* DBusThreadManager::GetSMSClient() { return client_bundle_->sms_client(); } SystemClockClient* DBusThreadManager::GetSystemClockClient() { return client_bundle_->system_clock_client(); } UpdateEngineClient* DBusThreadManager::GetUpdateEngineClient() { return client_bundle_->update_engine_client(); } PowerPolicyController* DBusThreadManager::GetPowerPolicyController() { return power_policy_controller_.get(); } void DBusThreadManager::InitializeClients() { GetBluetoothAdapterClient()->Init(GetSystemBus()); GetBluetoothAgentManagerClient()->Init(GetSystemBus()); GetBluetoothDeviceClient()->Init(GetSystemBus()); GetBluetoothGattCharacteristicClient()->Init(GetSystemBus()); GetBluetoothGattDescriptorClient()->Init(GetSystemBus()); GetBluetoothGattManagerClient()->Init(GetSystemBus()); GetBluetoothGattServiceClient()->Init(GetSystemBus()); GetBluetoothInputClient()->Init(GetSystemBus()); GetBluetoothProfileManagerClient()->Init(GetSystemBus()); GetCrasAudioClient()->Init(GetSystemBus()); GetCrosDisksClient()->Init(GetSystemBus()); GetCryptohomeClient()->Init(GetSystemBus()); GetDebugDaemonClient()->Init(GetSystemBus()); GetEasyUnlockClient()->Init(GetSystemBus()); GetGsmSMSClient()->Init(GetSystemBus()); GetImageBurnerClient()->Init(GetSystemBus()); GetIntrospectableClient()->Init(GetSystemBus()); GetLorgnetteManagerClient()->Init(GetSystemBus()); GetModemMessagingClient()->Init(GetSystemBus()); GetPermissionBrokerClient()->Init(GetSystemBus()); GetPowerManagerClient()->Init(GetSystemBus()); GetSessionManagerClient()->Init(GetSystemBus()); GetShillDeviceClient()->Init(GetSystemBus()); GetShillIPConfigClient()->Init(GetSystemBus()); GetShillManagerClient()->Init(GetSystemBus()); GetShillServiceClient()->Init(GetSystemBus()); GetShillProfileClient()->Init(GetSystemBus()); GetSMSClient()->Init(GetSystemBus()); GetSystemClockClient()->Init(GetSystemBus()); GetUpdateEngineClient()->Init(GetSystemBus()); // Initialize the NFC clients in the correct order. The order of // initialization matters due to dependencies that exist between the // client objects. GetNfcManagerClient()->Init(GetSystemBus()); GetNfcAdapterClient()->Init(GetSystemBus()); GetNfcDeviceClient()->Init(GetSystemBus()); GetNfcTagClient()->Init(GetSystemBus()); GetNfcRecordClient()->Init(GetSystemBus()); // PowerPolicyController is dependent on PowerManagerClient, so // initialize it after the main list of clients. if (GetPowerPolicyController()) GetPowerPolicyController()->Init(this); // This must be called after the list of clients so they've each had a // chance to register with their object g_dbus_thread_managers. if (GetSystemBus()) GetSystemBus()->GetManagedObjects(); client_bundle_->SetupDefaultEnvironment(); } bool DBusThreadManager::IsUsingStub(DBusClientBundle::DBusClientType client) { return client_bundle_->IsUsingStub(client); } // static void DBusThreadManager::Initialize() { // If we initialize DBusThreadManager twice we may also be shutting it down // early; do not allow that. if (g_using_dbus_thread_manager_for_testing) return; CHECK(!g_dbus_thread_manager); bool use_dbus_stub = !base::SysInfo::IsRunningOnChromeOS() || CommandLine::ForCurrentProcess()->HasSwitch( chromeos::switches::kDbusStub); bool force_unstub_clients = CommandLine::ForCurrentProcess()->HasSwitch( chromeos::switches::kDbusUnstubClients); // Determine whether we use stub or real client implementations. if (force_unstub_clients) { InitializeWithPartialStub( CommandLine::ForCurrentProcess()->GetSwitchValueASCII( chromeos::switches::kDbusUnstubClients)); } else if (use_dbus_stub) { InitializeWithStubs(); } else { InitializeWithRealClients(); } } // static scoped_ptr<DBusThreadManagerSetter> DBusThreadManager::GetSetterForTesting() { if (!g_using_dbus_thread_manager_for_testing) { g_using_dbus_thread_manager_for_testing = true; InitializeWithStubs(); } return make_scoped_ptr(new DBusThreadManagerSetter()); } // static void DBusThreadManager::CreateGlobalInstance( DBusClientBundle::DBusClientTypeMask unstub_client_mask) { CHECK(!g_dbus_thread_manager); g_dbus_thread_manager = new DBusThreadManager( make_scoped_ptr(new DBusClientBundle(unstub_client_mask))); g_dbus_thread_manager->InitializeClients(); } // static void DBusThreadManager::InitializeWithRealClients() { CreateGlobalInstance(~static_cast<DBusClientBundle::DBusClientTypeMask>(0)); VLOG(1) << "DBusThreadManager initialized for Chrome OS"; } // static void DBusThreadManager::InitializeWithStubs() { CreateGlobalInstance(0 /* unstub_client_mask */); VLOG(1) << "DBusThreadManager created for testing"; } // static void DBusThreadManager::InitializeWithPartialStub( const std::string& unstub_clients) { DBusClientBundle::DBusClientTypeMask unstub_client_mask = DBusClientBundle::ParseUnstubList(unstub_clients); // We should have something parsed correctly here. LOG_IF(FATAL, unstub_client_mask == 0) << "Switch values for --" << chromeos::switches::kDbusUnstubClients << " cannot be parsed: " << unstub_clients; VLOG(1) << "DBusThreadManager initialized for mixed runtime environment"; CreateGlobalInstance(unstub_client_mask); } // static bool DBusThreadManager::IsInitialized() { return g_dbus_thread_manager != NULL; } // static void DBusThreadManager::Shutdown() { // Ensure that we only shutdown DBusThreadManager once. CHECK(g_dbus_thread_manager); DBusThreadManager* dbus_thread_manager = g_dbus_thread_manager; g_dbus_thread_manager = NULL; g_using_dbus_thread_manager_for_testing = false; delete dbus_thread_manager; VLOG(1) << "DBusThreadManager Shutdown completed"; } // static DBusThreadManager* DBusThreadManager::Get() { CHECK(g_dbus_thread_manager) << "DBusThreadManager::Get() called before Initialize()"; return g_dbus_thread_manager; } DBusThreadManagerSetter::DBusThreadManagerSetter() { } DBusThreadManagerSetter::~DBusThreadManagerSetter() { } void DBusThreadManagerSetter::SetBluetoothAdapterClient( scoped_ptr<BluetoothAdapterClient> client) { DBusThreadManager::Get()->client_bundle_->bluetooth_adapter_client_ = client.Pass(); } void DBusThreadManagerSetter::SetBluetoothAgentManagerClient( scoped_ptr<BluetoothAgentManagerClient> client) { DBusThreadManager::Get()->client_bundle_->bluetooth_agent_manager_client_ = client.Pass(); } void DBusThreadManagerSetter::SetBluetoothDeviceClient( scoped_ptr<BluetoothDeviceClient> client) { DBusThreadManager::Get()->client_bundle_->bluetooth_device_client_ = client.Pass(); } void DBusThreadManagerSetter::SetBluetoothGattCharacteristicClient( scoped_ptr<BluetoothGattCharacteristicClient> client) { DBusThreadManager::Get()->client_bundle_-> bluetooth_gatt_characteristic_client_ = client.Pass(); } void DBusThreadManagerSetter::SetBluetoothGattDescriptorClient( scoped_ptr<BluetoothGattDescriptorClient> client) { DBusThreadManager::Get()->client_bundle_->bluetooth_gatt_descriptor_client_ = client.Pass(); } void DBusThreadManagerSetter::SetBluetoothGattManagerClient( scoped_ptr<BluetoothGattManagerClient> client) { DBusThreadManager::Get()->client_bundle_->bluetooth_gatt_manager_client_ = client.Pass(); } void DBusThreadManagerSetter::SetBluetoothGattServiceClient( scoped_ptr<BluetoothGattServiceClient> client) { DBusThreadManager::Get()->client_bundle_->bluetooth_gatt_service_client_ = client.Pass(); } void DBusThreadManagerSetter::SetBluetoothInputClient( scoped_ptr<BluetoothInputClient> client) { DBusThreadManager::Get()->client_bundle_->bluetooth_input_client_ = client.Pass(); } void DBusThreadManagerSetter::SetBluetoothProfileManagerClient( scoped_ptr<BluetoothProfileManagerClient> client) { DBusThreadManager::Get()->client_bundle_->bluetooth_profile_manager_client_ = client.Pass(); } void DBusThreadManagerSetter::SetCrasAudioClient( scoped_ptr<CrasAudioClient> client) { DBusThreadManager::Get()->client_bundle_->cras_audio_client_ = client.Pass(); } void DBusThreadManagerSetter::SetCrosDisksClient( scoped_ptr<CrosDisksClient> client) { DBusThreadManager::Get()->client_bundle_->cros_disks_client_ = client.Pass(); } void DBusThreadManagerSetter::SetCryptohomeClient( scoped_ptr<CryptohomeClient> client) { DBusThreadManager::Get()->client_bundle_->cryptohome_client_ = client.Pass(); } void DBusThreadManagerSetter::SetDebugDaemonClient( scoped_ptr<DebugDaemonClient> client) { DBusThreadManager::Get()->client_bundle_->debug_daemon_client_ = client.Pass(); } void DBusThreadManagerSetter::SetEasyUnlockClient( scoped_ptr<EasyUnlockClient> client) { DBusThreadManager::Get()->client_bundle_->easy_unlock_client_ = client.Pass(); } void DBusThreadManagerSetter::SetLorgnetteManagerClient( scoped_ptr<LorgnetteManagerClient> client) { DBusThreadManager::Get()->client_bundle_->lorgnette_manager_client_ = client.Pass(); } void DBusThreadManagerSetter::SetShillDeviceClient( scoped_ptr<ShillDeviceClient> client) { DBusThreadManager::Get()->client_bundle_->shill_device_client_ = client.Pass(); } void DBusThreadManagerSetter::SetShillIPConfigClient( scoped_ptr<ShillIPConfigClient> client) { DBusThreadManager::Get()->client_bundle_->shill_ipconfig_client_ = client.Pass(); } void DBusThreadManagerSetter::SetShillManagerClient( scoped_ptr<ShillManagerClient> client) { DBusThreadManager::Get()->client_bundle_->shill_manager_client_ = client.Pass(); } void DBusThreadManagerSetter::SetShillServiceClient( scoped_ptr<ShillServiceClient> client) { DBusThreadManager::Get()->client_bundle_->shill_service_client_ = client.Pass(); } void DBusThreadManagerSetter::SetShillProfileClient( scoped_ptr<ShillProfileClient> client) { DBusThreadManager::Get()->client_bundle_->shill_profile_client_ = client.Pass(); } void DBusThreadManagerSetter::SetGsmSMSClient( scoped_ptr<GsmSMSClient> client) { DBusThreadManager::Get()->client_bundle_->gsm_sms_client_ = client.Pass(); } void DBusThreadManagerSetter::SetImageBurnerClient( scoped_ptr<ImageBurnerClient> client) { DBusThreadManager::Get()->client_bundle_->image_burner_client_ = client.Pass(); } void DBusThreadManagerSetter::SetIntrospectableClient( scoped_ptr<IntrospectableClient> client) { DBusThreadManager::Get()->client_bundle_->introspectable_client_ = client.Pass(); } void DBusThreadManagerSetter::SetModemMessagingClient( scoped_ptr<ModemMessagingClient> client) { DBusThreadManager::Get()->client_bundle_->modem_messaging_client_ = client.Pass(); } void DBusThreadManagerSetter::SetNfcAdapterClient( scoped_ptr<NfcAdapterClient> client) { DBusThreadManager::Get()->client_bundle_->nfc_adapter_client_ = client.Pass(); } void DBusThreadManagerSetter::SetNfcDeviceClient( scoped_ptr<NfcDeviceClient> client) { DBusThreadManager::Get()->client_bundle_->nfc_device_client_ = client.Pass(); } void DBusThreadManagerSetter::SetNfcManagerClient( scoped_ptr<NfcManagerClient> client) { DBusThreadManager::Get()->client_bundle_->nfc_manager_client_ = client.Pass(); } void DBusThreadManagerSetter::SetNfcRecordClient( scoped_ptr<NfcRecordClient> client) { DBusThreadManager::Get()->client_bundle_->nfc_record_client_ = client.Pass(); } void DBusThreadManagerSetter::SetNfcTagClient( scoped_ptr<NfcTagClient> client) { DBusThreadManager::Get()->client_bundle_->nfc_tag_client_ = client.Pass(); } void DBusThreadManagerSetter::SetPermissionBrokerClient( scoped_ptr<PermissionBrokerClient> client) { DBusThreadManager::Get()->client_bundle_->permission_broker_client_ = client.Pass(); } void DBusThreadManagerSetter::SetPowerManagerClient( scoped_ptr<PowerManagerClient> client) { DBusThreadManager::Get()->power_policy_controller_.reset(); DBusThreadManager::Get()->client_bundle_->power_manager_client_ = client.Pass(); DBusThreadManager::Get()->power_policy_controller_.reset( new PowerPolicyController); DBusThreadManager::Get()->power_policy_controller_->Init( DBusThreadManager::Get()); } void DBusThreadManagerSetter::SetSessionManagerClient( scoped_ptr<SessionManagerClient> client) { DBusThreadManager::Get()->client_bundle_->session_manager_client_ = client.Pass(); } void DBusThreadManagerSetter::SetSMSClient(scoped_ptr<SMSClient> client) { DBusThreadManager::Get()->client_bundle_->sms_client_ = client.Pass(); } void DBusThreadManagerSetter::SetSystemClockClient( scoped_ptr<SystemClockClient> client) { DBusThreadManager::Get()->client_bundle_->system_clock_client_ = client.Pass(); } void DBusThreadManagerSetter::SetUpdateEngineClient( scoped_ptr<UpdateEngineClient> client) { DBusThreadManager::Get()->client_bundle_->update_engine_client_ = client.Pass(); } } // namespace chromeos