diff options
-rw-r--r-- | chromeos/chromeos.gyp | 2 | ||||
-rw-r--r-- | chromeos/chromeos_switches.cc | 3 | ||||
-rw-r--r-- | chromeos/chromeos_switches.h | 1 | ||||
-rw-r--r-- | chromeos/dbus/dbus_client_bundle.cc | 6 | ||||
-rw-r--r-- | chromeos/dbus/dbus_client_bundle.h | 5 | ||||
-rw-r--r-- | chromeos/dbus/dbus_thread_manager.cc | 11 | ||||
-rw-r--r-- | chromeos/dbus/dbus_thread_manager.h | 3 | ||||
-rw-r--r-- | chromeos/dbus/metronome_client.cc | 216 | ||||
-rw-r--r-- | chromeos/dbus/metronome_client.h | 49 |
9 files changed, 296 insertions, 0 deletions
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index 00a41dd..f7596b8 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp @@ -200,6 +200,8 @@ 'dbus/leadership_daemon_manager_client.h', 'dbus/lorgnette_manager_client.cc', 'dbus/lorgnette_manager_client.h', + 'dbus/metronome_client.cc', + 'dbus/metronome_client.h', 'dbus/modem_messaging_client.cc', 'dbus/modem_messaging_client.h', 'dbus/nfc_adapter_client.cc', diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc index b96d5d4..e8878ad 100644 --- a/chromeos/chromeos_switches.cc +++ b/chromeos/chromeos_switches.cc @@ -296,6 +296,9 @@ const char kForceFirstRunUI[] = "force-first-run-ui"; // Enables testing for auto update UI. const char kTestAutoUpdateUI[] = "test-auto-update-ui"; +// Enables testing Metronome client with a periodic timer. +const char kTestMetronomeTimer[] = "test-metronome-timer"; + // Disable memory pressure checks on ChromeOS. const char kDisableMemoryPressureSystemChromeOS[] = "disable-memory-pressure-chromeos"; diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h index 6a9f9bf..562317d 100644 --- a/chromeos/chromeos_switches.h +++ b/chromeos/chromeos_switches.h @@ -102,6 +102,7 @@ CHROMEOS_EXPORT extern const char kSmsTestMessages[]; CHROMEOS_EXPORT extern const char kStubCrosSettings[]; CHROMEOS_EXPORT extern const char kSystemDevMode[]; CHROMEOS_EXPORT extern const char kTestAutoUpdateUI[]; +CHROMEOS_EXPORT extern const char kTestMetronomeTimer[]; CHROMEOS_EXPORT extern const char kWakeOnPackets[]; CHROMEOS_EXPORT extern const char kEnableCaptivePortalBypassProxyOption[]; CHROMEOS_EXPORT extern const char kDisableTimeZoneTrackingOption[]; diff --git a/chromeos/dbus/dbus_client_bundle.cc b/chromeos/dbus/dbus_client_bundle.cc index 77a7010..d762b7e 100644 --- a/chromeos/dbus/dbus_client_bundle.cc +++ b/chromeos/dbus/dbus_client_bundle.cc @@ -67,6 +67,7 @@ #include "chromeos/dbus/introspectable_client.h" #include "chromeos/dbus/leadership_daemon_manager_client.h" #include "chromeos/dbus/lorgnette_manager_client.h" +#include "chromeos/dbus/metronome_client.h" #include "chromeos/dbus/modem_messaging_client.h" #include "chromeos/dbus/nfc_adapter_client.h" #include "chromeos/dbus/nfc_device_client.h" @@ -105,6 +106,7 @@ const struct { { "easy_unlock", DBusClientBundle::EASY_UNLOCK }, { "leadership_daemon", DBusClientBundle::LEADERSHIP_DAEMON }, { "lorgnette_manager", DBusClientBundle::LORGNETTE_MANAGER }, + { "metronome", DBusClientBundle::METRONOME }, { "shill", DBusClientBundle::SHILL }, { "gsm_sms", DBusClientBundle::GSM_SMS }, { "image_burner", DBusClientBundle::IMAGE_BURNER }, @@ -201,6 +203,10 @@ DBusClientBundle::DBusClientBundle(DBusClientTypeMask unstub_client_mask) else lorgnette_manager_client_.reset(new FakeLorgnetteManagerClient); + metronome_client_.reset(MetronomeClient::Create( + IsUsingStub(METRONOME) ? STUB_DBUS_CLIENT_IMPLEMENTATION + : REAL_DBUS_CLIENT_IMPLEMENTATION)); + if (!IsUsingStub(SHILL)) { shill_manager_client_.reset(ShillManagerClient::Create()); shill_device_client_.reset(ShillDeviceClient::Create()); diff --git a/chromeos/dbus/dbus_client_bundle.h b/chromeos/dbus/dbus_client_bundle.h index 7397ada..48d000c 100644 --- a/chromeos/dbus/dbus_client_bundle.h +++ b/chromeos/dbus/dbus_client_bundle.h @@ -30,6 +30,7 @@ class DebugDaemonClient; class EasyUnlockClient; class LeadershipDaemonManagerClient; class LorgnetteManagerClient; +class MetronomeClient; class ShillDeviceClient; class ShillIPConfigClient; class ShillManagerClient; @@ -85,6 +86,7 @@ class CHROMEOS_EXPORT DBusClientBundle { UPDATE_ENGINE = 1 << 18, PEER_DAEMON = 1 << 19, LEADERSHIP_DAEMON = 1 << 20, + METRONOME = 1 << 21, }; explicit DBusClientBundle(DBusClientTypeMask unstub_client_mask); @@ -175,6 +177,8 @@ class CHROMEOS_EXPORT DBusClientBundle { return lorgnette_manager_client_.get(); } + MetronomeClient* metronome_client() { return metronome_client_.get(); } + ShillDeviceClient* shill_device_client() { return shill_device_client_.get(); } @@ -289,6 +293,7 @@ class CHROMEOS_EXPORT DBusClientBundle { scoped_ptr<EasyUnlockClient> easy_unlock_client_; scoped_ptr<LeadershipDaemonManagerClient> leadership_daemon_manager_client_; scoped_ptr<LorgnetteManagerClient> lorgnette_manager_client_; + scoped_ptr<MetronomeClient> metronome_client_; scoped_ptr<PeerDaemonManagerClient> peer_daemon_manager_client_; scoped_ptr<ShillDeviceClient> shill_device_client_; scoped_ptr<ShillIPConfigClient> shill_ipconfig_client_; diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc index 62f48f1..c8d7ddb 100644 --- a/chromeos/dbus/dbus_thread_manager.cc +++ b/chromeos/dbus/dbus_thread_manager.cc @@ -30,6 +30,7 @@ #include "chromeos/dbus/introspectable_client.h" #include "chromeos/dbus/leadership_daemon_manager_client.h" #include "chromeos/dbus/lorgnette_manager_client.h" +#include "chromeos/dbus/metronome_client.h" #include "chromeos/dbus/modem_messaging_client.h" #include "chromeos/dbus/nfc_adapter_client.h" #include "chromeos/dbus/nfc_device_client.h" @@ -192,6 +193,10 @@ DBusThreadManager::GetLorgnetteManagerClient() { return client_bundle_->lorgnette_manager_client(); } +MetronomeClient* DBusThreadManager::GetMetronomeClient() { + return client_bundle_->metronome_client(); +} + ShillDeviceClient* DBusThreadManager::GetShillDeviceClient() { return client_bundle_->shill_device_client(); @@ -308,6 +313,7 @@ void DBusThreadManager::InitializeClients() { GetIntrospectableClient()->Init(GetSystemBus()); GetLeadershipDaemonManagerClient()->Init(GetSystemBus()); GetLorgnetteManagerClient()->Init(GetSystemBus()); + GetMetronomeClient()->Init(GetSystemBus()); GetModemMessagingClient()->Init(GetSystemBus()); GetPermissionBrokerClient()->Init(GetSystemBus()); GetPeerDaemonManagerClient()->Init(GetSystemBus()); @@ -546,6 +552,11 @@ void DBusThreadManagerSetter::SetLorgnetteManagerClient( client.Pass(); } +void DBusThreadManagerSetter::SetMetronomeClient( + scoped_ptr<MetronomeClient> client) { + DBusThreadManager::Get()->client_bundle_->metronome_client_ = client.Pass(); +} + void DBusThreadManagerSetter::SetShillDeviceClient( scoped_ptr<ShillDeviceClient> client) { DBusThreadManager::Get()->client_bundle_->shill_device_client_ = diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h index fd26384..3c76f0d 100644 --- a/chromeos/dbus/dbus_thread_manager.h +++ b/chromeos/dbus/dbus_thread_manager.h @@ -47,6 +47,7 @@ class ImageBurnerClient; class IntrospectableClient; class LeadershipDaemonManagerClient; class LorgnetteManagerClient; +class MetronomeClient; class ModemMessagingClient; class NfcAdapterClient; class NfcDeviceClient; @@ -138,6 +139,7 @@ class CHROMEOS_EXPORT DBusThreadManager { IntrospectableClient* GetIntrospectableClient(); LeadershipDaemonManagerClient* GetLeadershipDaemonManagerClient(); LorgnetteManagerClient* GetLorgnetteManagerClient(); + MetronomeClient* GetMetronomeClient(); ModemMessagingClient* GetModemMessagingClient(); NfcAdapterClient* GetNfcAdapterClient(); NfcDeviceClient* GetNfcDeviceClient(); @@ -226,6 +228,7 @@ class CHROMEOS_EXPORT DBusThreadManagerSetter { void SetLeadershipDaemonManagerClient( scoped_ptr<LeadershipDaemonManagerClient> client); void SetLorgnetteManagerClient(scoped_ptr<LorgnetteManagerClient> client); + void SetMetronomeClient(scoped_ptr<MetronomeClient> client); void SetShillDeviceClient(scoped_ptr<ShillDeviceClient> client); void SetShillIPConfigClient(scoped_ptr<ShillIPConfigClient> client); void SetShillManagerClient(scoped_ptr<ShillManagerClient> client); diff --git a/chromeos/dbus/metronome_client.cc b/chromeos/dbus/metronome_client.cc new file mode 100644 index 0000000..be3a8b6 --- /dev/null +++ b/chromeos/dbus/metronome_client.cc @@ -0,0 +1,216 @@ +// Copyright 2015 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/metronome_client.h" + +#include "base/bind.h" +#include "base/rand_util.h" +#include "base/command_line.h" +#include "base/logging.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "chromeos/chromeos_switches.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" + +// TODO(benchan): Move these DBus constants to system_api. +namespace metronome { + +const char kMetronomeInterface[] = "org.chromium.Metronome"; +const char kMetronomeServiceName[] = "org.chromium.Metronome"; +const char kMetronomeServicePath[] = "/org/chromium/Metronome"; +const char kTimestampUpdatedSignal[] = "TimestampUpdated"; + +} // namespace metronome + +namespace chromeos { + +namespace { + +//////////////////////////////////////////////////////////////////////////////// + +// The MetronomeClient implementation. +class MetronomeClientImpl : public MetronomeClient { + public: + MetronomeClientImpl() + : proxy_(nullptr), signal_connected_(false), weak_ptr_factory_(this) {} + + ~MetronomeClientImpl() override {} + + // MetronomeClient: + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + + protected: + // DBusClient: + void Init(dbus::Bus* bus) override; + + private: + // Handles TimestampUpdated signal and notifies |observers_|. + void OnTimestampUpdated(dbus::Signal* signal); + + // Handles the result of signal connection setup. + void OnSignalConnected(const std::string& interface, + const std::string& signal, + bool succeeded); + + dbus::ObjectProxy* proxy_; + + // True when |proxy_| has been connected. + bool signal_connected_; + + // List of observers interested in event notifications from us. + ObserverList<Observer> observers_; + + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<MetronomeClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(MetronomeClientImpl); +}; + +void MetronomeClientImpl::AddObserver(Observer* observer) { + DCHECK(observer); + if (!signal_connected_) { + signal_connected_ = true; + proxy_->ConnectToSignal(metronome::kMetronomeInterface, + metronome::kTimestampUpdatedSignal, + base::Bind(&MetronomeClientImpl::OnTimestampUpdated, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&MetronomeClientImpl::OnSignalConnected, + weak_ptr_factory_.GetWeakPtr())); + } + observers_.AddObserver(observer); +} + +void MetronomeClientImpl::RemoveObserver(Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); +} + +void MetronomeClientImpl::Init(dbus::Bus* bus) { + proxy_ = + bus->GetObjectProxy(metronome::kMetronomeServiceName, + dbus::ObjectPath(metronome::kMetronomeServicePath)); +} + +void MetronomeClientImpl::OnTimestampUpdated(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + uint64 beacon_timestamp = 0; + uint64 local_timestamp = 0; + if (!reader.PopUint64(&beacon_timestamp) || + !reader.PopUint64(&local_timestamp)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + FOR_EACH_OBSERVER(Observer, observers_, + OnTimestampUpdated(beacon_timestamp, local_timestamp)); +} + +void MetronomeClientImpl::OnSignalConnected(const std::string& interface, + const std::string& signal, + bool succeeded) { + LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " << signal + << " failed."; +} + +//////////////////////////////////////////////////////////////////////////////// + +// A fake implementation of MetronomeClient. It does not provide true +// synchronization and only exists to exercise the interfaces. +class MetronomeClientFakeImpl : public MetronomeClient { + public: + MetronomeClientFakeImpl() + : random_offset_(base::RandInt(-1000000, 1000000)) {} + + ~MetronomeClientFakeImpl() override { beacon_timer_.Stop(); } + + // MetronomeClient: + void AddObserver(Observer* observer) override { + DCHECK(observer); + observers_.AddObserver(observer); + } + + void RemoveObserver(Observer* observer) override { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // DBusClient: + void Init(dbus::Bus* bus) override { + beacon_timer_.Start(FROM_HERE, + base::TimeDelta::FromMilliseconds(1000), + this, + &MetronomeClientFakeImpl::UpdateBeacon); + } + + private: + void UpdateBeacon() { + base::Time now_time = base::Time::Now(); + base::TimeTicks now_ticks = base::TimeTicks::Now(); + uint64 fake_beacon_timestamp = now_time.ToInternalValue() + + base::RandInt(-1000, 1000); + uint64 fake_local_timestamp = now_ticks.ToInternalValue() + random_offset_ + + base::RandInt(-1000, 1000); + FOR_EACH_OBSERVER( + Observer, observers_, + OnTimestampUpdated(fake_beacon_timestamp, fake_local_timestamp)); + } + + int64 random_offset_; + base::RepeatingTimer<MetronomeClientFakeImpl> beacon_timer_; + + // List of observers interested in event notifications from us. + ObserverList<Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(MetronomeClientFakeImpl); +}; + +//////////////////////////////////////////////////////////////////////////////// + +// A stub implementation of MetronomeClient. It allows unit tests to complete. +class MetronomeClientStubImpl : public MetronomeClient { + public: + MetronomeClientStubImpl() {} + ~MetronomeClientStubImpl() override {} + + // MetronomeClient: + void AddObserver(Observer* observer) override {} + void RemoveObserver(Observer* observer) override {} + + // DBusClient: + void Init(dbus::Bus* bus) override {} + + private: + DISALLOW_COPY_AND_ASSIGN(MetronomeClientStubImpl); +}; + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// + +MetronomeClient::MetronomeClient() { +} + +MetronomeClient::~MetronomeClient() { +} + +// static +MetronomeClient* MetronomeClient::Create(DBusClientImplementationType type) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new MetronomeClientImpl(); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kTestMetronomeTimer)) { + return new MetronomeClientFakeImpl(); + } + return new MetronomeClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/metronome_client.h b/chromeos/dbus/metronome_client.h new file mode 100644 index 0000000..caa546b --- /dev/null +++ b/chromeos/dbus/metronome_client.h @@ -0,0 +1,49 @@ +// Copyright 2015 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. + +#ifndef CHROMEOS_DBUS_METRONOME_CLIENT_H_ +#define CHROMEOS_DBUS_METRONOME_CLIENT_H_ + +#include "base/basictypes.h" +#include "base/callback_forward.h" +#include "base/memory/ref_counted.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" + +namespace chromeos { + +// A DBus client class for the org.chromium.Metronome service. +class CHROMEOS_EXPORT MetronomeClient : public DBusClient { + public: + // Interface for observing timestamp events from a metronome client. + class Observer { + public: + // Called when the TimestampUpdated signal is received. + virtual void OnTimestampUpdated(uint64 beacon_timestamp, + uint64 local_timestamp) = 0; + virtual ~Observer() {} + }; + + ~MetronomeClient() override; + + // Adds and removes observers for timestamp events. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Factory function, creates a new instance and returns ownership. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static MetronomeClient* Create(DBusClientImplementationType type); + + protected: + // Create() should be used instead. + MetronomeClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(MetronomeClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_METRONOME_CLIENT_H_ |