Skip to content

Commit

Permalink
audio-settings: add setActiveDevice to mojo
Browse files Browse the repository at this point in the history
- Add setActiveDevice to mojo interface.
- Remove "setActiveDevice" from fake interface to rely on mojo
  definition.
- Update fake backend and related tests to use updated API using
  ID instead of AudioDevice.
- Request CrasAudioHandler to update active output or input device
  when `setActiveDevice` called with valid device id.
- Test output devices update correctly.
- Test input devices update correctly.

Bug: b:260277007
Test: ./out/Default/chromeos_unittests --gtest_filter=*CrosAudioConfigImpl*
Test: browser_test --gtest_filter=*OSSettings*DevicePage*:*OSSettings*FakeCros*
Change-Id: I1c6c61ae94a505c2834a8bbd919055a176b0430d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4088288
Auto-Submit: Ashley Prasad <ashleydp@google.com>
Reviewed-by: Michael Checo <michaelcheco@google.com>
Commit-Queue: Emily Stark <estark@chromium.org>
Reviewed-by: Emily Stark <estark@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1085135}
  • Loading branch information
Ashley Prasad authored and Chromium LUCI CQ committed Dec 19, 2022
1 parent 8054c42 commit 0bc91aa
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 18 deletions.
13 changes: 3 additions & 10 deletions chrome/browser/resources/settings/chromeos/device_page/audio.ts
Expand Up @@ -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';
Expand Down Expand Up @@ -142,10 +142,7 @@ class SettingsAudioElement extends SettingsAudioElementBase {
const inputDeviceSelect = this.shadowRoot!.querySelector<HTMLSelectElement>(
'#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));
}

/**
Expand Down Expand Up @@ -185,11 +182,7 @@ class SettingsAudioElement extends SettingsAudioElementBase {
this.shadowRoot!.querySelector<HTMLSelectElement>(
'#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. */
Expand Down
Expand Up @@ -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;
Expand All @@ -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();
Expand Down
Expand Up @@ -100,7 +100,8 @@ suite('FakeCrosAudioConfig', function() {
],
};
onPropertiesUpdated.addExpectation(updateActiveOutputDevice);
crosAudioConfig.setActiveDevice(fakeCrosAudioConfig.defaultFakeSpeaker);
crosAudioConfig.setActiveDevice(
fakeCrosAudioConfig.defaultFakeSpeaker.id);

mockController.verifyMocks();
});
Expand All @@ -117,7 +118,7 @@ suite('FakeCrosAudioConfig', function() {
],
};
onPropertiesUpdated.addExpectation(updateActiveInputDevice);
crosAudioConfig.setActiveDevice(fakeCrosAudioConfig.fakeBluetoothMic);
crosAudioConfig.setActiveDevice(fakeCrosAudioConfig.fakeBluetoothMic.id);

mockController.verifyMocks();
});
Expand Down
17 changes: 17 additions & 0 deletions chromeos/ash/components/audio/cros_audio_config_impl.cc
Expand Up @@ -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 {
Expand Down Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions chromeos/ash/components/audio/cros_audio_config_impl.h
Expand Up @@ -26,6 +26,7 @@ class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_AUDIO) CrosAudioConfigImpl
std::vector<mojom::AudioDevicePtr>* output_devices_out,
std::vector<mojom::AudioDevicePtr>* 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;
Expand Down
53 changes: 53 additions & 0 deletions chromeos/ash/components/audio/cros_audio_config_impl_unittest.cc
Expand Up @@ -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();
Expand Down Expand Up @@ -465,4 +470,52 @@ TEST_F(CrosAudioConfigImplTest, HandleExternalActiveInputDeviceUpdate) {
->is_active);
}

TEST_F(CrosAudioConfigImplTest, SetActiveOutputDevice) {
std::unique_ptr<FakeAudioSystemPropertiesObserver> 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<FakeAudioSystemPropertiesObserver> 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
Expand Up @@ -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);
};

0 comments on commit 0bc91aa

Please sign in to comment.