diff options
author | jamescook <jamescook@chromium.org> | 2014-12-17 17:47:25 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-12-18 01:48:45 +0000 |
commit | 9439c7396b3e8816c1339b90a10dcbd50ac76792 (patch) | |
tree | 714d9b0129dd4fa37e482af4555868005cef2b0d /chromeos/audio | |
parent | 7c369d42b3557d37884d03a71021fa5b15919932 (diff) | |
download | chromium_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.h | 6 | ||||
-rw-r--r-- | chromeos/audio/audio_devices_pref_handler_impl.cc | 249 | ||||
-rw-r--r-- | chromeos/audio/audio_devices_pref_handler_impl.h | 93 | ||||
-rw-r--r-- | chromeos/audio/audio_devices_pref_handler_impl_unittest.cc | 129 |
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 |