Commit 5e2d4287 authored by Chih-Yang Hsia's avatar Chih-Yang Hsia Committed by Chromium LUCI CQ

Add NumberOfInputStreamsWithPermission interfaces

Expose NumberOfInputStreamsWithPermission related APIs up to
CrasAudioHandler.

- Add CrasAudioHandler::ClientType enum class.
- Add OnNumberOfInputStreamsWithPermissionChanged to
  CrasAudioHandler::Observer.
- Add GetNumberOfInputStreamsWithPermission to CrasAudioHandler.

BUG=b:174336267
TEST=chromeos_unittests
TEST=Build and use input streams to trigger dbus from CRAS

Change-Id: Ia040a310e8e4604076ecc89018700d1d210f29d3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2579931Reviewed-by: default avatarJason Lin <lxj@google.com>
Reviewed-by: default avatarHsinyu Chao <hychao@chromium.org>
Commit-Queue: Chih-Yang Hsia <paulhsia@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836959}
parent 667dc36e
......@@ -96,6 +96,9 @@ void CrasAudioHandler::AudioObserver::OnBluetoothBatteryChanged(
const std::string& /* address */,
uint32_t /* level */) {}
void CrasAudioHandler::AudioObserver::
OnNumberOfInputStreamsWithPermissionChanged() {}
void CrasAudioHandler::AudioObserver::OnOutputStarted() {}
void CrasAudioHandler::AudioObserver::OnOutputStopped() {}
......@@ -415,6 +418,11 @@ const AudioDevice* CrasAudioHandler::GetDeviceByType(AudioDeviceType type) {
return nullptr;
}
base::flat_map<CrasAudioHandler::ClientType, uint32_t>
CrasAudioHandler::GetNumberOfInputStreamsWithPermission() const {
return number_of_input_streams_with_permission_;
}
void CrasAudioHandler::GetDefaultOutputBufferSize(int32_t* buffer_size) const {
*buffer_size = default_output_buffer_size_;
}
......@@ -858,6 +866,13 @@ void CrasAudioHandler::BluetoothBatteryChanged(const std::string& address,
observer.OnBluetoothBatteryChanged(address, level);
}
void CrasAudioHandler::NumberOfInputStreamsWithPermissionChanged(
const base::flat_map<std::string, uint32_t>& num_input_streams) {
HandleGetNumberOfInputStreamsWithPermission(num_input_streams);
for (auto& observer : observers_)
observer.OnNumberOfInputStreamsWithPermissionChanged();
}
void CrasAudioHandler::ResendBluetoothBattery() {
CrasAudioClient::Get()->ResendBluetoothBattery();
}
......@@ -1005,6 +1020,7 @@ void CrasAudioHandler::InitializeAudioAfterCrasServiceAvailable(
GetSystemAecGroupId();
GetNodes();
GetNumberOfOutputStreams();
GetNumberOfInputStreamsWithPermissionInternal();
CrasAudioClient::Get()->SetFixA2dpPacketSize(base::FeatureList::IsEnabled(
chromeos::features::kBluetoothFixA2dpPacketSize));
......@@ -1777,6 +1793,41 @@ bool CrasAudioHandler::HasExternalDevice(bool is_input) const {
return false;
}
void CrasAudioHandler::GetNumberOfInputStreamsWithPermissionInternal() {
CrasAudioClient::Get()->GetNumberOfInputStreamsWithPermission(base::BindOnce(
&CrasAudioHandler::HandleGetNumberOfInputStreamsWithPermission,
weak_ptr_factory_.GetWeakPtr()));
}
// static
CrasAudioHandler::ClientType CrasAudioHandler::ConvertClientTypeStringToEnum(
std::string client_type_str) {
if (client_type_str == "CRAS_CLIENT_TYPE_PLUGIN") {
return ClientType::VM_PLUGIN;
} else if (client_type_str == "CRAS_CLIENT_TYPE_CROSVM") {
return ClientType::VM_TERMINA;
} else if (client_type_str == "CRAS_CLIENT_TYPE_CHROME") {
return ClientType::CHROME;
} else if (client_type_str == "CRAS_CLIENT_TYPE_ARC") {
return ClientType::ARC;
} else {
return ClientType::UNKNOWN;
}
}
void CrasAudioHandler::HandleGetNumberOfInputStreamsWithPermission(
base::Optional<base::flat_map<std::string, uint32_t>> num_input_streams) {
if (!num_input_streams.has_value()) {
LOG(ERROR) << "Failed to retrieve number of input streams with permission";
return;
}
number_of_input_streams_with_permission_.clear();
for (const auto& it : *num_input_streams) {
number_of_input_streams_with_permission_[ConvertClientTypeStringToEnum(
it.first)] = it.second;
}
}
void CrasAudioHandler::GetDefaultOutputBufferSizeInternal() {
CrasAudioClient::Get()->GetDefaultOutputBufferSize(
base::BindOnce(&CrasAudioHandler::HandleGetDefaultOutputBufferSize,
......
......@@ -96,6 +96,10 @@ class COMPONENT_EXPORT(CHROMEOS_AUDIO) CrasAudioHandler
virtual void OnBluetoothBatteryChanged(const std::string& address,
uint32_t level);
// Called when the number of input streams with permission per client type
// changed.
virtual void OnNumberOfInputStreamsWithPermissionChanged();
// Called when an initial output stream is opened.
virtual void OnOutputStarted();
......@@ -115,6 +119,14 @@ class COMPONENT_EXPORT(CHROMEOS_AUDIO) CrasAudioHandler
ACTIVATE_BY_CAMERA
};
enum class ClientType {
CHROME = 0,
ARC,
VM_TERMINA,
VM_PLUGIN,
UNKNOWN,
};
// Sets the global instance. Must be called before any calls to Get().
static void Initialize(
mojo::PendingRemote<media_session::mojom::MediaControllerManager>
......@@ -207,6 +219,11 @@ class COMPONENT_EXPORT(CHROMEOS_AUDIO) CrasAudioHandler
// return the first one found.
const AudioDevice* GetDeviceByType(AudioDeviceType type);
// Returns a map contains number of input streams with permission per
// ClientType. If a ClientType is not in the map, we assume the number is 0.
base::flat_map<ClientType, uint32_t> GetNumberOfInputStreamsWithPermission()
const;
// Gets the default output buffer size in frames.
void GetDefaultOutputBufferSize(int32_t* buffer_size) const;
......@@ -346,6 +363,8 @@ class COMPONENT_EXPORT(CHROMEOS_AUDIO) CrasAudioHandler
void HotwordTriggered(uint64_t tv_sec, uint64_t tv_nsec) override;
void BluetoothBatteryChanged(const std::string& address,
uint32_t level) override;
void NumberOfInputStreamsWithPermissionChanged(
const base::flat_map<std::string, uint32_t>& num_input_streams) override;
void NumberOfActiveStreamsChanged() override;
// AudioPrefObserver overrides.
......@@ -542,6 +561,18 @@ class COMPONENT_EXPORT(CHROMEOS_AUDIO) CrasAudioHandler
// Handle dbus callback for GetDefaultOutputBufferSize.
void HandleGetDefaultOutputBufferSize(base::Optional<int> buffer_size);
// Calling dbus to get current number of input streams with permission and
// storing the result in number_of_input_streams_with_permission_.
void GetNumberOfInputStreamsWithPermissionInternal();
// Static function converts |client_type_str| to ClientType which used by
// HandleGetNumberOfInputStreamsWithPermission.
static ClientType ConvertClientTypeStringToEnum(std::string client_type_str);
// Handle dbus callback for GetNumberOfInputStreamsWithPermission.
void HandleGetNumberOfInputStreamsWithPermission(
base::Optional<base::flat_map<std::string, uint32_t>> num_input_streams);
// Calling dbus to get system AEC supported flag.
void GetSystemAecSupported();
......@@ -619,6 +650,8 @@ class COMPONENT_EXPORT(CHROMEOS_AUDIO) CrasAudioHandler
// Default output buffer size in frames.
int32_t default_output_buffer_size_ = 512;
base::flat_map<ClientType, uint32_t> number_of_input_streams_with_permission_;
bool system_aec_supported_ = false;
int32_t system_aec_group_id_ = kSystemAecGroupIdNotAvailable;
......
......@@ -107,6 +107,19 @@ class CrasAudioClientImpl : public CrasAudioClient {
base::BindOnce(&CrasAudioClientImpl::SignalConnected,
weak_ptr_factory_.GetWeakPtr()));
// Monitor the D-Bus signal for changes in number of input streams with
// permission per client type.
cras_proxy_->ConnectToSignal(
cras::kCrasControlInterface,
cras::kNumberOfInputStreamsWithPermissionChanged,
base::BindRepeating(
&CrasAudioClientImpl::NumberOfInputStreamsWithPermissionReceived,
weak_ptr_factory_.GetWeakPtr()),
base::BindOnce(&CrasAudioClientImpl::SignalConnected,
weak_ptr_factory_.GetWeakPtr())
);
// Monitor the D-Bus signal for changes in Bluetooth headset battery level.
cras_proxy_->ConnectToSignal(
cras::kCrasControlInterface, cras::kBluetoothBatteryChanged,
......@@ -187,6 +200,18 @@ class CrasAudioClientImpl : public CrasAudioClient {
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void GetNumberOfInputStreamsWithPermission(
DBusMethodCallback<base::flat_map<std::string, uint32_t>> callback)
override {
dbus::MethodCall method_call(cras::kCrasControlInterface,
cras::kGetNumberOfInputStreamsWithPermission);
cras_proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(
&CrasAudioClientImpl::OnGetNumberOfInputStreamsWithPermission,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void GetDeprioritizeBtWbsMic(DBusMethodCallback<bool> callback) override {
dbus::MethodCall method_call(cras::kCrasControlInterface,
cras::kGetDeprioritizeBtWbsMic);
......@@ -534,6 +559,30 @@ class CrasAudioClientImpl : public CrasAudioClient {
observer.NumberOfActiveStreamsChanged();
}
void NumberOfInputStreamsWithPermissionReceived(dbus::Signal* signal) {
dbus::MessageReader signal_reader(signal);
dbus::MessageReader array_reader(nullptr);
base::flat_map<std::string, uint32_t> res;
while (signal_reader.HasMoreData()) {
if (!signal_reader.PopArray(&array_reader)) {
LOG(ERROR) << "Error reading signal from cras: " << signal->ToString();
return;
}
std::string client_type;
uint32_t num_input_streams;
if (!GetNumerInputStreams(&array_reader, &client_type,
&num_input_streams)) {
LOG(ERROR) << "Error reading number of input streams from cras: "
<< signal->ToString();
return;
}
res[client_type] = num_input_streams;
}
for (auto& observer : observers_)
observer.NumberOfInputStreamsWithPermissionChanged(res);
}
void BluetoothBatteryChangedReceived(dbus::Signal* signal) {
dbus::MessageReader reader(signal);
std::string address;
......@@ -686,6 +735,64 @@ class CrasAudioClientImpl : public CrasAudioClient {
std::move(callback).Run(num_active_streams);
}
bool GetNumerInputStreams(dbus::MessageReader* array_reader,
std::string* client_type,
uint32_t* num_input_streams) {
while (array_reader->HasMoreData()) {
dbus::MessageReader dict_entry_reader(nullptr);
dbus::MessageReader value_reader(nullptr);
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::kClientType) {
if (!value_reader.PopString(client_type))
return false;
} else if (key == cras::kNumStreamsWithPermission) {
if (!value_reader.PopUint32(num_input_streams))
return false;
}
}
return true;
}
void OnGetNumberOfInputStreamsWithPermission(
DBusMethodCallback<base::flat_map<std::string, uint32_t>> callback,
dbus::Response* response) {
if (!response) {
LOG(ERROR) << "Error calling "
<< cras::kGetNumberOfInputStreamsWithPermission;
std::move(callback).Run(base::nullopt);
return;
}
dbus::MessageReader response_reader(response);
dbus::MessageReader array_reader(nullptr);
base::flat_map<std::string, uint32_t> res;
while (response_reader.HasMoreData()) {
if (!response_reader.PopArray(&array_reader)) {
LOG(ERROR) << "Error reading response from cras: "
<< response->ToString();
std::move(callback).Run(base::nullopt);
return;
}
std::string client_type;
uint32_t num_input_streams;
if (!GetNumerInputStreams(&array_reader, &client_type,
&num_input_streams)) {
LOG(ERROR) << "Error reading number of input streams from cras: "
<< response->ToString();
std::move(callback).Run(base::nullopt);
return;
}
res[client_type] = num_input_streams;
}
std::move(callback).Run(std::move(res));
}
void OnGetDeprioritizeBtWbsMic(DBusMethodCallback<bool> callback,
dbus::Response* response) {
if (!response) {
......@@ -818,6 +925,9 @@ void CrasAudioClient::Observer::BluetoothBatteryChanged(
const std::string& address,
uint32_t level) {}
void CrasAudioClient::Observer::NumberOfInputStreamsWithPermissionChanged(
const base::flat_map<std::string, uint32_t>& num_input_streams) {}
CrasAudioClient::CrasAudioClient() {
DCHECK(!g_instance);
g_instance = this;
......
......@@ -12,6 +12,7 @@
#include "base/callback.h"
#include "base/component_export.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "chromeos/dbus/audio/audio_node.h"
......@@ -62,6 +63,11 @@ class COMPONENT_EXPORT(DBUS_AUDIO) CrasAudioClient {
virtual void BluetoothBatteryChanged(const std::string& address,
uint32_t level);
// Called when the number of input streams with permission per client type
// changed.
virtual void NumberOfInputStreamsWithPermissionChanged(
const base::flat_map<std::string, uint32_t>& num_input_streams);
protected:
virtual ~Observer();
};
......@@ -103,6 +109,10 @@ class COMPONENT_EXPORT(DBUS_AUDIO) CrasAudioClient {
virtual void GetNumberOfActiveOutputStreams(
DBusMethodCallback<int> callback) = 0;
// Gets the number of input streams with permission per client type.
virtual void GetNumberOfInputStreamsWithPermission(
DBusMethodCallback<base::flat_map<std::string, uint32_t>>) = 0;
// Gets the DeprioritzeBtWbsMic flag. On a few platforms CRAS may
// report to deprioritize Bluetooth WBS mic's node priority because
// WBS feature is still working to be stabilized.
......
......@@ -101,6 +101,9 @@ class MockObserver : public CrasAudioClient::Observer {
MOCK_METHOD2(OutputNodeVolumeChanged, void(uint64_t node_id, int volume));
MOCK_METHOD2(HotwordTriggered, void(uint64_t tv_sec, uint64_t tv_nsec));
MOCK_METHOD0(NumberOfActiveStreamsChanged, void());
MOCK_METHOD1(
NumberOfInputStreamsWithPermissionChanged,
void(const base::flat_map<std::string, uint32_t>& num_input_streams));
MOCK_METHOD2(BluetoothBatteryChanged,
void(const std::string& address, uint32_t level));
};
......@@ -414,6 +417,17 @@ class CrasAudioClientTest : public testing::Test {
.WillRepeatedly(
Invoke(this, &CrasAudioClientTest::OnNumberOfActiveStreamsChanged));
// Set and expectation so mock_cras_proxy's monitoring
// NumberOfInputStreamsWithPermissionChanged ConnectToSignal will use
// OnNumberOfInputStreamsWithPermissionChanged to run the callback.
EXPECT_CALL(*mock_cras_proxy_.get(),
DoConnectToSignal(
interface_name_,
cras::kNumberOfInputStreamsWithPermissionChanged, _, _))
.WillRepeatedly(Invoke(
this,
&CrasAudioClientTest::OnNumberOfInputStreamsWithPermissionChanged));
// Set an expectation so mock_cras_proxy's monitoring
// BluetoothBatteryChanged ConnectToSignal will use
// OnBluetoothBatteryChanged() to run the callback.
......@@ -506,6 +520,15 @@ class CrasAudioClientTest : public testing::Test {
number_of_active_streams_changed_handler_.Run(signal);
}
// Send number-of-input-streams-with-permission-changed signal to the tested
// client.
void SendNumberOfInputStreamsWithPermissionChangedSignal(
dbus::Signal* signal) {
ASSERT_FALSE(
number_of_input_streams_with_permission_changed_handler_.is_null());
number_of_input_streams_with_permission_changed_handler_.Run(signal);
}
// Send Bluetooth battery changed signal to the tested client.
void SendBluetoothBatteryChangedSignal(dbus::Signal* signal) {
ASSERT_FALSE(bluetooth_battery_changed_handler_.is_null());
......@@ -539,6 +562,10 @@ class CrasAudioClientTest : public testing::Test {
dbus::ObjectProxy::SignalCallback hotword_triggered_handler_;
// The NumberOfActiveStreamsChanged signal handler given by the tested client.
dbus::ObjectProxy::SignalCallback number_of_active_streams_changed_handler_;
// The NumberOfInputStreamsWithPermissionChanged signal handler given by the
// tested client.
dbus::ObjectProxy::SignalCallback
number_of_input_streams_with_permission_changed_handler_;
// The BluetoothBatteryChanged signal handler given by the tested client.
dbus::ObjectProxy::SignalCallback bluetooth_battery_changed_handler_;
// The name of the method which is expected to be called.
......@@ -661,6 +688,18 @@ class CrasAudioClientTest : public testing::Test {
interface_name, signal_name, success));
}
void OnNumberOfInputStreamsWithPermissionChanged(
const std::string& interface_name,
const std::string& signal_name,
const dbus::ObjectProxy::SignalCallback& signal_callback,
dbus::ObjectProxy::OnConnectedCallback* on_connected_callback) {
number_of_input_streams_with_permission_changed_handler_ = signal_callback;
const bool success = true;
task_environment_.GetMainThreadTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(std::move(*on_connected_callback),
interface_name, signal_name, success));
}
// Checks the requested interface name and signal name.
// Used to implement the mock cras proxy.
void OnBluetoothBatteryChanged(
......@@ -805,6 +844,48 @@ TEST_F(CrasAudioClientTest, NumberOfActiveStreamsChanged) {
base::RunLoop().RunUntilIdle();
}
TEST_F(CrasAudioClientTest, NumberOfInputStreamsWithPermissionChanged) {
dbus::Signal signal(cras::kCrasControlInterface,
cras::kNumberOfInputStreamsWithPermissionChanged);
dbus::MessageWriter writer(&signal);
base::flat_map<std::string, uint32_t> num_input_streams = {
{"CRAS_CLIENT_TYPE_CHROME", 1}, {"CRAS_CLIENT_TYPE_CROSVM", 0}};
for (auto& it : num_input_streams) {
dbus::MessageWriter sub_writer(nullptr);
dbus::MessageWriter entry_writer(nullptr);
writer.OpenArray("{sv}", &sub_writer);
sub_writer.OpenDictEntry(&entry_writer);
entry_writer.AppendString(cras::kClientType);
entry_writer.AppendVariantOfString(it.first);
sub_writer.CloseContainer(&entry_writer);
sub_writer.OpenDictEntry(&entry_writer);
entry_writer.AppendString(cras::kNumStreamsWithPermission);
entry_writer.AppendVariantOfUint32(it.second);
sub_writer.CloseContainer(&entry_writer);
writer.CloseContainer(&sub_writer);
}
MockObserver observer;
EXPECT_CALL(observer,
NumberOfInputStreamsWithPermissionChanged(num_input_streams))
.Times(1);
client()->AddObserver(&observer);
SendNumberOfInputStreamsWithPermissionChangedSignal(&signal);
client()->RemoveObserver(&observer);
EXPECT_CALL(observer,
NumberOfInputStreamsWithPermissionChanged(num_input_streams))
.Times(0);
// Run the signal callback again and make sure the observer isn't called.
SendNumberOfInputStreamsWithPermissionChangedSignal(&signal);
base::RunLoop().RunUntilIdle();
}
TEST_F(CrasAudioClientTest, BluetoothBatteryChanged) {
const std::string address = "11:22:33:44:55:66";
const uint32_t level = 82;
......
......@@ -149,6 +149,12 @@ void FakeCrasAudioClient::GetNumberOfActiveOutputStreams(
std::move(callback).Run(0);
}
void FakeCrasAudioClient::GetNumberOfInputStreamsWithPermission(
DBusMethodCallback<base::flat_map<std::string, uint32_t>> callback) {
base::flat_map<std::string, uint32_t> res;
std::move(callback).Run(std::move(res));
}
void FakeCrasAudioClient::GetDeprioritizeBtWbsMic(
DBusMethodCallback<bool> callback) {
std::move(callback).Run(base::nullopt);
......
......@@ -35,6 +35,8 @@ class COMPONENT_EXPORT(DBUS_AUDIO) FakeCrasAudioClient
void GetNodes(DBusMethodCallback<AudioNodeList> callback) override;
void GetNumberOfActiveOutputStreams(
DBusMethodCallback<int> callback) override;
void GetNumberOfInputStreamsWithPermission(
DBusMethodCallback<base::flat_map<std::string, uint32_t>>) override;
void GetDeprioritizeBtWbsMic(DBusMethodCallback<bool> callback) override;
void SetOutputNodeVolume(uint64_t node_id, int32_t volume) override;
void SetOutputUserMute(bool mute_on) override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment