diff --git a/chrome/browser/resources/settings/chromeos/device_page/audio.ts b/chrome/browser/resources/settings/chromeos/device_page/audio.ts index 416a43f87b56f..5fb1c4ea39d81 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/audio.ts +++ b/chrome/browser/resources/settings/chromeos/device_page/audio.ts @@ -18,7 +18,7 @@ import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {AudioDevice, AudioSystemPropertiesObserverReceiver, MuteState} from '../../mojom-webui/audio/cros_audio_config.mojom-webui.js'; +import {AudioSystemPropertiesObserverReceiver, MuteState} from '../../mojom-webui/audio/cros_audio_config.mojom-webui.js'; import {routes} from '../os_route.js'; import {RouteObserverMixin} from '../route_observer_mixin.js'; import {Route} from '../router.js'; @@ -142,10 +142,7 @@ class SettingsAudioElement extends SettingsAudioElementBase { const inputDeviceSelect = this.shadowRoot!.querySelector( '#audioInputDeviceDropdown'); assert(!!inputDeviceSelect); - const nextActiveDevice = this.audioSystemProperties_.inputDevices.find( - (device: AudioDevice) => device.id === BigInt(inputDeviceSelect.value)); - assert(!!nextActiveDevice); - this.crosAudioConfig_.setActiveDevice(nextActiveDevice); + this.crosAudioConfig_.setActiveDevice(BigInt(inputDeviceSelect.value)); } /** @@ -185,11 +182,7 @@ class SettingsAudioElement extends SettingsAudioElementBase { this.shadowRoot!.querySelector( '#audioOutputDeviceDropdown'); assert(!!outputDeviceSelect); - const nextActiveDevice = this.audioSystemProperties_.outputDevices.find( - (device: AudioDevice) => - device.id === BigInt(outputDeviceSelect.value)); - assert(!!nextActiveDevice); - this.crosAudioConfig_.setActiveDevice(nextActiveDevice); + this.crosAudioConfig_.setActiveDevice(BigInt(outputDeviceSelect.value)); } /** Handles updating outputMuteState. */ diff --git a/chrome/browser/resources/settings/chromeos/device_page/fake_cros_audio_config.ts b/chrome/browser/resources/settings/chromeos/device_page/fake_cros_audio_config.ts index 9a90da4d3c7ce..a8a305351f00f 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/fake_cros_audio_config.ts +++ b/chrome/browser/resources/settings/chromeos/device_page/fake_cros_audio_config.ts @@ -82,7 +82,6 @@ export function createAudioDevice( } export interface FakeCrosAudioConfigInterface extends CrosAudioConfigInterface { - setActiveDevice(outputDevice: AudioDevice): void; setOutputMuted(muted: boolean): void; setInputMuted(muted: boolean): void; setInputVolumePercent(percent: number): void; @@ -102,23 +101,23 @@ export class FakeCrosAudioConfig implements FakeCrosAudioConfigInterface { /** * Sets the active output or input device and notifies observers. */ - setActiveDevice(nextActiveDevice: AudioDevice): void { + setActiveDevice(deviceId: bigint): void { const isOutputDevice: boolean = !!(this.audioSystemProperties.outputDevices.find( - (device: AudioDevice) => device.id === nextActiveDevice.id)); + (device: AudioDevice) => device.id === deviceId)); if (isOutputDevice) { const devices = this.audioSystemProperties.outputDevices.map( (device: AudioDevice): AudioDevice => - createAudioDevice(device, device.id === nextActiveDevice.id)); + createAudioDevice(device, device.id === deviceId)); this.audioSystemProperties.outputDevices = devices; } else { // Device must be an input device otherwise an invalid device was // provided. assert(this.audioSystemProperties.inputDevices.find( - (device: AudioDevice) => device.id === nextActiveDevice.id)); + (device: AudioDevice) => device.id === deviceId)); const devices = this.audioSystemProperties.inputDevices.map( (device: AudioDevice): AudioDevice => - createAudioDevice(device, device.id === nextActiveDevice.id)); + createAudioDevice(device, device.id === deviceId)); this.audioSystemProperties.inputDevices = devices; } this.notifyAudioSystemPropertiesUpdated(); diff --git a/chrome/test/data/webui/settings/chromeos/fake_cros_audio_config_test.js b/chrome/test/data/webui/settings/chromeos/fake_cros_audio_config_test.js index cc96e0da74a36..b31814ac0afd3 100644 --- a/chrome/test/data/webui/settings/chromeos/fake_cros_audio_config_test.js +++ b/chrome/test/data/webui/settings/chromeos/fake_cros_audio_config_test.js @@ -100,7 +100,8 @@ suite('FakeCrosAudioConfig', function() { ], }; onPropertiesUpdated.addExpectation(updateActiveOutputDevice); - crosAudioConfig.setActiveDevice(fakeCrosAudioConfig.defaultFakeSpeaker); + crosAudioConfig.setActiveDevice( + fakeCrosAudioConfig.defaultFakeSpeaker.id); mockController.verifyMocks(); }); @@ -117,7 +118,7 @@ suite('FakeCrosAudioConfig', function() { ], }; onPropertiesUpdated.addExpectation(updateActiveInputDevice); - crosAudioConfig.setActiveDevice(fakeCrosAudioConfig.fakeBluetoothMic); + crosAudioConfig.setActiveDevice(fakeCrosAudioConfig.fakeBluetoothMic.id); mockController.verifyMocks(); }); diff --git a/chromeos/ash/components/audio/cros_audio_config_impl.cc b/chromeos/ash/components/audio/cros_audio_config_impl.cc index 720709bdfcff5..8668d8c7ac396 100644 --- a/chromeos/ash/components/audio/cros_audio_config_impl.cc +++ b/chromeos/ash/components/audio/cros_audio_config_impl.cc @@ -4,6 +4,7 @@ #include "chromeos/ash/components/audio/cros_audio_config_impl.h" +#include "base/logging.h" #include "chromeos/ash/components/audio/cras_audio_handler.h" namespace ash::audio_config { @@ -111,6 +112,22 @@ void CrosAudioConfigImpl::SetOutputVolumePercent(int8_t volume) { } } +void CrosAudioConfigImpl::SetActiveDevice(uint64_t device_id) { + CrasAudioHandler* audio_handler = CrasAudioHandler::Get(); + const AudioDevice* next_active_device = + audio_handler->GetDeviceFromId(device_id); + + if (!next_active_device) { + LOG(ERROR) << "SetActiveDevice: Cannot find device id=" + << "0x" << std::hex << device_id; + return; + } + + audio_handler->SwitchToDevice( + *next_active_device, /*notify=*/true, + CrasAudioHandler::DeviceActivateType::ACTIVATE_BY_USER); +} + void CrosAudioConfigImpl::OnOutputNodeVolumeChanged(uint64_t node_id, int volume) { NotifyObserversAudioSystemPropertiesChanged(); diff --git a/chromeos/ash/components/audio/cros_audio_config_impl.h b/chromeos/ash/components/audio/cros_audio_config_impl.h index fcc7fa8caeef0..3bda804fe9b7b 100644 --- a/chromeos/ash/components/audio/cros_audio_config_impl.h +++ b/chromeos/ash/components/audio/cros_audio_config_impl.h @@ -26,6 +26,7 @@ class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_AUDIO) CrosAudioConfigImpl std::vector* output_devices_out, std::vector* input_devices_out) const override; void SetOutputVolumePercent(int8_t volume) override; + void SetActiveDevice(uint64_t device_id) override; // CrasAudioHandler::AudioObserver: void OnOutputNodeVolumeChanged(uint64_t node_id, int volume) override; diff --git a/chromeos/ash/components/audio/cros_audio_config_impl_unittest.cc b/chromeos/ash/components/audio/cros_audio_config_impl_unittest.cc index d39a868c7d863..53790f97b3224 100644 --- a/chromeos/ash/components/audio/cros_audio_config_impl_unittest.cc +++ b/chromeos/ash/components/audio/cros_audio_config_impl_unittest.cc @@ -114,6 +114,11 @@ class CrosAudioConfigImplTest : public testing::Test { return fake_observer; } + void SimulateSetActiveDevice(const uint64_t& device_id) { + remote_->SetActiveDevice(device_id); + base::RunLoop().RunUntilIdle(); + } + void SetOutputVolumePercent(uint8_t volume_percent) { remote_->SetOutputVolumePercent(volume_percent); base::RunLoop().RunUntilIdle(); @@ -465,4 +470,52 @@ TEST_F(CrosAudioConfigImplTest, HandleExternalActiveInputDeviceUpdate) { ->is_active); } +TEST_F(CrosAudioConfigImplTest, SetActiveOutputDevice) { + std::unique_ptr fake_observer = Observe(); + + // Test default audio node list, with two output and one input node. + SetAudioNodes({kInternalSpeaker, kHDMIOutput, kMicJack}); + // Set active output node for test. + SetActiveOutputNodes({kInternalSpeakerId}); + ASSERT_TRUE(fake_observer->last_audio_system_properties_.value() + ->output_devices[0] + ->is_active); + ASSERT_FALSE(fake_observer->last_audio_system_properties_.value() + ->output_devices[1] + ->is_active); + + SimulateSetActiveDevice(kHDMIOutputId); + + ASSERT_FALSE(fake_observer->last_audio_system_properties_.value() + ->output_devices[0] + ->is_active); + ASSERT_TRUE(fake_observer->last_audio_system_properties_.value() + ->output_devices[1] + ->is_active); +} + +TEST_F(CrosAudioConfigImplTest, SetActiveInputDevice) { + std::unique_ptr fake_observer = Observe(); + + // Test default audio node list, with two input and one output node. + SetAudioNodes({kInternalSpeaker, kMicJack, kUsbMic}); + // Set active output node for test. + SetActiveInputNodes({kMicJackId}); + ASSERT_TRUE(fake_observer->last_audio_system_properties_.value() + ->input_devices[0] + ->is_active); + ASSERT_FALSE(fake_observer->last_audio_system_properties_.value() + ->input_devices[1] + ->is_active); + + SimulateSetActiveDevice(kUsbMicId); + + ASSERT_FALSE(fake_observer->last_audio_system_properties_.value() + ->input_devices[0] + ->is_active); + ASSERT_TRUE(fake_observer->last_audio_system_properties_.value() + ->input_devices[1] + ->is_active); +} + } // namespace ash::audio_config diff --git a/chromeos/ash/components/audio/public/mojom/cros_audio_config.mojom b/chromeos/ash/components/audio/public/mojom/cros_audio_config.mojom index 7b70809289c2d..776621d54cbd3 100644 --- a/chromeos/ash/components/audio/public/mojom/cros_audio_config.mojom +++ b/chromeos/ash/components/audio/public/mojom/cros_audio_config.mojom @@ -95,4 +95,8 @@ interface CrosAudioConfig { // Sets the volume of the active output device. If |volume| is above a // threshold and the device is muted, it's unmuted. SetOutputVolumePercent(int8 volume); + + // Updates active output or input device based on the audio device ID + // provided. + SetActiveDevice(uint64 device); };