1 // Copyright (c) 2012 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.
5 #include "chromeos/dbus/dbus_thread_manager.h"
7 #include "base/command_line.h"
8 #include "base/sys_info.h"
9 #include "base/threading/thread.h"
10 #include "chromeos/chromeos_switches.h"
11 #include "chromeos/dbus/bluetooth_adapter_client.h"
12 #include "chromeos/dbus/bluetooth_agent_manager_client.h"
13 #include "chromeos/dbus/bluetooth_device_client.h"
14 #include "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
15 #include "chromeos/dbus/bluetooth_gatt_descriptor_client.h"
16 #include "chromeos/dbus/bluetooth_gatt_manager_client.h"
17 #include "chromeos/dbus/bluetooth_gatt_service_client.h"
18 #include "chromeos/dbus/bluetooth_input_client.h"
19 #include "chromeos/dbus/bluetooth_profile_manager_client.h"
20 #include "chromeos/dbus/cras_audio_client.h"
21 #include "chromeos/dbus/cros_disks_client.h"
22 #include "chromeos/dbus/cryptohome_client.h"
23 #include "chromeos/dbus/dbus_client.h"
24 #include "chromeos/dbus/dbus_client_bundle.h"
25 #include "chromeos/dbus/debug_daemon_client.h"
26 #include "chromeos/dbus/easy_unlock_client.h"
27 #include "chromeos/dbus/fake_dbus_thread_manager.h"
28 #include "chromeos/dbus/gsm_sms_client.h"
29 #include "chromeos/dbus/image_burner_client.h"
30 #include "chromeos/dbus/introspectable_client.h"
31 #include "chromeos/dbus/lorgnette_manager_client.h"
32 #include "chromeos/dbus/modem_messaging_client.h"
33 #include "chromeos/dbus/nfc_adapter_client.h"
34 #include "chromeos/dbus/nfc_device_client.h"
35 #include "chromeos/dbus/nfc_manager_client.h"
36 #include "chromeos/dbus/nfc_record_client.h"
37 #include "chromeos/dbus/nfc_tag_client.h"
38 #include "chromeos/dbus/permission_broker_client.h"
39 #include "chromeos/dbus/power_manager_client.h"
40 #include "chromeos/dbus/power_policy_controller.h"
41 #include "chromeos/dbus/session_manager_client.h"
42 #include "chromeos/dbus/shill_device_client.h"
43 #include "chromeos/dbus/shill_ipconfig_client.h"
44 #include "chromeos/dbus/shill_manager_client.h"
45 #include "chromeos/dbus/shill_profile_client.h"
46 #include "chromeos/dbus/shill_service_client.h"
47 #include "chromeos/dbus/sms_client.h"
48 #include "chromeos/dbus/system_clock_client.h"
49 #include "chromeos/dbus/update_engine_client.h"
51 #include "dbus/dbus_statistics.h"
55 static DBusThreadManager* g_dbus_thread_manager = NULL;
56 static DBusThreadManager* g_dbus_thread_manager_for_testing = NULL;
58 DBusClientBundle::DBusClientTypeMask
59 DBusThreadManager::unstub_client_mask_ = DBusClientBundle::NO_CLIENTS;
61 // The DBusThreadManager implementation used in production.
62 class DBusThreadManagerImpl : public DBusThreadManager {
64 DBusThreadManagerImpl() {
65 // Create the D-Bus thread.
66 base::Thread::Options thread_options;
67 thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
68 dbus_thread_.reset(new base::Thread("D-Bus thread"));
69 dbus_thread_->StartWithOptions(thread_options);
71 // Create the connection to the system bus.
72 dbus::Bus::Options system_bus_options;
73 system_bus_options.bus_type = dbus::Bus::SYSTEM;
74 system_bus_options.connection_type = dbus::Bus::PRIVATE;
75 system_bus_options.dbus_task_runner = dbus_thread_->message_loop_proxy();
76 system_bus_ = new dbus::Bus(system_bus_options);
78 CreateDefaultClients();
81 virtual ~DBusThreadManagerImpl() {
82 // PowerPolicyController's destructor depends on PowerManagerClient.
83 power_policy_controller_.reset();
85 // Delete all D-Bus clients before shutting down the system bus.
86 client_bundle_.reset();
88 // Shut down the bus. During the browser shutdown, it's ok to shut down
89 // the bus synchronously.
90 system_bus_->ShutdownOnDBusThreadAndBlock();
92 // Stop the D-Bus thread.
96 void SetupDefaultEnvironment() {
97 return client_bundle_->SetupDefaultEnvironment();
100 virtual dbus::Bus* GetSystemBus() OVERRIDE {
101 return system_bus_.get();
104 virtual BluetoothAdapterClient* GetBluetoothAdapterClient() OVERRIDE {
105 return client_bundle_->bluetooth_adapter_client();
108 virtual BluetoothAgentManagerClient* GetBluetoothAgentManagerClient()
110 return client_bundle_->bluetooth_agent_manager_client();
113 virtual BluetoothDeviceClient* GetBluetoothDeviceClient() OVERRIDE {
114 return client_bundle_->bluetooth_device_client();
117 virtual BluetoothGattCharacteristicClient*
118 GetBluetoothGattCharacteristicClient() OVERRIDE {
119 return client_bundle_->bluetooth_gatt_characteristic_client();
122 virtual BluetoothGattDescriptorClient* GetBluetoothGattDescriptorClient()
124 return client_bundle_->bluetooth_gatt_descriptor_client();
127 virtual BluetoothGattManagerClient* GetBluetoothGattManagerClient() OVERRIDE {
128 return client_bundle_->bluetooth_gatt_manager_client();
131 virtual BluetoothGattServiceClient* GetBluetoothGattServiceClient() OVERRIDE {
132 return client_bundle_->bluetooth_gatt_service_client();
135 virtual BluetoothInputClient* GetBluetoothInputClient() OVERRIDE {
136 return client_bundle_->bluetooth_input_client();
139 virtual BluetoothProfileManagerClient* GetBluetoothProfileManagerClient()
141 return client_bundle_->bluetooth_profile_manager_client();
144 virtual CrasAudioClient* GetCrasAudioClient() OVERRIDE {
145 return client_bundle_->cras_audio_client();
148 virtual CrosDisksClient* GetCrosDisksClient() OVERRIDE {
149 return client_bundle_->cros_disks_client();
152 virtual CryptohomeClient* GetCryptohomeClient() OVERRIDE {
153 return client_bundle_->cryptohome_client();
156 virtual DebugDaemonClient* GetDebugDaemonClient() OVERRIDE {
157 return client_bundle_->debug_daemon_client();
160 virtual EasyUnlockClient* GetEasyUnlockClient() OVERRIDE {
161 return client_bundle_->easy_unlock_client();
163 virtual LorgnetteManagerClient* GetLorgnetteManagerClient() OVERRIDE {
164 return client_bundle_->lorgnette_manager_client();
167 virtual ShillDeviceClient* GetShillDeviceClient() OVERRIDE {
168 return client_bundle_->shill_device_client();
171 virtual ShillIPConfigClient* GetShillIPConfigClient() OVERRIDE {
172 return client_bundle_->shill_ipconfig_client();
175 virtual ShillManagerClient* GetShillManagerClient() OVERRIDE {
176 return client_bundle_->shill_manager_client();
179 virtual ShillServiceClient* GetShillServiceClient() OVERRIDE {
180 return client_bundle_->shill_service_client();
183 virtual ShillProfileClient* GetShillProfileClient() OVERRIDE {
184 return client_bundle_->shill_profile_client();
187 virtual GsmSMSClient* GetGsmSMSClient() OVERRIDE {
188 return client_bundle_->gsm_sms_client();
191 virtual ImageBurnerClient* GetImageBurnerClient() OVERRIDE {
192 return client_bundle_->image_burner_client();
195 virtual IntrospectableClient* GetIntrospectableClient() OVERRIDE {
196 return client_bundle_->introspectable_client();
199 virtual ModemMessagingClient* GetModemMessagingClient() OVERRIDE {
200 return client_bundle_->modem_messaging_client();
203 virtual NfcAdapterClient* GetNfcAdapterClient() OVERRIDE {
204 return client_bundle_->nfc_adapter_client();
207 virtual NfcDeviceClient* GetNfcDeviceClient() OVERRIDE {
208 return client_bundle_->nfc_device_client();
211 virtual NfcManagerClient* GetNfcManagerClient() OVERRIDE {
212 return client_bundle_->nfc_manager_client();
215 virtual NfcRecordClient* GetNfcRecordClient() OVERRIDE {
216 return client_bundle_->nfc_record_client();
219 virtual NfcTagClient* GetNfcTagClient() OVERRIDE {
220 return client_bundle_->nfc_tag_client();
223 virtual PermissionBrokerClient* GetPermissionBrokerClient() OVERRIDE {
224 return client_bundle_->permission_broker_client();
227 virtual PowerManagerClient* GetPowerManagerClient() OVERRIDE {
228 return client_bundle_->power_manager_client();
231 virtual SessionManagerClient* GetSessionManagerClient() OVERRIDE {
232 return client_bundle_->session_manager_client();
235 virtual SMSClient* GetSMSClient() OVERRIDE {
236 return client_bundle_->sms_client();
239 virtual SystemClockClient* GetSystemClockClient() OVERRIDE {
240 return client_bundle_->system_clock_client();
243 virtual UpdateEngineClient* GetUpdateEngineClient() OVERRIDE {
244 return client_bundle_->update_engine_client();
247 virtual PowerPolicyController* GetPowerPolicyController() OVERRIDE {
248 return power_policy_controller_.get();
252 // Constructs all clients and stores them in the respective *_client_ member
254 void CreateDefaultClients() {
255 client_bundle_.reset(new DBusClientBundle());
256 // TODO(crbug.com/345586): Move PowerPolicyController out of
257 // DBusThreadManagerImpl.
258 power_policy_controller_.reset(new PowerPolicyController);
261 scoped_ptr<base::Thread> dbus_thread_;
262 scoped_refptr<dbus::Bus> system_bus_;
263 scoped_ptr<DBusClientBundle> client_bundle_;
264 scoped_ptr<PowerPolicyController> power_policy_controller_;
266 DISALLOW_COPY_AND_ASSIGN(DBusThreadManagerImpl);
270 bool DBusThreadManager::IsUsingStub(DBusClientBundle::DBusClientType client) {
271 return !(unstub_client_mask_ & client);
275 void DBusThreadManager::Initialize() {
276 // If we initialize DBusThreadManager twice we may also be shutting it down
277 // early; do not allow that.
278 CHECK(g_dbus_thread_manager == NULL);
280 if (g_dbus_thread_manager_for_testing) {
281 g_dbus_thread_manager = g_dbus_thread_manager_for_testing;
283 VLOG(1) << "DBusThreadManager initialized with test implementation";
287 bool use_dbus_stub = !base::SysInfo::IsRunningOnChromeOS() ||
288 CommandLine::ForCurrentProcess()->HasSwitch(
289 chromeos::switches::kDbusStub);
290 bool force_unstub_clients = CommandLine::ForCurrentProcess()->HasSwitch(
291 chromeos::switches::kDbusUnstubClients);
292 // Determine whether we use stub or real client implementations.
293 if (force_unstub_clients) {
294 InitializeWithPartialStub(
295 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
296 chromeos::switches::kDbusUnstubClients));
297 } else if (use_dbus_stub) {
298 InitializeWithStub();
305 void DBusThreadManager::SetInstanceForTesting(
306 DBusThreadManager* dbus_thread_manager) {
307 CHECK(!g_dbus_thread_manager);
308 CHECK(!g_dbus_thread_manager_for_testing);
309 g_dbus_thread_manager_for_testing = dbus_thread_manager;
313 void DBusThreadManager::InitializeForTesting(
314 DBusThreadManager* dbus_thread_manager) {
315 unstub_client_mask_ = DBusClientBundle::NO_CLIENTS;
316 SetInstanceForTesting(dbus_thread_manager);
321 void DBusThreadManager::InitializeRegular() {
322 unstub_client_mask_ = DBusClientBundle::ALL_CLIENTS;
323 g_dbus_thread_manager = new DBusThreadManagerImpl();
325 VLOG(1) << "DBusThreadManager initialized for Chrome OS";
329 void DBusThreadManager::InitializeWithPartialStub(
330 const std::string& unstub_clients) {
331 // If we initialize DBusThreadManager twice we may also be shutting it down
332 // early; do not allow that.
333 CHECK(g_dbus_thread_manager == NULL);
335 unstub_client_mask_ = DBusClientBundle::ParseUnstubList(unstub_clients);
336 // We should have something parsed correctly here.
337 if (unstub_client_mask_ == 0) {
338 LOG(FATAL) << "Switch values for --"
339 << chromeos::switches::kDbusUnstubClients
340 << " cannot be parsed: "
343 DBusThreadManagerImpl* dbus_thread_manager = new DBusThreadManagerImpl();
344 VLOG(1) << "DBusThreadManager initialized for mixed runtime environment";
345 g_dbus_thread_manager = dbus_thread_manager;
347 dbus_thread_manager->SetupDefaultEnvironment();
351 void DBusThreadManager::InitializeWithStub() {
352 unstub_client_mask_ = DBusClientBundle::NO_CLIENTS;
353 // If we initialize DBusThreadManager twice we may also be shutting it down
354 // early; do not allow that.
355 CHECK(g_dbus_thread_manager == NULL);
356 FakeDBusThreadManager* fake_dbus_thread_manager = new FakeDBusThreadManager;
357 fake_dbus_thread_manager->SetFakeClients();
358 g_dbus_thread_manager = fake_dbus_thread_manager;
360 fake_dbus_thread_manager->SetupDefaultEnvironment();
361 VLOG(1) << "DBusThreadManager initialized with stub implementation";
365 bool DBusThreadManager::IsInitialized() {
366 return g_dbus_thread_manager != NULL;
370 void DBusThreadManager::Shutdown() {
371 // If we called InitializeForTesting, this may get called more than once.
372 // Ensure that we only shutdown DBusThreadManager once.
373 CHECK(g_dbus_thread_manager || g_dbus_thread_manager_for_testing);
374 DBusThreadManager* dbus_thread_manager = g_dbus_thread_manager;
375 g_dbus_thread_manager = NULL;
376 g_dbus_thread_manager_for_testing = NULL;
377 delete dbus_thread_manager;
378 VLOG(1) << "DBusThreadManager Shutdown completed";
381 DBusThreadManager::DBusThreadManager() {
382 dbus::statistics::Initialize();
385 DBusThreadManager::~DBusThreadManager() {
386 dbus::statistics::Shutdown();
387 if (g_dbus_thread_manager == NULL)
388 return; // Called form Shutdown() or local test instance.
389 // There should never be both a global instance and a local instance.
390 CHECK(this == g_dbus_thread_manager);
391 if (g_dbus_thread_manager_for_testing) {
392 g_dbus_thread_manager = NULL;
393 g_dbus_thread_manager_for_testing = NULL;
394 VLOG(1) << "DBusThreadManager destroyed";
396 LOG(FATAL) << "~DBusThreadManager() called outside of Shutdown()";
401 DBusThreadManager* DBusThreadManager::Get() {
402 CHECK(g_dbus_thread_manager)
403 << "DBusThreadManager::Get() called before Initialize()";
404 return g_dbus_thread_manager;
408 void DBusThreadManager::InitializeClients() {
409 InitClient(g_dbus_thread_manager->GetBluetoothAdapterClient());
410 InitClient(g_dbus_thread_manager->GetBluetoothAgentManagerClient());
411 InitClient(g_dbus_thread_manager->GetBluetoothDeviceClient());
412 InitClient(g_dbus_thread_manager->GetBluetoothGattCharacteristicClient());
413 InitClient(g_dbus_thread_manager->GetBluetoothGattDescriptorClient());
414 InitClient(g_dbus_thread_manager->GetBluetoothGattManagerClient());
415 InitClient(g_dbus_thread_manager->GetBluetoothGattServiceClient());
416 InitClient(g_dbus_thread_manager->GetBluetoothInputClient());
417 InitClient(g_dbus_thread_manager->GetBluetoothProfileManagerClient());
418 InitClient(g_dbus_thread_manager->GetCrasAudioClient());
419 InitClient(g_dbus_thread_manager->GetCrosDisksClient());
420 InitClient(g_dbus_thread_manager->GetCryptohomeClient());
421 InitClient(g_dbus_thread_manager->GetDebugDaemonClient());
422 InitClient(g_dbus_thread_manager->GetEasyUnlockClient());
423 InitClient(g_dbus_thread_manager->GetGsmSMSClient());
424 InitClient(g_dbus_thread_manager->GetImageBurnerClient());
425 InitClient(g_dbus_thread_manager->GetIntrospectableClient());
426 InitClient(g_dbus_thread_manager->GetLorgnetteManagerClient());
427 InitClient(g_dbus_thread_manager->GetModemMessagingClient());
428 InitClient(g_dbus_thread_manager->GetPermissionBrokerClient());
429 InitClient(g_dbus_thread_manager->GetPowerManagerClient());
430 InitClient(g_dbus_thread_manager->GetSessionManagerClient());
431 InitClient(g_dbus_thread_manager->GetShillDeviceClient());
432 InitClient(g_dbus_thread_manager->GetShillIPConfigClient());
433 InitClient(g_dbus_thread_manager->GetShillManagerClient());
434 InitClient(g_dbus_thread_manager->GetShillServiceClient());
435 InitClient(g_dbus_thread_manager->GetShillProfileClient());
436 InitClient(g_dbus_thread_manager->GetSMSClient());
437 InitClient(g_dbus_thread_manager->GetSystemClockClient());
438 InitClient(g_dbus_thread_manager->GetUpdateEngineClient());
440 // Initialize the NFC clients in the correct order. The order of
441 // initialization matters due to dependencies that exist between the
443 InitClient(g_dbus_thread_manager->GetNfcManagerClient());
444 InitClient(g_dbus_thread_manager->GetNfcAdapterClient());
445 InitClient(g_dbus_thread_manager->GetNfcDeviceClient());
446 InitClient(g_dbus_thread_manager->GetNfcTagClient());
447 InitClient(g_dbus_thread_manager->GetNfcRecordClient());
449 // PowerPolicyController is dependent on PowerManagerClient, so
450 // initialize it after the main list of clients.
451 if (g_dbus_thread_manager->GetPowerPolicyController()) {
452 g_dbus_thread_manager->GetPowerPolicyController()->Init(
453 g_dbus_thread_manager);
456 // This must be called after the list of clients so they've each had a
457 // chance to register with their object g_dbus_thread_managers.
458 if (g_dbus_thread_manager->GetSystemBus())
459 g_dbus_thread_manager->GetSystemBus()->GetManagedObjects();
463 void DBusThreadManager::InitClient(DBusClient* client) {
465 client->Init(g_dbus_thread_manager->GetSystemBus());
468 } // namespace chromeos