Merge from Chromium at DEPS revision r198571

This commit was generated by merge_to_master.py.

Change-Id: I951118a03836157090561764dd2627f0add8118f
diff --git a/chromeos/dbus/cras_audio_client.cc b/chromeos/dbus/cras_audio_client.cc
new file mode 100644
index 0000000..ec20ea7
--- /dev/null
+++ b/chromeos/dbus/cras_audio_client.cc
@@ -0,0 +1,579 @@
+// Copyright (c) 2013 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/cras_audio_client.h"
+
+#include "base/bind.h"
+#include "dbus/bus.h"
+#include "dbus/message.h"
+#include "dbus/object_path.h"
+#include "dbus/object_proxy.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+// The CrasAudioClient implementation used in production.
+class CrasAudioClientImpl : public CrasAudioClient {
+ public:
+  explicit CrasAudioClientImpl(dbus::Bus* bus)
+      : cras_proxy_(NULL),
+        weak_ptr_factory_(this) {
+    cras_proxy_ = bus->GetObjectProxy(
+        cras::kCrasServiceName,
+        dbus::ObjectPath(cras::kCrasServicePath));
+
+    // Monitor NameOwnerChanged signal.
+    cras_proxy_->SetNameOwnerChangedCallback(
+        base::Bind(&CrasAudioClientImpl::NameOwnerChangedReceived,
+                   weak_ptr_factory_.GetWeakPtr()));
+
+    // Monitor the D-Bus signal for output volume change.
+    cras_proxy_->ConnectToSignal(
+        cras::kCrasControlInterface,
+        cras::kOutputVolumeChanged,
+        base::Bind(&CrasAudioClientImpl::OutputVolumeChangedReceived,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::Bind(&CrasAudioClientImpl::SignalConnected,
+                   weak_ptr_factory_.GetWeakPtr()));
+
+    // Monitor the D-Bus signal for output mute change.
+    cras_proxy_->ConnectToSignal(
+        cras::kCrasControlInterface,
+        cras::kOutputMuteChanged,
+        base::Bind(&CrasAudioClientImpl::OutputMuteChangedReceived,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::Bind(&CrasAudioClientImpl::SignalConnected,
+                   weak_ptr_factory_.GetWeakPtr()));
+
+    // Monitor the D-Bus signal for input gain change.
+    cras_proxy_->ConnectToSignal(
+        cras::kCrasControlInterface,
+        cras::kInputGainChanged,
+        base::Bind(&CrasAudioClientImpl::InputGainChangedReceived,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::Bind(&CrasAudioClientImpl::SignalConnected,
+                   weak_ptr_factory_.GetWeakPtr()));
+
+    // Monitor the D-Bus signal for input mute change.
+    cras_proxy_->ConnectToSignal(
+        cras::kCrasControlInterface,
+        cras::kInputMuteChanged,
+        base::Bind(&CrasAudioClientImpl::InputMuteChangedReceived,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::Bind(&CrasAudioClientImpl::SignalConnected,
+                   weak_ptr_factory_.GetWeakPtr()));
+
+    // Monitor the D-Bus signal for nodes change.
+    cras_proxy_->ConnectToSignal(
+        cras::kCrasControlInterface,
+        cras::kNodesChanged,
+        base::Bind(&CrasAudioClientImpl::NodesChangedReceived,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::Bind(&CrasAudioClientImpl::SignalConnected,
+                   weak_ptr_factory_.GetWeakPtr()));
+
+    // Monitor the D-Bus signal for active output node change.
+    cras_proxy_->ConnectToSignal(
+        cras::kCrasControlInterface,
+        cras::kActiveOutputNodeChanged,
+        base::Bind(&CrasAudioClientImpl::ActiveOutputNodeChangedReceived,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::Bind(&CrasAudioClientImpl::SignalConnected,
+                   weak_ptr_factory_.GetWeakPtr()));
+
+    // Monitor the D-Bus signal for active input node change.
+    cras_proxy_->ConnectToSignal(
+        cras::kCrasControlInterface,
+        cras::kActiveInputNodeChanged,
+        base::Bind(&CrasAudioClientImpl::ActiveInputNodeChangedReceived,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::Bind(&CrasAudioClientImpl::SignalConnected,
+                   weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  virtual ~CrasAudioClientImpl() {
+  }
+
+  // CrasAudioClient overrides:
+  virtual void AddObserver(Observer* observer) OVERRIDE {
+    observers_.AddObserver(observer);
+  }
+
+  virtual void RemoveObserver(Observer* observer) OVERRIDE {
+    observers_.RemoveObserver(observer);
+  }
+
+  virtual bool HasObserver(Observer* observer) OVERRIDE {
+    return observers_.HasObserver(observer);
+  }
+
+  virtual void GetVolumeState(const GetVolumeStateCallback& callback) OVERRIDE {
+    dbus::MethodCall method_call(cras::kCrasControlInterface,
+                                 cras::kGetVolumeState);
+    cras_proxy_->CallMethod(
+        &method_call,
+        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::Bind(&CrasAudioClientImpl::OnGetVolumeState,
+                   weak_ptr_factory_.GetWeakPtr(), callback));
+  }
+
+  virtual void GetNodes(const GetNodesCallback& callback) OVERRIDE {
+    dbus::MethodCall method_call(cras::kCrasControlInterface,
+                                 cras::kGetNodes);
+    cras_proxy_->CallMethod(
+        &method_call,
+        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::Bind(&CrasAudioClientImpl::OnGetNodes,
+                   weak_ptr_factory_.GetWeakPtr(), callback));
+  }
+
+  virtual void SetOutputVolume(int32 volume) OVERRIDE {
+    dbus::MethodCall method_call(cras::kCrasControlInterface,
+                                 cras::kSetOutputVolume);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendInt32(volume);
+    cras_proxy_->CallMethod(
+        &method_call,
+        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        dbus::ObjectProxy::EmptyResponseCallback());
+  }
+
+  virtual void SetOutputMute(bool mute_on) OVERRIDE {
+    dbus::MethodCall method_call(cras::kCrasControlInterface,
+                                 cras::kSetOutputMute);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendBool(mute_on);
+    cras_proxy_->CallMethod(
+        &method_call,
+        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        dbus::ObjectProxy::EmptyResponseCallback());
+  }
+
+  virtual void SetInputGain(int32 input_gain) OVERRIDE {
+    dbus::MethodCall method_call(cras::kCrasControlInterface,
+                                 cras::kSetInputGain);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendInt32(input_gain);
+    cras_proxy_->CallMethod(
+        &method_call,
+        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        dbus::ObjectProxy::EmptyResponseCallback());
+  }
+
+  virtual void SetInputMute(bool mute_on) OVERRIDE {
+    dbus::MethodCall method_call(cras::kCrasControlInterface,
+                                 cras::kSetInputMute);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendBool(mute_on);
+    cras_proxy_->CallMethod(
+        &method_call,
+        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        dbus::ObjectProxy::EmptyResponseCallback());
+  }
+
+  virtual void SetActiveOutputNode(uint64 node_id) OVERRIDE {
+    dbus::MethodCall method_call(cras::kCrasControlInterface,
+                                 cras::kSetActiveOutputNode);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendUint64(node_id);
+    cras_proxy_->CallMethod(
+        &method_call,
+        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        dbus::ObjectProxy::EmptyResponseCallback());
+  }
+
+  virtual void SetActiveInputNode(uint64 node_id) OVERRIDE {
+    dbus::MethodCall method_call(cras::kCrasControlInterface,
+                                 cras::kSetActiveInputNode);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendUint64(node_id);
+    cras_proxy_->CallMethod(
+        &method_call,
+        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        dbus::ObjectProxy::EmptyResponseCallback());
+  }
+
+ private:
+  // Called when the cras signal is initially connected.
+  void SignalConnected(const std::string& interface_name,
+                       const std::string& signal_name,
+                       bool success) {
+    LOG_IF(ERROR, !success)
+        << "Failed to connect to cras signal:" << signal_name;
+  }
+
+  void NameOwnerChangedReceived(dbus::Signal* signal) {
+    FOR_EACH_OBSERVER(Observer, observers_, AudioClientRestarted());
+  }
+
+  // Called when a OutputVolumeChanged signal is received.
+  void OutputVolumeChangedReceived(dbus::Signal* signal) {
+    dbus::MessageReader reader(signal);
+    int32 volume;
+    if (!reader.PopInt32(&volume)) {
+      LOG(ERROR) << "Error reading signal from cras:"
+                 << signal->ToString();
+    }
+    FOR_EACH_OBSERVER(Observer, observers_, OutputVolumeChanged(volume));
+  }
+
+  // Called when a OutputMuteChanged signal is received.
+  void OutputMuteChangedReceived(dbus::Signal* signal) {
+    dbus::MessageReader reader(signal);
+    bool mute;
+    if (!reader.PopBool(&mute)) {
+      LOG(ERROR) << "Error reading signal from cras:"
+                 << signal->ToString();
+    }
+    FOR_EACH_OBSERVER(Observer, observers_, OutputMuteChanged(mute));
+  }
+
+  // Called when a InputGainChanged signal is received.
+  void InputGainChangedReceived(dbus::Signal* signal) {
+    dbus::MessageReader reader(signal);
+    int32 gain;
+    if (!reader.PopInt32(&gain)) {
+      LOG(ERROR) << "Error reading signal from cras:"
+                 << signal->ToString();
+    }
+    FOR_EACH_OBSERVER(Observer, observers_, InputGainChanged(gain));
+  }
+
+  // Called when a InputMuteChanged signal is received.
+  void InputMuteChangedReceived(dbus::Signal* signal) {
+    dbus::MessageReader reader(signal);
+    bool mute;
+    if (!reader.PopBool(&mute)) {
+      LOG(ERROR) << "Error reading signal from cras:"
+                 << signal->ToString();
+    }
+    FOR_EACH_OBSERVER(Observer, observers_, InputMuteChanged(mute));
+  }
+
+  void NodesChangedReceived(dbus::Signal* signal) {
+    FOR_EACH_OBSERVER(Observer, observers_, NodesChanged());
+  }
+
+  void ActiveOutputNodeChangedReceived(dbus::Signal* signal) {
+    dbus::MessageReader reader(signal);
+    uint64 node_id;
+    if (!reader.PopUint64(&node_id)) {
+      LOG(ERROR) << "Error reading signal from cras:"
+                 << signal->ToString();
+    }
+    FOR_EACH_OBSERVER(Observer, observers_, ActiveOutputNodeChanged(node_id));
+  }
+
+  void ActiveInputNodeChangedReceived(dbus::Signal* signal) {
+    dbus::MessageReader reader(signal);
+    uint64 node_id;
+    if (!reader.PopUint64(&node_id)) {
+      LOG(ERROR) << "Error reading signal from cras:"
+                 << signal->ToString();
+    }
+    FOR_EACH_OBSERVER(Observer, observers_, ActiveInputNodeChanged(node_id));
+  }
+
+  void OnGetVolumeState(const GetVolumeStateCallback& callback,
+                        dbus::Response* response) {
+    bool success = true;
+    VolumeState volume_state;
+    if (response) {
+      dbus::MessageReader reader(response);
+      if (!reader.PopInt32(&volume_state.output_volume) ||
+          !reader.PopBool(&volume_state.output_mute) ||
+          !reader.PopInt32(&volume_state.input_gain) ||
+          !reader.PopBool(&volume_state.input_mute)) {
+        success = false;
+        LOG(ERROR) << "Error reading response from cras: "
+                   << response->ToString();
+      }
+    } else {
+      success = false;
+      LOG(ERROR) << "Error calling " << cras::kGetVolumeState;
+    }
+
+    callback.Run(volume_state, success);
+  }
+
+  void OnGetNodes(const GetNodesCallback& callback,
+                  dbus::Response* response) {
+    bool success = true;
+    AudioNodeList node_list;
+    if (response) {
+      dbus::MessageReader response_reader(response);
+      dbus::MessageReader array_reader(response);
+      while (response_reader.HasMoreData()) {
+        if (!response_reader.PopArray(&array_reader)) {
+          success = false;
+          LOG(ERROR) << "Error reading response from cras: "
+                     << response->ToString();
+          break;
+        }
+
+        AudioNode node;
+        if (!GetAudioNode(response, &array_reader, &node)) {
+          success = false;
+          LOG(WARNING) << "Error reading audio node data from cras: "
+                       << response->ToString();
+          break;
+        }
+
+        node_list.push_back(node);
+      }
+    } else {
+      success = false;
+      LOG(ERROR) << "Error calling " << cras::kGetNodes;
+    }
+
+    callback.Run(node_list, success);
+  }
+
+  bool GetAudioNode(dbus::Response* response,
+                    dbus::MessageReader* array_reader,
+                    AudioNode *node) {
+    while (array_reader->HasMoreData()) {
+      dbus::MessageReader dict_entry_reader(response);
+      dbus::MessageReader value_reader(response);
+      std::string key;
+      if (!array_reader->PopDictEntry(&dict_entry_reader) ||
+          !dict_entry_reader.PopString(&key) ||
+          !dict_entry_reader.PopVariant(&value_reader)) {
+         return false;
+      }
+
+      if (key == cras::kIsInputProperty) {
+        if (!value_reader.PopBool(&node->is_input))
+          return false;
+      } else if (key == cras::kIdProperty) {
+        if (!value_reader.PopUint64(&node->id))
+          return false;
+      } else if (key == cras::kDeviceNameProperty) {
+        if (!value_reader.PopString(&node->device_name))
+          return false;
+      } else if (key == cras::kTypeProperty) {
+        if (!value_reader.PopString(&node->type))
+          return false;
+      } else if (key == cras::kNameProperty) {
+        if (!value_reader.PopString(&node->name))
+          return false;
+      } else if (key == cras::kActiveProperty) {
+        if (!value_reader.PopBool(&node->active))
+          return false;
+      } else if (key == cras::kPluggedTimeProperty) {
+        if (!value_reader.PopUint64(&node->plugged_time))
+          return false;
+      }
+    }
+
+    return true;
+  }
+
+  dbus::ObjectProxy* cras_proxy_;
+  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<CrasAudioClientImpl> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(CrasAudioClientImpl);
+};
+
+// The CrasAudioClient implementation used on Linux desktop,
+// which does nothing.
+class CrasAudioClientStubImpl : public CrasAudioClient {
+ public:
+  CrasAudioClientStubImpl() {
+    VLOG(1) << "CrasAudioClientStubImpl is created";
+
+    // Fake audio output nodes.
+    AudioNode node_1;
+    node_1.is_input = false;
+    node_1.id = 10001;
+    node_1.device_name = "Fake Speaker";
+    node_1.type = "INTERNAL_SPEAKER";
+    node_1.name = "Speaker";
+    node_1.active = false;
+    node_list_.push_back(node_1);
+
+    AudioNode node_2;
+    node_2.is_input = false;
+    node_2.id = 10002;
+    node_2.device_name = "Fake Headphone";
+    node_2.type = "HEADPHONE";
+    node_2.name = "Headphone";
+    node_2.active = true;
+    node_list_.push_back(node_2);
+    active_output_node_id_ = node_2.id;
+
+    AudioNode node_3;
+    node_3.is_input = false;
+    node_3.id = 10003;
+    node_3.device_name = "Fake Audio Output";
+    node_3.type = "BLUETOOTH";
+    node_3.name = "Bluetooth Headphone";
+    node_3.active = false;
+    node_list_.push_back(node_3);
+
+    // Fake audio input ndoes
+    AudioNode node_4;
+    node_4.is_input = true;
+    node_4.id = 10004;
+    node_4.device_name = "Fake Internal Mic";
+    node_4.type = "INTERNAL_MIC";
+    node_4.name = "Internal Mic";
+    node_4.active = false;
+    node_list_.push_back(node_4);
+
+    AudioNode node_5;
+    node_5.is_input = true;
+    node_5.id = 10005;
+    node_5.device_name = "Fake Internal Mic";
+    node_5.type = "USB";
+    node_5.name = "USB Mic";
+    node_5.active = true;
+    node_list_.push_back(node_5);
+    active_input_node_id_ = node_5.id;
+  }
+  virtual ~CrasAudioClientStubImpl() {
+  }
+
+  // CrasAudioClient overrides:
+  // TODO(jennyz): Implement the observers and callbacks in the stub for UI
+  // testing.
+  virtual void AddObserver(Observer* observer) OVERRIDE {
+    observers_.AddObserver(observer);
+  }
+
+  virtual void RemoveObserver(Observer* observer) OVERRIDE {
+    observers_.RemoveObserver(observer);
+  }
+
+  virtual bool HasObserver(Observer* observer) OVERRIDE {
+    return observers_.HasObserver(observer);
+  }
+
+  virtual void GetVolumeState(const GetVolumeStateCallback& callback) OVERRIDE {
+    callback.Run(volume_state_, true);
+  }
+
+  virtual void GetNodes(const GetNodesCallback& callback)OVERRIDE {
+    callback.Run(node_list_, true);
+  }
+
+  virtual void SetOutputVolume(int32 volume) OVERRIDE {
+    volume_state_.output_volume = volume;
+    FOR_EACH_OBSERVER(Observer,
+                      observers_,
+                      OutputVolumeChanged(volume_state_.output_volume));
+  }
+
+  virtual void SetOutputMute(bool mute_on) OVERRIDE {
+    volume_state_.output_mute = mute_on;
+    FOR_EACH_OBSERVER(Observer,
+                      observers_,
+                      OutputMuteChanged(volume_state_.output_mute));
+  }
+
+  virtual void SetInputGain(int32 input_gain) OVERRIDE {
+    volume_state_.input_gain = input_gain;
+    FOR_EACH_OBSERVER(Observer,
+                      observers_,
+                      InputGainChanged(volume_state_.input_gain));
+  }
+
+  virtual void SetInputMute(bool mute_on) OVERRIDE {
+    volume_state_.input_mute = mute_on;
+    FOR_EACH_OBSERVER(Observer,
+                      observers_,
+                      InputMuteChanged(volume_state_.input_mute));
+  }
+
+  virtual void SetActiveOutputNode(uint64 node_id) OVERRIDE {
+    if (active_output_node_id_ == node_id)
+      return;
+
+    for (size_t i = 0; i < node_list_.size(); ++i) {
+      if (node_list_[i].id == active_output_node_id_)
+        node_list_[i].active = false;
+      else if (node_list_[i].id == node_id)
+        node_list_[i].active = true;
+    }
+    active_output_node_id_ = node_id;
+    FOR_EACH_OBSERVER(Observer,
+                      observers_,
+                      ActiveOutputNodeChanged(node_id));
+  }
+
+  virtual void SetActiveInputNode(uint64 node_id) OVERRIDE {
+    if (active_input_node_id_ == node_id)
+      return;
+
+    for (size_t i = 0; i < node_list_.size(); ++i) {
+      if (node_list_[i].id == active_input_node_id_)
+        node_list_[i].active = false;
+      else if (node_list_[i].id == node_id)
+        node_list_[i].active = true;
+    }
+    active_input_node_id_ = node_id;
+    FOR_EACH_OBSERVER(Observer,
+                      observers_,
+                      ActiveInputNodeChanged(node_id));
+  }
+
+ private:
+  VolumeState volume_state_;
+  AudioNodeList node_list_;
+  uint64 active_input_node_id_;
+  uint64 active_output_node_id_;
+  ObserverList<Observer> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(CrasAudioClientStubImpl);
+};
+
+CrasAudioClient::Observer::~Observer() {
+}
+
+void CrasAudioClient::Observer::AudioClientRestarted() {
+}
+
+void CrasAudioClient::Observer::OutputVolumeChanged(int32 volume) {
+}
+
+void CrasAudioClient::Observer::OutputMuteChanged(bool mute_on) {
+}
+
+void CrasAudioClient::Observer::InputGainChanged(int gain) {
+}
+
+void CrasAudioClient::Observer::InputMuteChanged(bool mute_on) {
+}
+
+void CrasAudioClient::Observer::NodesChanged() {
+}
+
+void CrasAudioClient::Observer::ActiveOutputNodeChanged(uint64 node_id){
+}
+
+void CrasAudioClient::Observer::ActiveInputNodeChanged(uint64 node_id) {
+}
+
+CrasAudioClient::CrasAudioClient() {
+}
+
+CrasAudioClient::~CrasAudioClient() {
+}
+
+// static
+CrasAudioClient* CrasAudioClient::Create(
+    DBusClientImplementationType type,
+    dbus::Bus* bus) {
+  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) {
+    return new CrasAudioClientImpl(bus);
+  }
+  DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
+  return new CrasAudioClientStubImpl();
+}
+
+}  // namespace chromeos