summaryrefslogtreecommitdiffstats
path: root/chromeos/audio
diff options
context:
space:
mode:
authorjamescook <jamescook@chromium.org>2014-12-17 17:47:25 -0800
committerCommit bot <commit-bot@chromium.org>2014-12-18 01:48:45 +0000
commit9439c7396b3e8816c1339b90a10dcbd50ac76792 (patch)
tree714d9b0129dd4fa37e482af4555868005cef2b0d /chromeos/audio
parent7c369d42b3557d37884d03a71021fa5b15919932 (diff)
downloadchromium_src-9439c7396b3e8816c1339b90a10dcbd50ac76792.zip
chromium_src-9439c7396b3e8816c1339b90a10dcbd50ac76792.tar.gz
chromium_src-9439c7396b3e8816c1339b90a10dcbd50ac76792.tar.bz2
cros: Move AudioDevicesPrefHandlerImpl to //chromeos/audio
This consolidates all the audio device code in //chromeos/audio and will make it possible for app_shell to create a real CrasAudioHandler. * Make the "allow audio capture" preference optional so that it can be used by Chrome and skipped by app_shell. * Introduce chromeos/chromeos_pref_names.h/cc for Chrome OS specific prefs. The next CL will connect this code to app_shell. BUG=442401 TEST=added to chromeos_unittests AudioDevicesPrefHandlerTest Review URL: https://codereview.chromium.org/805373002 Cr-Commit-Position: refs/heads/master@{#308919}
Diffstat (limited to 'chromeos/audio')
-rw-r--r--chromeos/audio/audio_devices_pref_handler.h6
-rw-r--r--chromeos/audio/audio_devices_pref_handler_impl.cc249
-rw-r--r--chromeos/audio/audio_devices_pref_handler_impl.h93
-rw-r--r--chromeos/audio/audio_devices_pref_handler_impl_unittest.cc129
4 files changed, 473 insertions, 4 deletions
diff --git a/chromeos/audio/audio_devices_pref_handler.h b/chromeos/audio/audio_devices_pref_handler.h
index 417c4ec..53a3fce 100644
--- a/chromeos/audio/audio_devices_pref_handler.h
+++ b/chromeos/audio/audio_devices_pref_handler.h
@@ -35,7 +35,8 @@ class CHROMEOS_EXPORT AudioDevicesPrefHandler
// Sets the audio mute value to prefs for a device.
virtual void SetMuteValue(const AudioDevice& device, bool mute_on) = 0;
- // Reads the audio capture allowed value from prefs.
+ // Reads the audio capture allowed value from prefs, which can be used to
+ // disable audio capture via policy.
virtual bool GetAudioCaptureAllowedValue() = 0;
// Reads the audio output allowed value from prefs.
virtual bool GetAudioOutputAllowedValue() = 0;
@@ -45,9 +46,6 @@ class CHROMEOS_EXPORT AudioDevicesPrefHandler
// Removes an audio preference observer.
virtual void RemoveAudioPrefObserver(AudioPrefObserver* observer) = 0;
- // Creates the instance.
- static AudioDevicesPrefHandler* Create(PrefService* local_state);
-
protected:
virtual ~AudioDevicesPrefHandler() {}
diff --git a/chromeos/audio/audio_devices_pref_handler_impl.cc b/chromeos/audio/audio_devices_pref_handler_impl.cc
new file mode 100644
index 0000000..77987c7
--- /dev/null
+++ b/chromeos/audio/audio_devices_pref_handler_impl.cc
@@ -0,0 +1,249 @@
+// 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/audio/audio_devices_pref_handler_impl.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service.h"
+#include "base/prefs/scoped_user_pref_update.h"
+#include "base/strings/string_number_conversions.h"
+#include "chromeos/audio/audio_device.h"
+#include "chromeos/chromeos_pref_names.h"
+
+namespace {
+
+const double kDefaultOutputVolume = 75.0;
+const double kDefaultHDMIOutputVolume = 100.0;
+
+// Values used for muted preference.
+const int kPrefMuteOff = 0;
+const int kPrefMuteOn = 1;
+
+// Gets the device id string for storing audio preference. The format of
+// device string is a string consisting of 3 parts.
+// |device_name| : |integer from lower 32 bit of device id| :
+// |0(output device) or 1(input device)|
+// If an audio device has both integrated input and output devices, the first 2
+// parts of the string could be identical, only the last part will differentiate
+// them.
+std::string GetDeviceIdString(const chromeos::AudioDevice& device) {
+ std::string device_id_string =
+ device.device_name + " : " +
+ base::Uint64ToString(device.id & static_cast<uint64>(0xffffffff)) +
+ " : " + (device.is_input ? "1" : "0");
+ // Replace any periods from the device id string with a space, since setting
+ // names cannot contain periods.
+ std::replace(device_id_string.begin(), device_id_string.end(), '.', ' ');
+ return device_id_string;
+}
+
+} // namespace
+
+namespace chromeos {
+
+double AudioDevicesPrefHandlerImpl::GetOutputVolumeValue(
+ const AudioDevice* device) {
+ if (!device)
+ return kDefaultOutputVolume;
+ else
+ return GetVolumeGainPrefValue(*device);
+}
+
+double AudioDevicesPrefHandlerImpl::GetInputGainValue(
+ const AudioDevice* device) {
+ DCHECK(device);
+ return GetVolumeGainPrefValue(*device);
+}
+
+void AudioDevicesPrefHandlerImpl::SetVolumeGainValue(
+ const AudioDevice& device, double value) {
+ device_volume_settings_->SetDouble(GetDeviceIdString(device), value);
+
+ SaveDevicesVolumePref();
+}
+
+bool AudioDevicesPrefHandlerImpl::GetMuteValue(const AudioDevice& device) {
+ UpdateDevicesMutePref();
+
+ std::string device_id_str = GetDeviceIdString(device);
+ if (!device_mute_settings_->HasKey(device_id_str))
+ MigrateDeviceMuteSettings(device_id_str);
+
+ int mute = kPrefMuteOff;
+ device_mute_settings_->GetInteger(device_id_str, &mute);
+
+ return (mute == kPrefMuteOn);
+}
+
+void AudioDevicesPrefHandlerImpl::SetMuteValue(const AudioDevice& device,
+ bool mute) {
+ device_mute_settings_->SetInteger(GetDeviceIdString(device),
+ mute ? kPrefMuteOn : kPrefMuteOff);
+ SaveDevicesMutePref();
+}
+
+
+bool AudioDevicesPrefHandlerImpl::GetAudioCaptureAllowedValue() {
+ if (audio_capture_allowed_pref_.empty())
+ return true;
+
+ return local_state_->GetBoolean(audio_capture_allowed_pref_);
+}
+
+bool AudioDevicesPrefHandlerImpl::GetAudioOutputAllowedValue() {
+ return local_state_->GetBoolean(prefs::kAudioOutputAllowed);
+}
+
+void AudioDevicesPrefHandlerImpl::AddAudioPrefObserver(
+ AudioPrefObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void AudioDevicesPrefHandlerImpl::RemoveAudioPrefObserver(
+ AudioPrefObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+double AudioDevicesPrefHandlerImpl::GetVolumeGainPrefValue(
+ const AudioDevice& device) {
+ UpdateDevicesVolumePref();
+
+ std::string device_id_str = GetDeviceIdString(device);
+ if (!device_volume_settings_->HasKey(device_id_str))
+ MigrateDeviceVolumeSettings(device_id_str);
+
+ // TODO(jennyz, rkc): Return a meaningful input gain default value, when
+ // cras has added support for normalizing input gain range.
+ double value = device.is_input ?
+ 0.0 : GetDeviceDefaultOutputVolume(device);
+ // TODO(rkc): The above code is completely ignored since we 'always' have a
+ // default pref value. Fix this. http://crbug.com/442489
+ device_volume_settings_->GetDouble(device_id_str, &value);
+
+ return value;
+}
+
+double AudioDevicesPrefHandlerImpl::GetDeviceDefaultOutputVolume(
+ const AudioDevice& device) {
+ if (device.type == AUDIO_TYPE_HDMI)
+ return kDefaultHDMIOutputVolume;
+ else
+ return kDefaultOutputVolume;
+}
+
+AudioDevicesPrefHandlerImpl::AudioDevicesPrefHandlerImpl(
+ PrefService* local_state,
+ const std::string& audio_capture_allowed_pref)
+ : device_mute_settings_(new base::DictionaryValue()),
+ device_volume_settings_(new base::DictionaryValue()),
+ local_state_(local_state),
+ audio_capture_allowed_pref_(audio_capture_allowed_pref) {
+ InitializePrefObservers();
+
+ UpdateDevicesMutePref();
+ UpdateDevicesVolumePref();
+}
+
+AudioDevicesPrefHandlerImpl::~AudioDevicesPrefHandlerImpl() {
+}
+
+void AudioDevicesPrefHandlerImpl::InitializePrefObservers() {
+ pref_change_registrar_.Init(local_state_);
+ base::Closure callback =
+ base::Bind(&AudioDevicesPrefHandlerImpl::NotifyAudioPolicyChange,
+ base::Unretained(this));
+ pref_change_registrar_.Add(prefs::kAudioOutputAllowed, callback);
+
+ if (!audio_capture_allowed_pref_.empty())
+ pref_change_registrar_.Add(audio_capture_allowed_pref_, callback);
+}
+
+void AudioDevicesPrefHandlerImpl::UpdateDevicesMutePref() {
+ const base::DictionaryValue* mute_prefs =
+ local_state_->GetDictionary(prefs::kAudioDevicesMute);
+ if (mute_prefs)
+ device_mute_settings_.reset(mute_prefs->DeepCopy());
+}
+
+void AudioDevicesPrefHandlerImpl::SaveDevicesMutePref() {
+ DictionaryPrefUpdate dict_update(local_state_, prefs::kAudioDevicesMute);
+ base::DictionaryValue::Iterator it(*device_mute_settings_);
+ while (!it.IsAtEnd()) {
+ int mute = kPrefMuteOff;
+ it.value().GetAsInteger(&mute);
+ dict_update->SetInteger(it.key(), mute);
+ it.Advance();
+ }
+}
+
+void AudioDevicesPrefHandlerImpl::UpdateDevicesVolumePref() {
+ const base::DictionaryValue* volume_prefs =
+ local_state_->GetDictionary(prefs::kAudioDevicesVolumePercent);
+ if (volume_prefs)
+ device_volume_settings_.reset(volume_prefs->DeepCopy());
+}
+
+void AudioDevicesPrefHandlerImpl::SaveDevicesVolumePref() {
+ DictionaryPrefUpdate dict_update(local_state_,
+ prefs::kAudioDevicesVolumePercent);
+ base::DictionaryValue::Iterator it(*device_volume_settings_);
+ while (!it.IsAtEnd()) {
+ double volume = kDefaultOutputVolume;
+ bool success = it.value().GetAsDouble(&volume);
+ DCHECK(success);
+ dict_update->SetDouble(it.key(), volume);
+ it.Advance();
+ }
+}
+
+void AudioDevicesPrefHandlerImpl::MigrateDeviceMuteSettings(
+ std::string active_device) {
+ int old_mute = local_state_->GetInteger(prefs::kAudioMute);
+ device_mute_settings_->SetInteger(active_device, old_mute);
+ SaveDevicesMutePref();
+}
+
+void AudioDevicesPrefHandlerImpl::MigrateDeviceVolumeSettings(
+ std::string active_device) {
+ double old_volume = local_state_->GetDouble(prefs::kAudioVolumePercent);
+ device_volume_settings_->SetDouble(active_device, old_volume);
+ SaveDevicesVolumePref();
+}
+
+void AudioDevicesPrefHandlerImpl::NotifyAudioPolicyChange() {
+ FOR_EACH_OBSERVER(AudioPrefObserver,
+ observers_,
+ OnAudioPolicyPrefChanged());
+}
+
+// static
+void AudioDevicesPrefHandlerImpl::RegisterPrefs(
+ PrefRegistrySimple* registry,
+ const std::string& audio_capture_allowed_pref) {
+ registry->RegisterDictionaryPref(prefs::kAudioDevicesVolumePercent);
+ registry->RegisterDictionaryPref(prefs::kAudioDevicesMute);
+
+ // Register the prefs backing the audio muting policies.
+ registry->RegisterBooleanPref(prefs::kAudioOutputAllowed, true);
+
+ // This pref has moved to the media subsystem but we should verify it is there
+ // before we use it.
+ // NOTE: This registers the pref in the device-wide local state pref registry.
+ // In Chrome the media subsystem also registers kAudioCaptureAllowed in the
+ // per-user profile pref registry.
+ if (!audio_capture_allowed_pref.empty())
+ registry->RegisterBooleanPref(audio_capture_allowed_pref, true);
+
+ // Register the legacy audio prefs for migration.
+ registry->RegisterDoublePref(prefs::kAudioVolumePercent,
+ kDefaultOutputVolume);
+ registry->RegisterIntegerPref(prefs::kAudioMute, kPrefMuteOff);
+}
+
+} // namespace chromeos
diff --git a/chromeos/audio/audio_devices_pref_handler_impl.h b/chromeos/audio/audio_devices_pref_handler_impl.h
new file mode 100644
index 0000000..ccb4236
--- /dev/null
+++ b/chromeos/audio/audio_devices_pref_handler_impl.h
@@ -0,0 +1,93 @@
+// 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.
+
+#ifndef CHROMEOS_AUDIO_AUDIO_DEVICES_PREF_HANDLER_IMPL_H_
+#define CHROMEOS_AUDIO_AUDIO_DEVICES_PREF_HANDLER_IMPL_H_
+
+#include <string>
+
+#include "base/observer_list.h"
+#include "base/prefs/pref_change_registrar.h"
+#include "base/values.h"
+#include "chromeos/audio/audio_devices_pref_handler.h"
+#include "chromeos/chromeos_export.h"
+
+class PrefRegistrySimple;
+class PrefService;
+
+namespace chromeos {
+
+// Class which implements AudioDevicesPrefHandler interface and register audio
+// preferences as well.
+class CHROMEOS_EXPORT AudioDevicesPrefHandlerImpl
+ : public AudioDevicesPrefHandler {
+ public:
+ AudioDevicesPrefHandlerImpl(PrefService* local_state,
+ const std::string& audio_capture_allowed_pref);
+
+ // Overridden from AudioDevicesPrefHandler.
+ virtual double GetOutputVolumeValue(const AudioDevice* device) override;
+ virtual double GetInputGainValue(const AudioDevice* device) override;
+ virtual void SetVolumeGainValue(const AudioDevice& device,
+ double value) override;
+
+ virtual bool GetMuteValue(const AudioDevice& device) override;
+ virtual void SetMuteValue(const AudioDevice& device, bool mute_on) override;
+
+ virtual bool GetAudioCaptureAllowedValue() override;
+ virtual bool GetAudioOutputAllowedValue() override;
+
+ virtual void AddAudioPrefObserver(AudioPrefObserver* observer) override;
+ virtual void RemoveAudioPrefObserver(AudioPrefObserver* observer) override;
+
+ // Registers volume and mute preferences.
+ static void RegisterPrefs(PrefRegistrySimple* registry,
+ const std::string& audio_capture_allowed_pref);
+
+ protected:
+ virtual ~AudioDevicesPrefHandlerImpl();
+
+ private:
+ // Initializes the observers for the policy prefs.
+ void InitializePrefObservers();
+
+ // Update and save methods for the mute preferences for all devices.
+ void UpdateDevicesMutePref();
+ void SaveDevicesMutePref();
+
+ // Update and save methods for the volume preferences for all devices.
+ void UpdateDevicesVolumePref();
+ void SaveDevicesVolumePref();
+
+ double GetVolumeGainPrefValue(const AudioDevice& device);
+ double GetDeviceDefaultOutputVolume(const AudioDevice& device);
+
+ // Methods to migrate the mute and volume settings for a device from the
+ // previous global pref value to the new per device pref value for the
+ // current active device. If a previous global setting doesn't exist, we'll
+ // use default values of mute = off and volume = 75%.
+ void MigrateDeviceMuteSettings(std::string active_device);
+ void MigrateDeviceVolumeSettings(std::string active_device);
+
+ // Notifies the AudioPrefObserver for audio policy pref changes.
+ void NotifyAudioPolicyChange();
+
+ scoped_ptr<base::DictionaryValue> device_mute_settings_;
+ scoped_ptr<base::DictionaryValue> device_volume_settings_;
+
+ PrefService* local_state_; // not owned
+
+ // The name of the preferences to check if audio capture is allowed or the
+ // empty string if audio capture is always allowed.
+ const std::string audio_capture_allowed_pref_;
+
+ PrefChangeRegistrar pref_change_registrar_;
+ ObserverList<AudioPrefObserver> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioDevicesPrefHandlerImpl);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_AUDIO_AUDIO_DEVICES_PREF_HANDLER_IMPL_H_
diff --git a/chromeos/audio/audio_devices_pref_handler_impl_unittest.cc b/chromeos/audio/audio_devices_pref_handler_impl_unittest.cc
new file mode 100644
index 0000000..a3f7e77
--- /dev/null
+++ b/chromeos/audio/audio_devices_pref_handler_impl_unittest.cc
@@ -0,0 +1,129 @@
+// Copyright 2014 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/audio/audio_devices_pref_handler_impl.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/prefs/testing_pref_service.h"
+#include "chromeos/audio/audio_device.h"
+#include "chromeos/audio/audio_devices_pref_handler.h"
+#include "chromeos/chromeos_pref_names.h"
+#include "chromeos/dbus/audio_node.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+const uint64 kInternalMicId = 10003;
+const uint64 kHeadphoneId = 10002;
+const uint64 kHDMIOutputId = 10006;
+const uint64 kOtherTypeOutputId = 90001;
+const uint64 kOtherTypeInputId = 90002;
+
+const AudioDevice kInternalMic(AudioNode(true,
+ kInternalMicId,
+ "Fake Mic",
+ "INTERNAL_MIC",
+ "Internal Mic",
+ false,
+ 0));
+
+const AudioDevice kHeadphone(AudioNode(false,
+ kHeadphoneId,
+ "Fake Headphone",
+ "HEADPHONE",
+ "Headphone",
+ false,
+ 0));
+
+const AudioDevice kHDMIOutput(AudioNode(false,
+ kHDMIOutputId,
+ "HDMI output",
+ "HDMI",
+ "HDMI output",
+ false,
+ 0));
+
+const AudioDevice kInputDeviceWithSpecialCharacters(
+ AudioNode(true,
+ kOtherTypeInputId,
+ "Fake ~!@#$%^&*()_+`-=<>?,./{}|[]\\\\Mic",
+ "SOME_OTHER_TYPE",
+ "Other Type Input Device",
+ true,
+ 0));
+
+const AudioDevice kOutputDeviceWithSpecialCharacters(
+ AudioNode(false,
+ kOtherTypeOutputId,
+ "Fake ~!@#$%^&*()_+`-=<>?,./{}|[]\\\\Headphone",
+ "SOME_OTHER_TYPE",
+ "Other Type Output Device",
+ false,
+ 0));
+
+const char kAudioCaptureAllowedPref[] = "audio_capture_allowed";
+
+class AudioDevicesPrefHandlerTest : public testing::Test {
+ public:
+ AudioDevicesPrefHandlerTest() {}
+ ~AudioDevicesPrefHandlerTest() override {}
+
+ void SetUp() override {
+ pref_service_.reset(new TestingPrefServiceSimple());
+ AudioDevicesPrefHandlerImpl::RegisterPrefs(pref_service_->registry(),
+ kAudioCaptureAllowedPref);
+ audio_pref_handler_ = new AudioDevicesPrefHandlerImpl(
+ pref_service_.get(), kAudioCaptureAllowedPref);
+ }
+
+ void TearDown() override { audio_pref_handler_ = NULL; }
+
+ protected:
+ scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler_;
+ scoped_ptr<TestingPrefServiceSimple> pref_service_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AudioDevicesPrefHandlerTest);
+};
+
+TEST_F(AudioDevicesPrefHandlerTest, TestDefaultValues) {
+ // TODO(rkc): Once the bug with default preferences is fixed, fix this test
+ // also. http://crbug.com/442489
+ EXPECT_EQ(75.0, audio_pref_handler_->GetInputGainValue(&kInternalMic));
+ EXPECT_EQ(75.0, audio_pref_handler_->GetOutputVolumeValue(&kHeadphone));
+ EXPECT_EQ(75.0, audio_pref_handler_->GetOutputVolumeValue(&kHDMIOutput));
+}
+
+TEST_F(AudioDevicesPrefHandlerTest, PrefsRegistered) {
+ // The standard audio prefs are registered.
+ EXPECT_TRUE(pref_service_->FindPreference(prefs::kAudioDevicesVolumePercent));
+ EXPECT_TRUE(pref_service_->FindPreference(prefs::kAudioDevicesMute));
+ EXPECT_TRUE(pref_service_->FindPreference(prefs::kAudioOutputAllowed));
+ EXPECT_TRUE(pref_service_->FindPreference(prefs::kAudioVolumePercent));
+ EXPECT_TRUE(pref_service_->FindPreference(prefs::kAudioMute));
+
+ // The optional pref is also registered.
+ EXPECT_TRUE(pref_service_->FindPreference(kAudioCaptureAllowedPref));
+}
+
+TEST_F(AudioDevicesPrefHandlerTest, TestBasicInputOutputDevices) {
+ audio_pref_handler_->SetVolumeGainValue(kInternalMic, 13.37);
+ EXPECT_EQ(13.37, audio_pref_handler_->GetInputGainValue(&kInternalMic));
+ audio_pref_handler_->SetVolumeGainValue(kHeadphone, 47.28);
+ EXPECT_EQ(47.28, audio_pref_handler_->GetOutputVolumeValue(&kHeadphone));
+}
+
+TEST_F(AudioDevicesPrefHandlerTest, TestSpecialCharactersInDeviceNames) {
+ audio_pref_handler_->SetVolumeGainValue(kInputDeviceWithSpecialCharacters,
+ 73.31);
+ audio_pref_handler_->SetVolumeGainValue(kOutputDeviceWithSpecialCharacters,
+ 85.92);
+
+ EXPECT_EQ(73.31, audio_pref_handler_->GetInputGainValue(
+ &kInputDeviceWithSpecialCharacters));
+ EXPECT_EQ(85.92, audio_pref_handler_->GetOutputVolumeValue(
+ &kOutputDeviceWithSpecialCharacters));
+}
+
+} // namespace chromeos