Commit b8ae756e authored by Jeroen Dhollander's avatar Jeroen Dhollander Committed by Commit Bot

Cleanup handling of |device.MODIFY_SETTING| requests

Previously this was all done in the |AssistantManagerServiceImpl|,
but that class is already huge.

To solve this I made the following changes:
   * split it out in a separate |AssistantDeviceSettingsDelegate| class.
   * Introduce helper |Setting| classes, 1 for each supported setting.
   * Add unittests for each of the supported settings.

Bug: N/A
Change-Id: Ia32aecb15e3200a183c72ad8e5bcfcd3b2b4dfbc
Tests: new |chromeos_unittests| with filter |AssistantDeviceSettingsDelegateTest.*|
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2147693
Commit-Queue: Jeroen Dhollander <jeroendh@google.com>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#761041}
parent ab64521d
...@@ -60,6 +60,8 @@ component("lib") { ...@@ -60,6 +60,8 @@ component("lib") {
if (enable_cros_libassistant) { if (enable_cros_libassistant) {
sources += [ sources += [
"assistant_device_settings_delegate.cc",
"assistant_device_settings_delegate.h",
"assistant_manager_service_delegate.h", "assistant_manager_service_delegate.h",
"assistant_manager_service_delegate_impl.cc", "assistant_manager_service_delegate_impl.cc",
"assistant_manager_service_delegate_impl.h", "assistant_manager_service_delegate_impl.h",
...@@ -163,6 +165,7 @@ source_set("tests") { ...@@ -163,6 +165,7 @@ source_set("tests") {
if (enable_cros_libassistant) { if (enable_cros_libassistant) {
sources += [ sources += [
"assistant_device_settings_delegate_unittest.cc",
"assistant_manager_service_impl_unittest.cc", "assistant_manager_service_impl_unittest.cc",
"media_session/assistant_media_session_unittest.cc", "media_session/assistant_media_session_unittest.cc",
"platform/audio_input_impl_unittest.cc", "platform/audio_input_impl_unittest.cc",
...@@ -174,6 +177,8 @@ source_set("tests") { ...@@ -174,6 +177,8 @@ source_set("tests") {
"test_support/fake_assistant_manager_service_delegate.h", "test_support/fake_assistant_manager_service_delegate.h",
"test_support/fake_platform_api.cc", "test_support/fake_platform_api.cc",
"test_support/fake_platform_api.h", "test_support/fake_platform_api.h",
"test_support/fake_service_context.cc",
"test_support/fake_service_context.h",
"test_support/mock_assistant_interaction_subscriber.cc", "test_support/mock_assistant_interaction_subscriber.cc",
"test_support/mock_assistant_interaction_subscriber.h", "test_support/mock_assistant_interaction_subscriber.h",
"test_support/mock_media_manager.cc", "test_support/mock_media_manager.cc",
......
// Copyright 2020 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/services/assistant/assistant_device_settings_delegate.h"
#include <algorithm>
#include <memory>
#include <utility>
#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/assistant/internal/internal_util.h"
#include "chromeos/assistant/internal/proto/google3/assistant/api/client_op/device_args.pb.h"
#include "chromeos/services/assistant/cros_platform_api.h"
#include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
#include "chromeos/services/assistant/service_context.h"
#include "libassistant/shared/public/platform_audio_output.h"
#include "ui/accessibility/accessibility_switches.h"
namespace client_op = ::assistant::api::client_op;
namespace chromeos {
namespace assistant {
class Setting {
public:
Setting() = default;
Setting(Setting&) = delete;
Setting& operator=(Setting&) = delete;
virtual ~Setting() = default;
virtual const char* setting_id() const = 0;
virtual void Modify(const client_op::ModifySettingArgs& request) = 0;
};
namespace {
constexpr char kWiFiDeviceSettingId[] = "WIFI";
constexpr char kBluetoothDeviceSettingId[] = "BLUETOOTH";
constexpr char kVolumeLevelDeviceSettingId[] = "VOLUME_LEVEL";
constexpr char kScreenBrightnessDeviceSettingId[] = "BRIGHTNESS_LEVEL";
constexpr char kDoNotDisturbDeviceSettingId[] = "DO_NOT_DISTURB";
constexpr char kNightLightDeviceSettingId[] = "NIGHT_LIGHT_SWITCH";
constexpr char kSwitchAccessDeviceSettingId[] = "SWITCH_ACCESS";
constexpr float kDefaultSliderStep = 0.1f;
void LogUnsupportedChange(client_op::ModifySettingArgs args) {
LOG(ERROR) << "Unsupported change operation: " << args.change()
<< " for setting " << args.setting_id();
}
void HandleOnOffChange(client_op::ModifySettingArgs modify_setting_args,
std::function<void(bool)> on_off_handler) {
switch (modify_setting_args.change()) {
case client_op::ModifySettingArgs_Change_ON:
on_off_handler(true);
return;
case client_op::ModifySettingArgs_Change_OFF:
on_off_handler(false);
return;
// Currently there are no use-cases for toggling. This could change in the
// future.
case client_op::ModifySettingArgs_Change_TOGGLE:
break;
case client_op::ModifySettingArgs_Change_SET:
case client_op::ModifySettingArgs_Change_INCREASE:
case client_op::ModifySettingArgs_Change_DECREASE:
case client_op::ModifySettingArgs_Change_UNSPECIFIED:
// This shouldn't happen.
break;
}
LogUnsupportedChange(modify_setting_args);
}
// Helper function that converts a slider value sent from the server, either
// absolute or a delta, from a given unit (e.g., STEP), to a percentage.
double ConvertSliderValueToLevel(double value,
client_op::ModifySettingArgs_Unit unit,
double default_value) {
switch (unit) {
case client_op::ModifySettingArgs_Unit_RANGE:
// "set volume to 20%".
return value;
case client_op::ModifySettingArgs_Unit_STEP:
// "set volume to 20". Treat the step as a percentage.
return value / 100.0f;
// Currently, factor (e.g., 'double the volume') and decibel units aren't
// handled by the backend. This could change in the future.
case client_op::ModifySettingArgs_Unit_FACTOR:
case client_op::ModifySettingArgs_Unit_DECIBEL:
break;
case client_op::ModifySettingArgs_Unit_NATIVE:
case client_op::ModifySettingArgs_Unit_UNKNOWN_UNIT:
// This shouldn't happen.
break;
}
LOG(ERROR) << "Unsupported slider unit: " << unit;
return default_value;
}
void HandleSliderChange(client_op::ModifySettingArgs request,
std::function<void(double)> set_value_handler,
std::function<double()> get_value_handler) {
switch (request.change()) {
case client_op::ModifySettingArgs_Change_SET: {
// For unsupported units, set the value to the current value, for
// visual feedback.
double new_value = ConvertSliderValueToLevel(
request.numeric_value(), request.unit(), get_value_handler());
set_value_handler(new_value);
return;
}
case client_op::ModifySettingArgs_Change_INCREASE:
case client_op::ModifySettingArgs_Change_DECREASE: {
double current_value = get_value_handler();
double step = kDefaultSliderStep;
if (request.numeric_value() != 0.0f) {
// For unsupported units, use the default step percentage.
step = ConvertSliderValueToLevel(request.numeric_value(),
request.unit(), kDefaultSliderStep);
}
double new_value =
(request.change() == client_op::ModifySettingArgs_Change_INCREASE)
? std::min(current_value + step, 1.0)
: std::max(current_value - step, 0.0);
set_value_handler(new_value);
return;
}
case client_op::ModifySettingArgs_Change_ON:
case client_op::ModifySettingArgs_Change_OFF:
case client_op::ModifySettingArgs_Change_TOGGLE:
case client_op::ModifySettingArgs_Change_UNSPECIFIED:
// This shouldn't happen.
break;
}
LogUnsupportedChange(request);
}
class SettingWithDeviceAction : public Setting {
public:
explicit SettingWithDeviceAction(ServiceContext* context)
: context_(context) {}
mojom::DeviceActions* device_actions() { return context_->device_actions(); }
private:
ServiceContext* context_;
};
class WifiSetting : public SettingWithDeviceAction {
public:
using SettingWithDeviceAction::SettingWithDeviceAction;
const char* setting_id() const override { return kWiFiDeviceSettingId; }
void Modify(const client_op::ModifySettingArgs& request) override {
HandleOnOffChange(request, [&](bool enabled) {
this->device_actions()->SetWifiEnabled(enabled);
});
}
};
class BluetoothSetting : public SettingWithDeviceAction {
public:
using SettingWithDeviceAction::SettingWithDeviceAction;
const char* setting_id() const override { return kBluetoothDeviceSettingId; }
void Modify(const client_op::ModifySettingArgs& request) override {
HandleOnOffChange(request, [&](bool enabled) {
this->device_actions()->SetBluetoothEnabled(enabled);
});
}
};
class DoNotDisturbSetting : public Setting {
public:
explicit DoNotDisturbSetting(
ash::mojom::AssistantNotificationController* controller)
: assistant_notification_controller_(controller) {}
const char* setting_id() const override {
return kDoNotDisturbDeviceSettingId;
}
void Modify(const client_op::ModifySettingArgs& request) override {
HandleOnOffChange(request, [&](bool enabled) {
this->assistant_notification_controller_->SetQuietMode(enabled);
});
}
private:
ash::mojom::AssistantNotificationController* const
assistant_notification_controller_;
};
class SwitchAccessSetting : public SettingWithDeviceAction {
public:
using SettingWithDeviceAction::SettingWithDeviceAction;
const char* setting_id() const override {
return kSwitchAccessDeviceSettingId;
}
void Modify(const client_op::ModifySettingArgs& request) override {
HandleOnOffChange(request, [&](bool enabled) {
this->device_actions()->SetSwitchAccessEnabled(enabled);
});
}
};
class NightLightSetting : public SettingWithDeviceAction {
public:
using SettingWithDeviceAction::SettingWithDeviceAction;
const char* setting_id() const override { return kNightLightDeviceSettingId; }
void Modify(const client_op::ModifySettingArgs& request) override {
HandleOnOffChange(request, [&](bool enabled) {
this->device_actions()->SetNightLightEnabled(enabled);
});
}
};
class VolumeSetting : public Setting {
public:
explicit VolumeSetting(assistant_client::VolumeControl* volume_control)
: volume_control_(volume_control) {}
const char* setting_id() const override {
return kVolumeLevelDeviceSettingId;
}
void Modify(const client_op::ModifySettingArgs& request) override {
DCHECK(volume_control_ != nullptr);
HandleSliderChange(
request,
[this](double value) {
this->volume_control_->SetSystemVolume(value, true);
},
[this]() { return this->volume_control_->GetSystemVolume(); });
}
private:
assistant_client::VolumeControl* const volume_control_;
};
class BrightnessSetting : public SettingWithDeviceAction {
public:
explicit BrightnessSetting(ServiceContext* context)
: SettingWithDeviceAction(context), weak_factory_(this) {}
const char* setting_id() const override {
return kScreenBrightnessDeviceSettingId;
}
void Modify(const client_op::ModifySettingArgs& request) override {
device_actions()->GetScreenBrightnessLevel(base::BindOnce(
[](base::WeakPtr<BrightnessSetting> this_,
client_op::ModifySettingArgs request, bool success,
double current_value) {
if (!success || !this_) {
return;
}
HandleSliderChange(
request,
[&this_](double new_value) {
this_->device_actions()->SetScreenBrightnessLevel(new_value,
true);
},
[current_value]() { return current_value; });
},
weak_factory_.GetWeakPtr(), request));
}
private:
base::WeakPtrFactory<BrightnessSetting> weak_factory_;
};
} // namespace
AssistantDeviceSettingsDelegate::AssistantDeviceSettingsDelegate(
ServiceContext* context,
assistant_client::VolumeControl* volume_control) {
AddSetting(std::make_unique<WifiSetting>(context));
AddSetting(std::make_unique<BluetoothSetting>(context));
AddSetting(std::make_unique<NightLightSetting>(context));
AddSetting(std::make_unique<DoNotDisturbSetting>(
context->assistant_notification_controller()));
AddSetting(std::make_unique<VolumeSetting>(volume_control));
AddSetting(std::make_unique<BrightnessSetting>(context));
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kEnableExperimentalAccessibilitySwitchAccess)) {
AddSetting(std::make_unique<SwitchAccessSetting>(context));
}
}
AssistantDeviceSettingsDelegate::~AssistantDeviceSettingsDelegate() = default;
bool AssistantDeviceSettingsDelegate::IsSettingSupported(
const std::string& setting_id) const {
return std::any_of(settings_.begin(), settings_.end(),
[&setting_id](const auto& setting) {
return setting->setting_id() == setting_id;
});
}
void AssistantDeviceSettingsDelegate::HandleModifyDeviceSetting(
const client_op::ModifySettingArgs& modify_setting_args) {
DCHECK(IsSettingSupported(modify_setting_args.setting_id()));
for (const auto& setting : settings_) {
if (setting->setting_id() == modify_setting_args.setting_id()) {
setting->Modify(modify_setting_args);
return;
}
}
NOTREACHED();
}
std::vector<DeviceSetting> AssistantDeviceSettingsDelegate::GetDeviceSettings(
const ::assistant::api::client_op::GetDeviceSettingsArgs& args) const {
std::vector<DeviceSetting> result;
for (const std::string& setting_id : args.setting_ids())
result.emplace_back(setting_id, IsSettingSupported(setting_id));
return result;
}
void AssistantDeviceSettingsDelegate::AddSetting(
std::unique_ptr<Setting> setting) {
settings_.push_back(std::move(setting));
}
} // namespace assistant
} // namespace chromeos
// Copyright 2020 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_SERVICES_ASSISTANT_ASSISTANT_DEVICE_SETTINGS_DELEGATE_H_
#define CHROMEOS_SERVICES_ASSISTANT_ASSISTANT_DEVICE_SETTINGS_DELEGATE_H_
#include <memory>
#include <string>
#include <vector>
#include "ash/public/mojom/assistant_controller.mojom-forward.h"
#include "chromeos/services/assistant/public/mojom/assistant.mojom-forward.h"
namespace assistant_client {
class VolumeControl;
} // namespace assistant_client
namespace assistant {
namespace api {
namespace client_op {
class ModifySettingArgs;
class GetDeviceSettingsArgs;
} // namespace client_op
} // namespace api
} // namespace assistant
namespace chromeos {
namespace assistant {
struct DeviceSetting;
class ServiceContext;
class Setting;
// Delegate that handles Assistant actions related to retrieving/modifying
// the device settings, like Bluetooth or WiFi.
class AssistantDeviceSettingsDelegate {
public:
explicit AssistantDeviceSettingsDelegate(
ServiceContext* context,
assistant_client::VolumeControl* volume_control);
AssistantDeviceSettingsDelegate(AssistantDeviceSettingsDelegate&) = delete;
AssistantDeviceSettingsDelegate& operator=(AssistantDeviceSettingsDelegate&) =
delete;
~AssistantDeviceSettingsDelegate();
bool IsSettingSupported(const std::string& setting_id) const;
void HandleModifyDeviceSetting(
const ::assistant::api::client_op::ModifySettingArgs& args);
// Return which of the given device settings are supported or not.
std::vector<DeviceSetting> GetDeviceSettings(
const ::assistant::api::client_op::GetDeviceSettingsArgs& args) const;
private:
void AddSetting(std::unique_ptr<Setting> setting);
std::vector<std::unique_ptr<Setting>> settings_;
};
} // namespace assistant
} // namespace chromeos
#endif // CHROMEOS_SERVICES_ASSISTANT_ASSISTANT_DEVICE_SETTINGS_DELEGATE_H_
// Copyright 2020 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/services/assistant/assistant_device_settings_delegate.h"
#include <memory>
#include <utility>
#include "base/command_line.h"
#include "chromeos/assistant/internal/internal_util.h"
#include "chromeos/assistant/internal/proto/google3/assistant/api/client_op/device_args.pb.h"
#include "chromeos/services/assistant/test_support/fake_service_context.h"
#include "libassistant/shared/public/platform_audio_output.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/accessibility_switches.h"
namespace chromeos {
namespace assistant {
namespace {
constexpr double kEpsilon = 0.001;
using ::assistant::api::client_op::GetDeviceSettingsArgs;
using ::assistant::api::client_op::ModifySettingArgs;
using Change = ::assistant::api::client_op::ModifySettingArgs::Change;
using Unit = ::assistant::api::client_op::ModifySettingArgs::Unit;
using ::testing::AnyNumber;
using ::testing::DoubleNear;
using ::testing::ElementsAre;
using ::testing::FloatNear;
using ::testing::Return;
using ::testing::StrictMock;
constexpr char kWiFi[] = "WIFI";
constexpr char kBluetooth[] = "BLUETOOTH";
constexpr char kVolumeLevel[] = "VOLUME_LEVEL";
constexpr char kScreenBrightness[] = "BRIGHTNESS_LEVEL";
constexpr char kDoNotDisturb[] = "DO_NOT_DISTURB";
constexpr char kNightLight[] = "NIGHT_LIGHT_SWITCH";
constexpr char kSwitchAccess[] = "SWITCH_ACCESS";
// Returns the settings that are always supported.
// Does not contain |SWITCH_ACCESS| as that is conditionally supported.
const std::vector<std::string> kAlwaysSupportedSettings = {
kWiFi, kBluetooth, kVolumeLevel, kScreenBrightness,
kDoNotDisturb, kNightLight,
};
class DeviceActionsMock : public mojom::DeviceActions {
public:
// mojom::DeviceActions implementation:
MOCK_METHOD(void, SetWifiEnabled, (bool enabled));
MOCK_METHOD(void, SetBluetoothEnabled, (bool enabled));
MOCK_METHOD(void, SetScreenBrightnessLevel, (double level, bool gradual));
MOCK_METHOD(void, SetNightLightEnabled, (bool enabled));
MOCK_METHOD(void, SetSwitchAccessEnabled, (bool enabled));
MOCK_METHOD(void,
OpenAndroidApp,
(chromeos::assistant::mojom::AndroidAppInfoPtr app_info,
OpenAndroidAppCallback callback));
MOCK_METHOD(
void,
VerifyAndroidApp,
(std::vector<chromeos::assistant::mojom::AndroidAppInfoPtr> apps_info,
VerifyAndroidAppCallback callback));
MOCK_METHOD(void, LaunchAndroidIntent, (const std::string& intent));
MOCK_METHOD(
void,
AddAppListEventSubscriber,
(mojo::PendingRemote<chromeos::assistant::mojom::AppListEventSubscriber>
subscriber));
void GetScreenBrightnessLevel(
GetScreenBrightnessLevelCallback callback) override {
std::move(callback).Run(/*success=*/true, current_brightness_);
}
// Set the brightness value that will be returned by
// GetScreenBrightnessLevel();
void set_current_brightness(double value) { current_brightness_ = value; }
private:
double current_brightness_ = 0.0;
};
class VolumeControlMock : public assistant_client::VolumeControl {
public:
MOCK_METHOD(void, SetAudioFocus, (assistant_client::OutputStreamType));
MOCK_METHOD(float, GetSystemVolume, ());
MOCK_METHOD(void, SetSystemVolume, (float new_volume, bool user_initiated));
MOCK_METHOD(float, GetAlarmVolume, ());
MOCK_METHOD(void, SetAlarmVolume, (float new_volume, bool user_initiated));
MOCK_METHOD(bool, IsSystemMuted, ());
MOCK_METHOD(void, SetSystemMuted, (bool muted));
};
class AssistantNotificationControllerMock
: public ash::mojom::AssistantNotificationController {
public:
using AssistantNotificationPtr =
chromeos::assistant::mojom::AssistantNotificationPtr;
// ash::mojom::AssistantNotificationController implementation:
MOCK_METHOD(void,
AddOrUpdateNotification,
(AssistantNotificationPtr notification));
MOCK_METHOD(void,
RemoveNotificationById,
(const std::string& id, bool from_server));
MOCK_METHOD(void,
RemoveNotificationByGroupingKey,
(const std::string& grouping_id, bool from_server));
MOCK_METHOD(void, RemoveAllNotifications, (bool from_server));
MOCK_METHOD(void, SetQuietMode, (bool enabled));
};
class AssistantDeviceSettingsDelegateTest : public testing::Test {
public:
AssistantDeviceSettingsDelegateTest() = default;
void SetUp() override {
service_context_ = std::make_unique<FakeServiceContext>();
CreateAssistantDeviceSettingsDelegate();
}
DeviceSetting GetDeviceSettings(const std::string& setting_id) {
GetDeviceSettingsArgs args;
args.add_setting_ids(setting_id);
std::vector<DeviceSetting> result = delegate()->GetDeviceSettings(args);
EXPECT_EQ(result.size(), 1u);
return result[0];
}
// Warning: Use |CreateAssistantDeviceSettingsDelegate| to apply any changes
// made to the service context.
FakeServiceContext* service_context() { return service_context_.get(); }
AssistantDeviceSettingsDelegate* delegate() { return delegate_.get(); }
void CreateAssistantDeviceSettingsDelegate(
assistant_client::VolumeControl* volume_control = nullptr) {
delegate_ = std::make_unique<AssistantDeviceSettingsDelegate>(
service_context_.get(), volume_control);
}
private:
std::unique_ptr<FakeServiceContext> service_context_;
std::unique_ptr<AssistantDeviceSettingsDelegate> delegate_;
};
} // namespace
bool operator==(const DeviceSetting& left, const DeviceSetting& right) {
return (left.is_supported == right.is_supported) &&
(left.setting_id == right.setting_id);
}
std::ostream& operator<<(std::ostream& stream, const DeviceSetting& value) {
stream << "{ " << value.setting_id << ": " << value.is_supported << "}";
return stream;
}
TEST_F(AssistantDeviceSettingsDelegateTest,
IsSettingSupportedShouldReturnFalseForUnknownSetting) {
EXPECT_FALSE(delegate()->IsSettingSupported("<unknown-setting>"));
}
TEST_F(AssistantDeviceSettingsDelegateTest,
IsSettingSupportedShouldReturnTrueForKnownSettings) {
for (const std::string& setting : kAlwaysSupportedSettings) {
EXPECT_TRUE(delegate()->IsSettingSupported(setting))
<< "Error for " << setting;
}
}
TEST_F(AssistantDeviceSettingsDelegateTest,
IsSettingSupportedShouldConditionallySupportSwitchAccess) {
auto* command_line = base::CommandLine::ForCurrentProcess();
command_line->RemoveSwitch(
::switches::kEnableExperimentalAccessibilitySwitchAccess);
CreateAssistantDeviceSettingsDelegate();
EXPECT_FALSE(delegate()->IsSettingSupported(kSwitchAccess));
command_line->AppendSwitch(
::switches::kEnableExperimentalAccessibilitySwitchAccess);
CreateAssistantDeviceSettingsDelegate();
EXPECT_TRUE(delegate()->IsSettingSupported(kSwitchAccess));
}
TEST_F(AssistantDeviceSettingsDelegateTest,
GetDeviceSettingsShouldReturnFalseForUnknownSetting) {
EXPECT_EQ(GetDeviceSettings("UNKNOWN_SETTING"),
DeviceSetting("UNKNOWN_SETTING", false));
}
TEST_F(AssistantDeviceSettingsDelegateTest,
GetDeviceSettingsShouldReturnTrueForKnownSettings) {
for (const std::string& setting : kAlwaysSupportedSettings) {
EXPECT_EQ(GetDeviceSettings(setting), DeviceSetting(setting, true))
<< "Error for " << setting;
}
}
TEST_F(AssistantDeviceSettingsDelegateTest,
GetDeviceSettingsShouldMultipleSettingsAtTheSameTime) {
GetDeviceSettingsArgs args;
args.add_setting_ids("UNKNOWN_SETTING");
args.add_setting_ids(kWiFi);
std::vector<DeviceSetting> result = delegate()->GetDeviceSettings(args);
EXPECT_THAT(delegate()->GetDeviceSettings(args),
ElementsAre(DeviceSetting("UNKNOWN_SETTING", false),
DeviceSetting(kWiFi, true)));
}
TEST_F(AssistantDeviceSettingsDelegateTest, ShouldTurnWifiOnAndOff) {
StrictMock<DeviceActionsMock> device_actions;
service_context()->set_device_actions(&device_actions);
CreateAssistantDeviceSettingsDelegate();
ModifySettingArgs args;
args.set_setting_id(kWiFi);
args.set_change(Change::ModifySettingArgs_Change_ON);
EXPECT_CALL(device_actions, SetWifiEnabled(true));
delegate()->HandleModifyDeviceSetting(args);
args.set_change(Change::ModifySettingArgs_Change_OFF);
EXPECT_CALL(device_actions, SetWifiEnabled(false));
delegate()->HandleModifyDeviceSetting(args);
}
TEST_F(AssistantDeviceSettingsDelegateTest, ShouldTurnBluetoothOnAndOff) {
StrictMock<DeviceActionsMock> device_actions;
service_context()->set_device_actions(&device_actions);
CreateAssistantDeviceSettingsDelegate();
ModifySettingArgs args;
args.set_setting_id(kBluetooth);
args.set_change(Change::ModifySettingArgs_Change_ON);
EXPECT_CALL(device_actions, SetBluetoothEnabled(true));
delegate()->HandleModifyDeviceSetting(args);
args.set_change(Change::ModifySettingArgs_Change_OFF);
EXPECT_CALL(device_actions, SetBluetoothEnabled(false));
delegate()->HandleModifyDeviceSetting(args);
}
TEST_F(AssistantDeviceSettingsDelegateTest, ShouldTurnQuietModeOnAndOff) {
StrictMock<AssistantNotificationControllerMock> notification_controller;
service_context()->set_assistant_notification_controller(
&notification_controller);
CreateAssistantDeviceSettingsDelegate();
ModifySettingArgs args;
args.set_setting_id(kDoNotDisturb);
args.set_change(Change::ModifySettingArgs_Change_ON);
EXPECT_CALL(notification_controller, SetQuietMode(true));
delegate()->HandleModifyDeviceSetting(args);
args.set_change(Change::ModifySettingArgs_Change_OFF);
EXPECT_CALL(notification_controller, SetQuietMode(false));
delegate()->HandleModifyDeviceSetting(args);
}
TEST_F(AssistantDeviceSettingsDelegateTest, ShouldTurnSwitchAccessOnAndOff) {
auto* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitch(
::switches::kEnableExperimentalAccessibilitySwitchAccess);
StrictMock<DeviceActionsMock> device_actions;
service_context()->set_device_actions(&device_actions);
CreateAssistantDeviceSettingsDelegate();
ModifySettingArgs args;
args.set_setting_id(kSwitchAccess);
args.set_change(Change::ModifySettingArgs_Change_ON);
EXPECT_CALL(device_actions, SetSwitchAccessEnabled(true));
delegate()->HandleModifyDeviceSetting(args);
args.set_change(Change::ModifySettingArgs_Change_OFF);
EXPECT_CALL(device_actions, SetSwitchAccessEnabled(false));
delegate()->HandleModifyDeviceSetting(args);
}
TEST_F(AssistantDeviceSettingsDelegateTest, ShouldTurnNightLightOnAndOff) {
StrictMock<DeviceActionsMock> device_actions;
service_context()->set_device_actions(&device_actions);
CreateAssistantDeviceSettingsDelegate();
ModifySettingArgs args;
args.set_setting_id(kNightLight);
args.set_change(Change::ModifySettingArgs_Change_ON);
EXPECT_CALL(device_actions, SetNightLightEnabled(true));
delegate()->HandleModifyDeviceSetting(args);
args.set_change(Change::ModifySettingArgs_Change_OFF);
EXPECT_CALL(device_actions, SetNightLightEnabled(false));
delegate()->HandleModifyDeviceSetting(args);
}
TEST_F(AssistantDeviceSettingsDelegateTest, ShouldSetVolume) {
StrictMock<VolumeControlMock> volume_control;
CreateAssistantDeviceSettingsDelegate(&volume_control);
EXPECT_CALL(volume_control, GetSystemVolume).Times(AnyNumber());
ModifySettingArgs args;
args.set_setting_id(kVolumeLevel);
args.set_change(Change::ModifySettingArgs_Change_SET);
// Set volume to 20%
args.set_numeric_value(0.2);
args.set_unit(Unit::ModifySettingArgs_Unit_RANGE);
EXPECT_CALL(volume_control, SetSystemVolume(FloatNear(0.2, kEpsilon),
/*user_initiated=*/true));
delegate()->HandleModifyDeviceSetting(args);
// Set volume to 20.
// This will be converted to a percentage
args.set_numeric_value(20);
args.set_unit(Unit::ModifySettingArgs_Unit_STEP);
EXPECT_CALL(volume_control, SetSystemVolume(FloatNear(0.2, kEpsilon),
/*user_initiated=*/true));
delegate()->HandleModifyDeviceSetting(args);
}
TEST_F(AssistantDeviceSettingsDelegateTest, ShouldIncreaseAndDecreaseVolume) {
StrictMock<VolumeControlMock> volume_control;
CreateAssistantDeviceSettingsDelegate(&volume_control);
EXPECT_CALL(volume_control, GetSystemVolume).Times(AnyNumber());
ModifySettingArgs args;
args.set_setting_id(kVolumeLevel);
args.set_change(Change::ModifySettingArgs_Change_SET);
// Set volume to 20%
args.set_numeric_value(0.2);
args.set_unit(Unit::ModifySettingArgs_Unit_RANGE);
EXPECT_CALL(volume_control, SetSystemVolume(FloatNear(0.2, kEpsilon),
/*user_initiated=*/true));
delegate()->HandleModifyDeviceSetting(args);
// Set volume to 20.
// This will be converted to a percentage
args.set_numeric_value(20);
args.set_unit(Unit::ModifySettingArgs_Unit_STEP);
EXPECT_CALL(volume_control, SetSystemVolume(FloatNear(0.2, kEpsilon),
/*user_initiated=*/true));
delegate()->HandleModifyDeviceSetting(args);
}
TEST_F(AssistantDeviceSettingsDelegateTest, ShouldSetBrightness) {
StrictMock<DeviceActionsMock> device_actions;
service_context()->set_device_actions(&device_actions);
CreateAssistantDeviceSettingsDelegate();
ModifySettingArgs args;
args.set_setting_id(kScreenBrightness);
args.set_change(Change::ModifySettingArgs_Change_SET);
// Set brightness to 20%
args.set_numeric_value(0.2);
args.set_unit(Unit::ModifySettingArgs_Unit_RANGE);
EXPECT_CALL(device_actions,
SetScreenBrightnessLevel(DoubleNear(0.2, kEpsilon),
/*gradual=*/true));
delegate()->HandleModifyDeviceSetting(args);
// Set brightness to 30.
// This will be converted to a percentage
args.set_numeric_value(30);
args.set_unit(Unit::ModifySettingArgs_Unit_STEP);
EXPECT_CALL(device_actions, SetScreenBrightnessLevel(
DoubleNear(0.3, kEpsilon), /*gradual=*/true));
delegate()->HandleModifyDeviceSetting(args);
}
TEST_F(AssistantDeviceSettingsDelegateTest,
ShouldIncreaseAndDecreaseBrightness) {
StrictMock<DeviceActionsMock> device_actions;
service_context()->set_device_actions(&device_actions);
CreateAssistantDeviceSettingsDelegate();
ModifySettingArgs args;
args.set_setting_id(kScreenBrightness);
// Increase brightness - this will use a default increment of 10%
args.set_change(Change::ModifySettingArgs_Change_INCREASE);
args.set_unit(Unit::ModifySettingArgs_Unit_UNKNOWN_UNIT);
device_actions.set_current_brightness(0.2);
EXPECT_CALL(device_actions, SetScreenBrightnessLevel(
DoubleNear(0.3, kEpsilon), /*gradual=*/true));
delegate()->HandleModifyDeviceSetting(args);
// Decrease brightness - this will use a default decrement of 10%
args.set_change(Change::ModifySettingArgs_Change_DECREASE);
args.set_unit(Unit::ModifySettingArgs_Unit_UNKNOWN_UNIT);
device_actions.set_current_brightness(0.2);
EXPECT_CALL(device_actions, SetScreenBrightnessLevel(
DoubleNear(0.1, kEpsilon), /*gradual=*/true));
delegate()->HandleModifyDeviceSetting(args);
}
} // namespace assistant
} // namespace chromeos
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "chromeos/constants/chromeos_features.h" #include "chromeos/constants/chromeos_features.h"
#include "chromeos/constants/chromeos_switches.h" #include "chromeos/constants/chromeos_switches.h"
#include "chromeos/dbus/util/version_loader.h" #include "chromeos/dbus/util/version_loader.h"
#include "chromeos/services/assistant/assistant_device_settings_delegate.h"
#include "chromeos/services/assistant/assistant_manager_service_delegate.h" #include "chromeos/services/assistant/assistant_manager_service_delegate.h"
#include "chromeos/services/assistant/media_session/assistant_media_session.h" #include "chromeos/services/assistant/media_session/assistant_media_session.h"
#include "chromeos/services/assistant/platform_api_impl.h" #include "chromeos/services/assistant/platform_api_impl.h"
...@@ -45,7 +46,6 @@ ...@@ -45,7 +46,6 @@
#include "libassistant/shared/public/media_manager.h" #include "libassistant/shared/public/media_manager.h"
#include "services/media_session/public/mojom/media_session.mojom.h" #include "services/media_session/public/mojom/media_session.mojom.h"
#include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/shared_url_loader_factory.h"
#include "ui/accessibility/accessibility_switches.h"
#include "ui/accessibility/mojom/ax_assistant_structure.mojom.h" #include "ui/accessibility/mojom/ax_assistant_structure.mojom.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -76,14 +76,7 @@ namespace { ...@@ -76,14 +76,7 @@ namespace {
static bool is_first_init = true; static bool is_first_init = true;
constexpr char kWiFiDeviceSettingId[] = "WIFI";
constexpr char kBluetoothDeviceSettingId[] = "BLUETOOTH";
constexpr char kVolumeLevelDeviceSettingId[] = "VOLUME_LEVEL";
constexpr char kScreenBrightnessDeviceSettingId[] = "BRIGHTNESS_LEVEL";
constexpr char kDoNotDisturbDeviceSettingId[] = "DO_NOT_DISTURB";
constexpr char kNightLightDeviceSettingId[] = "NIGHT_LIGHT_SWITCH";
constexpr char kIntentActionView[] = "android.intent.action.VIEW"; constexpr char kIntentActionView[] = "android.intent.action.VIEW";
constexpr char kSwitchAccessDeviceSettingId[] = "SWITCH_ACCESS";
constexpr base::Feature kChromeOSAssistantDogfood{ constexpr base::Feature kChromeOSAssistantDogfood{
"ChromeOSAssistantDogfood", base::FEATURE_DISABLED_BY_DEFAULT}; "ChromeOSAssistantDogfood", base::FEATURE_DISABLED_BY_DEFAULT};
...@@ -99,8 +92,6 @@ constexpr char kPrevTrackClientOp[] = "media.PREVIOUS"; ...@@ -99,8 +92,6 @@ constexpr char kPrevTrackClientOp[] = "media.PREVIOUS";
constexpr char kResumeTrackClientOp[] = "media.RESUME"; constexpr char kResumeTrackClientOp[] = "media.RESUME";
constexpr char kStopTrackClientOp[] = "media.STOP"; constexpr char kStopTrackClientOp[] = "media.STOP";
constexpr float kDefaultSliderStep = 0.1f;
constexpr char kAndroidSettingsAppPackage[] = "com.android.settings"; constexpr char kAndroidSettingsAppPackage[] = "com.android.settings";
action::AppStatus GetActionAppStatus(mojom::AppStatus status) { action::AppStatus GetActionAppStatus(mojom::AppStatus status) {
...@@ -178,6 +169,9 @@ AssistantManagerServiceImpl::AssistantManagerServiceImpl( ...@@ -178,6 +169,9 @@ AssistantManagerServiceImpl::AssistantManagerServiceImpl(
platform_api_ = delegate_->CreatePlatformApi( platform_api_ = delegate_->CreatePlatformApi(
media_session_.get(), background_thread_.task_runner()); media_session_.get(), background_thread_.task_runner());
settings_delegate_ = std::make_unique<AssistantDeviceSettingsDelegate>(
context, &platform_api_->GetAudioOutputProvider().GetVolumeControl());
mojo::Remote<media_session::mojom::MediaControllerManager> mojo::Remote<media_session::mojom::MediaControllerManager>
media_controller_manager; media_controller_manager;
client->RequestMediaControllerManager( client->RequestMediaControllerManager(
...@@ -970,181 +964,20 @@ void AssistantManagerServiceImpl::OnSpeechLevelUpdated( ...@@ -970,181 +964,20 @@ void AssistantManagerServiceImpl::OnSpeechLevelUpdated(
it->OnSpeechLevelUpdated(speech_level); it->OnSpeechLevelUpdated(speech_level);
} }
void LogUnsupportedChange(api::client_op::ModifySettingArgs args) {
LOG(ERROR) << "Unsupported change operation: " << args.change()
<< " for setting " << args.setting_id();
}
void HandleOnOffChange(api::client_op::ModifySettingArgs modify_setting_args,
std::function<void(bool)> on_off_handler) {
switch (modify_setting_args.change()) {
case api::client_op::ModifySettingArgs_Change_ON:
on_off_handler(true);
return;
case api::client_op::ModifySettingArgs_Change_OFF:
on_off_handler(false);
return;
// Currently there are no use-cases for toggling. This could change in the
// future.
case api::client_op::ModifySettingArgs_Change_TOGGLE:
break;
case api::client_op::ModifySettingArgs_Change_SET:
case api::client_op::ModifySettingArgs_Change_INCREASE:
case api::client_op::ModifySettingArgs_Change_DECREASE:
case api::client_op::ModifySettingArgs_Change_UNSPECIFIED:
// This shouldn't happen.
break;
}
LogUnsupportedChange(modify_setting_args);
}
// Helper function that converts a slider value sent from the server, either
// absolute or a delta, from a given unit (e.g., STEP), to a percentage.
double ConvertSliderValueToLevel(double value,
api::client_op::ModifySettingArgs_Unit unit,
double default_value) {
switch (unit) {
case api::client_op::ModifySettingArgs_Unit_RANGE:
// "set volume to 20%".
return value;
case api::client_op::ModifySettingArgs_Unit_STEP:
// "set volume to 20". Treat the step as a percentage.
return value / 100.0f;
// Currently, factor (e.g., 'double the volume') and decibel units aren't
// handled by the backend. This could change in the future.
case api::client_op::ModifySettingArgs_Unit_FACTOR:
case api::client_op::ModifySettingArgs_Unit_DECIBEL:
break;
case api::client_op::ModifySettingArgs_Unit_NATIVE:
case api::client_op::ModifySettingArgs_Unit_UNKNOWN_UNIT:
// This shouldn't happen.
break;
}
LOG(ERROR) << "Unsupported slider unit: " << unit;
return default_value;
}
void HandleSliderChange(api::client_op::ModifySettingArgs modify_setting_args,
std::function<void(double)> set_value_handler,
std::function<double()> get_value_handler) {
switch (modify_setting_args.change()) {
case api::client_op::ModifySettingArgs_Change_SET: {
// For unsupported units, set the value to the current value, for
// visual feedback.
double new_value = ConvertSliderValueToLevel(
modify_setting_args.numeric_value(), modify_setting_args.unit(),
get_value_handler());
set_value_handler(new_value);
return;
}
case api::client_op::ModifySettingArgs_Change_INCREASE:
case api::client_op::ModifySettingArgs_Change_DECREASE: {
double current_value = get_value_handler();
double step = kDefaultSliderStep;
if (modify_setting_args.numeric_value() != 0.0f) {
// For unsupported units, use the default step percentage.
step = ConvertSliderValueToLevel(modify_setting_args.numeric_value(),
modify_setting_args.unit(),
kDefaultSliderStep);
}
double new_value = (modify_setting_args.change() ==
api::client_op::ModifySettingArgs_Change_INCREASE)
? std::min(current_value + step, 1.0)
: std::max(current_value - step, 0.0);
set_value_handler(new_value);
return;
}
case api::client_op::ModifySettingArgs_Change_ON:
case api::client_op::ModifySettingArgs_Change_OFF:
case api::client_op::ModifySettingArgs_Change_TOGGLE:
case api::client_op::ModifySettingArgs_Change_UNSPECIFIED:
// This shouldn't happen.
break;
}
LogUnsupportedChange(modify_setting_args);
}
void AssistantManagerServiceImpl::OnModifyDeviceSetting( void AssistantManagerServiceImpl::OnModifyDeviceSetting(
const api::client_op::ModifySettingArgs& modify_setting_args) { const api::client_op::ModifySettingArgs& modify_setting_args) {
ENSURE_MAIN_THREAD(&AssistantManagerServiceImpl::OnModifyDeviceSetting, ENSURE_MAIN_THREAD(&AssistantManagerServiceImpl::OnModifyDeviceSetting,
modify_setting_args); modify_setting_args);
DCHECK(IsSettingSupported(modify_setting_args.setting_id()));
receive_modify_settings_proto_response_ = true; receive_modify_settings_proto_response_ = true;
if (modify_setting_args.setting_id() == kWiFiDeviceSettingId) { settings_delegate_->HandleModifyDeviceSetting(modify_setting_args);
HandleOnOffChange(modify_setting_args, [&](bool enabled) {
this->device_actions()->SetWifiEnabled(enabled);
});
}
if (modify_setting_args.setting_id() == kBluetoothDeviceSettingId) {
HandleOnOffChange(modify_setting_args, [&](bool enabled) {
this->device_actions()->SetBluetoothEnabled(enabled);
});
}
if (modify_setting_args.setting_id() == kVolumeLevelDeviceSettingId) {
assistant_client::VolumeControl& volume_control =
this->platform_api_->GetAudioOutputProvider().GetVolumeControl();
HandleSliderChange(
modify_setting_args,
[&](double value) { volume_control.SetSystemVolume(value, true); },
[&]() { return volume_control.GetSystemVolume(); });
}
if (modify_setting_args.setting_id() == kScreenBrightnessDeviceSettingId) {
this->device_actions()->GetScreenBrightnessLevel(base::BindOnce(
[](base::WeakPtr<chromeos::assistant::AssistantManagerServiceImpl>
this_,
api::client_op::ModifySettingArgs modify_setting_args, bool success,
double current_value) {
if (!success || !this_) {
return;
}
HandleSliderChange(
modify_setting_args,
[&](double new_value) {
this_->device_actions()->SetScreenBrightnessLevel(new_value,
true);
},
[&]() { return current_value; });
},
weak_factory_.GetWeakPtr(), modify_setting_args));
}
if (modify_setting_args.setting_id() == kDoNotDisturbDeviceSettingId) {
HandleOnOffChange(modify_setting_args, [&](bool enabled) {
this->assistant_notification_controller()->SetQuietMode(enabled);
});
}
if (modify_setting_args.setting_id() == kNightLightDeviceSettingId) {
HandleOnOffChange(modify_setting_args, [&](bool enabled) {
this->device_actions()->SetNightLightEnabled(enabled);
});
}
if (modify_setting_args.setting_id() == kSwitchAccessDeviceSettingId) {
HandleOnOffChange(modify_setting_args, [&](bool enabled) {
this->device_actions()->SetSwitchAccessEnabled(enabled);
});
}
} }
void AssistantManagerServiceImpl::OnGetDeviceSettings( void AssistantManagerServiceImpl::OnGetDeviceSettings(
int interaction_id, int interaction_id,
const api::client_op::GetDeviceSettingsArgs& args) { const api::client_op::GetDeviceSettingsArgs& args) {
// Collect the required information. std::vector<DeviceSetting> result =
std::vector<DeviceSetting> result; settings_delegate_->GetDeviceSettings(args);
for (const std::string& setting_id : args.setting_ids())
result.emplace_back(setting_id, IsSettingSupported(setting_id));
SendVoicelessInteraction( SendVoicelessInteraction(
CreateGetDeviceSettingInteraction(interaction_id, result), CreateGetDeviceSettingInteraction(interaction_id, result),
...@@ -1156,18 +989,7 @@ bool AssistantManagerServiceImpl::IsSettingSupported( ...@@ -1156,18 +989,7 @@ bool AssistantManagerServiceImpl::IsSettingSupported(
const std::string& setting_id) { const std::string& setting_id) {
DVLOG(2) << "IsSettingSupported=" << setting_id; DVLOG(2) << "IsSettingSupported=" << setting_id;
if (base::CommandLine::ForCurrentProcess()->HasSwitch( return settings_delegate_->IsSettingSupported(setting_id);
::switches::kEnableExperimentalAccessibilitySwitchAccess) &&
setting_id == kSwitchAccessDeviceSettingId) {
return true;
}
return (setting_id == kWiFiDeviceSettingId ||
setting_id == kBluetoothDeviceSettingId ||
setting_id == kVolumeLevelDeviceSettingId ||
setting_id == kScreenBrightnessDeviceSettingId ||
setting_id == kDoNotDisturbDeviceSettingId ||
setting_id == kNightLightDeviceSettingId);
} }
bool AssistantManagerServiceImpl::SupportsModifySettings() { bool AssistantManagerServiceImpl::SupportsModifySettings() {
......
...@@ -57,6 +57,7 @@ class AssistantMediaSession; ...@@ -57,6 +57,7 @@ class AssistantMediaSession;
class CrosPlatformApi; class CrosPlatformApi;
class ServiceContext; class ServiceContext;
class AssistantManagerServiceDelegate; class AssistantManagerServiceDelegate;
class AssistantDeviceSettingsDelegate;
// Enumeration of Assistant query response type, also recorded in histograms. // Enumeration of Assistant query response type, also recorded in histograms.
// These values are persisted to logs. Entries should not be renumbered and // These values are persisted to logs. Entries should not be renumbered and
...@@ -350,6 +351,7 @@ class COMPONENT_EXPORT(ASSISTANT_SERVICE) AssistantManagerServiceImpl ...@@ -350,6 +351,7 @@ class COMPONENT_EXPORT(ASSISTANT_SERVICE) AssistantManagerServiceImpl
ServiceContext* const context_; ServiceContext* const context_;
std::unique_ptr<AssistantManagerServiceDelegate> delegate_; std::unique_ptr<AssistantManagerServiceDelegate> delegate_;
std::unique_ptr<AssistantDeviceSettingsDelegate> settings_delegate_;
bool spoken_feedback_enabled_ = false; bool spoken_feedback_enabled_ = false;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "chromeos/services/assistant/service_context.h" #include "chromeos/services/assistant/service_context.h"
#include "chromeos/services/assistant/test_support/fake_assistant_manager_service_delegate.h" #include "chromeos/services/assistant/test_support/fake_assistant_manager_service_delegate.h"
#include "chromeos/services/assistant/test_support/fake_client.h" #include "chromeos/services/assistant/test_support/fake_client.h"
#include "chromeos/services/assistant/test_support/fake_service_context.h"
#include "chromeos/services/assistant/test_support/fully_initialized_assistant_state.h" #include "chromeos/services/assistant/test_support/fully_initialized_assistant_state.h"
#include "chromeos/services/assistant/test_support/mock_assistant_interaction_subscriber.h" #include "chromeos/services/assistant/test_support/mock_assistant_interaction_subscriber.h"
#include "chromeos/services/assistant/test_support/mock_media_manager.h" #include "chromeos/services/assistant/test_support/mock_media_manager.h"
...@@ -46,7 +47,6 @@ using UserInfo = AssistantManagerService::UserInfo; ...@@ -46,7 +47,6 @@ using UserInfo = AssistantManagerService::UserInfo;
namespace { namespace {
const char* kGaiaId = "<fake-gaia-id>";
const char* kNoValue = FakeAssistantManager::kNoValue; const char* kNoValue = FakeAssistantManager::kNoValue;
// Action CloneArg<k>(pointer) clones the k-th (0-based) argument of the mock // Action CloneArg<k>(pointer) clones the k-th (0-based) argument of the mock
...@@ -116,80 +116,6 @@ class FakeAssistantClient : public FakeClient { ...@@ -116,80 +116,6 @@ class FakeAssistantClient : public FakeClient {
DISALLOW_COPY_AND_ASSIGN(FakeAssistantClient); DISALLOW_COPY_AND_ASSIGN(FakeAssistantClient);
}; };
class FakeServiceContext : public ServiceContext {
public:
FakeServiceContext(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
ash::AssistantState* assistant_state,
PowerManagerClient* power_manager_client)
: main_task_runner_(main_task_runner),
assistant_state_(assistant_state),
power_manager_client_(power_manager_client) {}
~FakeServiceContext() override = default;
void set_assistant_alarm_timer_controller(
ash::mojom::AssistantAlarmTimerController*
assistant_alarm_timer_controller) {
assistant_alarm_timer_controller_ = assistant_alarm_timer_controller;
}
ash::mojom::AssistantAlarmTimerController* assistant_alarm_timer_controller()
override {
return assistant_alarm_timer_controller_;
}
mojom::AssistantController* assistant_controller() override {
NOTIMPLEMENTED();
return nullptr;
}
ash::mojom::AssistantNotificationController*
assistant_notification_controller() override {
NOTIMPLEMENTED();
return nullptr;
}
ash::mojom::AssistantScreenContextController*
assistant_screen_context_controller() override {
NOTIMPLEMENTED();
return nullptr;
}
ash::AssistantStateBase* assistant_state() override {
return assistant_state_;
}
CrasAudioHandler* cras_audio_handler() override {
NOTIMPLEMENTED();
return nullptr;
}
mojom::DeviceActions* device_actions() override {
NOTIMPLEMENTED();
return nullptr;
}
scoped_refptr<base::SequencedTaskRunner> main_task_runner() override {
return main_task_runner_;
}
PowerManagerClient* power_manager_client() override {
return power_manager_client_;
}
std::string primary_account_gaia_id() override { return gaia_id; }
private:
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
ash::AssistantState* const assistant_state_;
PowerManagerClient* const power_manager_client_;
std::string gaia_id = kGaiaId;
ash::mojom::AssistantAlarmTimerController* assistant_alarm_timer_controller_ =
nullptr;
DISALLOW_COPY_AND_ASSIGN(FakeServiceContext);
};
class AssistantAlarmTimerControllerMock class AssistantAlarmTimerControllerMock
: public ash::mojom::AssistantAlarmTimerController { : public ash::mojom::AssistantAlarmTimerController {
public: public:
...@@ -250,9 +176,11 @@ class AssistantManagerServiceImplTest : public testing::Test { ...@@ -250,9 +176,11 @@ class AssistantManagerServiceImplTest : public testing::Test {
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&url_loader_factory_); &url_loader_factory_);
service_context_ = std::make_unique<FakeServiceContext>( service_context_ = std::make_unique<FakeServiceContext>();
task_environment.GetMainThreadTaskRunner(), &assistant_state_, service_context_
PowerManagerClient::Get()); ->set_main_task_runner(task_environment.GetMainThreadTaskRunner())
.set_power_manager_client(PowerManagerClient::Get())
.set_assistant_state(&assistant_state_);
CreateAssistantManagerServiceImpl(/*libassistant_config=*/{}); CreateAssistantManagerServiceImpl(/*libassistant_config=*/{});
} }
......
...@@ -2,12 +2,71 @@ ...@@ -2,12 +2,71 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chromeos/services/assistant/test_support/fake_platform_api.h" #include <vector>
#include "base/logging.h" #include "base/logging.h"
#include "chromeos/services/assistant/test_support/fake_platform_api.h"
#include "libassistant/shared/public/platform_audio_output.h"
namespace chromeos { namespace chromeos {
namespace assistant { namespace assistant {
namespace {
class FakeVolumeControl : public assistant_client::VolumeControl {
public:
// assistant_client::VolumeControl implementation:
void SetAudioFocus(assistant_client::OutputStreamType) override {}
float GetSystemVolume() override { return 0.5; }
void SetSystemVolume(float new_volume, bool user_initiated) override {}
float GetAlarmVolume() override { return 0.5; }
void SetAlarmVolume(float new_volume, bool user_initiated) override {}
bool IsSystemMuted() override { return false; }
void SetSystemMuted(bool muted) override {}
};
class FakeAudioOutputProvider : public assistant_client::AudioOutputProvider {
public:
FakeAudioOutputProvider() = default;
FakeAudioOutputProvider(FakeAudioOutputProvider&) = delete;
FakeAudioOutputProvider& operator=(FakeAudioOutputProvider&) = delete;
~FakeAudioOutputProvider() override = default;
// assistant_client::AudioOutputProvider implementation:
assistant_client::AudioOutput* CreateAudioOutput(
assistant_client::OutputStreamType type,
const assistant_client::OutputStreamFormat& stream_format) override {
NOTIMPLEMENTED();
abort();
}
std::vector<assistant_client::OutputStreamEncoding>
GetSupportedStreamEncodings() override {
return {};
}
assistant_client::AudioInput* GetReferenceInput() override {
NOTIMPLEMENTED();
abort();
}
bool SupportsPlaybackTimestamp() const override { return false; }
assistant_client::VolumeControl& GetVolumeControl() override {
return volume_control_;
}
private:
FakeVolumeControl volume_control_;
};
} // namespace
FakePlatformApi::FakePlatformApi()
: audio_output_provider_(std::make_unique<FakeAudioOutputProvider>()) {}
FakePlatformApi::~FakePlatformApi() = default;
assistant_client::AudioInputProvider& FakePlatformApi::GetAudioInputProvider() { assistant_client::AudioInputProvider& FakePlatformApi::GetAudioInputProvider() {
NOTIMPLEMENTED(); NOTIMPLEMENTED();
abort(); abort();
...@@ -15,8 +74,7 @@ assistant_client::AudioInputProvider& FakePlatformApi::GetAudioInputProvider() { ...@@ -15,8 +74,7 @@ assistant_client::AudioInputProvider& FakePlatformApi::GetAudioInputProvider() {
assistant_client::AudioOutputProvider& assistant_client::AudioOutputProvider&
FakePlatformApi::GetAudioOutputProvider() { FakePlatformApi::GetAudioOutputProvider() {
NOTIMPLEMENTED(); return *audio_output_provider_.get();
abort();
} }
assistant_client::AuthProvider& FakePlatformApi::GetAuthProvider() { assistant_client::AuthProvider& FakePlatformApi::GetAuthProvider() {
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef CHROMEOS_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_PLATFORM_API_H_ #ifndef CHROMEOS_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_PLATFORM_API_H_
#define CHROMEOS_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_PLATFORM_API_H_ #define CHROMEOS_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_PLATFORM_API_H_
#include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "chromeos/services/assistant/cros_platform_api.h" #include "chromeos/services/assistant/cros_platform_api.h"
...@@ -12,12 +14,12 @@ namespace chromeos { ...@@ -12,12 +14,12 @@ namespace chromeos {
namespace assistant { namespace assistant {
// Fake implementation of the |CrosPlatformApi| used during the unittests. // Fake implementation of the |CrosPlatformApi| used during the unittests.
// As of now the |assistant_client::PlatformApi| methods are not implemented // As of now most of the |assistant_client::PlatformApi| methods are not
// and will assert when called. // implemented and will assert when called.
class FakePlatformApi : public CrosPlatformApi { class FakePlatformApi : public CrosPlatformApi {
public: public:
FakePlatformApi() = default; FakePlatformApi();
~FakePlatformApi() override = default; ~FakePlatformApi() override;
// CrosPlatformApi overrides // CrosPlatformApi overrides
assistant_client::AudioInputProvider& GetAudioInputProvider() override; assistant_client::AudioInputProvider& GetAudioInputProvider() override;
...@@ -33,6 +35,8 @@ class FakePlatformApi : public CrosPlatformApi { ...@@ -33,6 +35,8 @@ class FakePlatformApi : public CrosPlatformApi {
private: private:
DISALLOW_COPY_AND_ASSIGN(FakePlatformApi); DISALLOW_COPY_AND_ASSIGN(FakePlatformApi);
std::unique_ptr<assistant_client::AudioOutputProvider> audio_output_provider_;
}; };
} // namespace assistant } // namespace assistant
......
// Copyright 2020 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 <string>
#include "chromeos/services/assistant/test_support/fake_service_context.h"
namespace chromeos {
namespace assistant {
/*static*/
constexpr const char* FakeServiceContext::kGaiaId;
FakeServiceContext::FakeServiceContext() = default;
FakeServiceContext::~FakeServiceContext() = default;
FakeServiceContext& FakeServiceContext::set_assistant_alarm_timer_controller(
ash::mojom::AssistantAlarmTimerController* value) {
assistant_alarm_timer_controller_ = value;
return *this;
}
FakeServiceContext& FakeServiceContext::set_main_task_runner(
scoped_refptr<base::SingleThreadTaskRunner> value) {
main_task_runner_ = value;
return *this;
}
FakeServiceContext& FakeServiceContext::set_power_manager_client(
PowerManagerClient* value) {
power_manager_client_ = value;
return *this;
}
FakeServiceContext& FakeServiceContext::set_primary_account_gaia_id(
std::string value) {
gaia_id_ = value;
return *this;
}
FakeServiceContext& FakeServiceContext::set_assistant_state(
ash::AssistantStateBase* value) {
assistant_state_ = value;
return *this;
}
FakeServiceContext& FakeServiceContext::set_device_actions(
mojom::DeviceActions* value) {
device_actions_ = value;
return *this;
}
FakeServiceContext& FakeServiceContext::set_assistant_notification_controller(
ash::mojom::AssistantNotificationController* value) {
assistant_notification_controller_ = value;
return *this;
}
ash::mojom::AssistantAlarmTimerController*
FakeServiceContext::assistant_alarm_timer_controller() {
DCHECK(assistant_alarm_timer_controller_ != nullptr);
return assistant_alarm_timer_controller_;
}
mojom::AssistantController* FakeServiceContext::assistant_controller() {
NOTIMPLEMENTED();
return nullptr;
}
ash::mojom::AssistantNotificationController*
FakeServiceContext::assistant_notification_controller() {
DCHECK(assistant_notification_controller_ != nullptr);
return assistant_notification_controller_;
}
ash::mojom::AssistantScreenContextController*
FakeServiceContext::assistant_screen_context_controller() {
NOTIMPLEMENTED();
return nullptr;
}
ash::AssistantStateBase* FakeServiceContext::assistant_state() {
DCHECK(assistant_state_ != nullptr);
return assistant_state_;
}
CrasAudioHandler* FakeServiceContext::cras_audio_handler() {
NOTIMPLEMENTED();
return nullptr;
}
mojom::DeviceActions* FakeServiceContext::device_actions() {
DCHECK(device_actions_ != nullptr);
return device_actions_;
}
scoped_refptr<base::SequencedTaskRunner>
FakeServiceContext::main_task_runner() {
DCHECK(main_task_runner_ != nullptr);
return main_task_runner_;
}
PowerManagerClient* FakeServiceContext::power_manager_client() {
DCHECK(power_manager_client_ != nullptr);
return power_manager_client_;
}
std::string FakeServiceContext::primary_account_gaia_id() {
return gaia_id_;
}
} // namespace assistant
} // namespace chromeos
// Copyright 2020 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_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_SERVICE_CONTEXT_H_
#define CHROMEOS_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_SERVICE_CONTEXT_H_
#include <string>
#include "base/single_thread_task_runner.h"
#include "chromeos/services/assistant/service_context.h"
namespace chromeos {
namespace assistant {
// Fake implementation of the |ServiceContext| used during the unittests.
// Every method will assert when called,
// unless you've provided the object using one of the setter methods.
class FakeServiceContext : public ServiceContext {
public:
// Gaia ID returned by primary_account_gaia_id() (unless overridden).
static constexpr const char* kGaiaId = "<fake-gaia-id>";
FakeServiceContext();
FakeServiceContext(const FakeServiceContext&) = delete;
FakeServiceContext& operator=(const FakeServiceContext&) = delete;
~FakeServiceContext() override;
FakeServiceContext& set_assistant_alarm_timer_controller(
ash::mojom::AssistantAlarmTimerController*);
FakeServiceContext& set_main_task_runner(
scoped_refptr<base::SingleThreadTaskRunner>);
FakeServiceContext& set_power_manager_client(PowerManagerClient*);
FakeServiceContext& set_primary_account_gaia_id(std::string);
FakeServiceContext& set_assistant_state(ash::AssistantStateBase*);
FakeServiceContext& set_device_actions(mojom::DeviceActions*);
FakeServiceContext& set_assistant_notification_controller(
ash::mojom::AssistantNotificationController*);
// ServiceContext implementation:
ash::mojom::AssistantAlarmTimerController* assistant_alarm_timer_controller()
override;
mojom::AssistantController* assistant_controller() override;
ash::mojom::AssistantNotificationController*
assistant_notification_controller() override;
ash::mojom::AssistantScreenContextController*
assistant_screen_context_controller() override;
ash::AssistantStateBase* assistant_state() override;
CrasAudioHandler* cras_audio_handler() override;
mojom::DeviceActions* device_actions() override;
scoped_refptr<base::SequencedTaskRunner> main_task_runner() override;
PowerManagerClient* power_manager_client() override;
std::string primary_account_gaia_id() override;
private:
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
ash::AssistantStateBase* assistant_state_ = nullptr;
PowerManagerClient* power_manager_client_ = nullptr;
std::string gaia_id_ = kGaiaId;
ash::mojom::AssistantAlarmTimerController* assistant_alarm_timer_controller_ =
nullptr;
mojom::DeviceActions* device_actions_ = nullptr;
ash::mojom::AssistantNotificationController*
assistant_notification_controller_ = nullptr;
};
} // namespace assistant
} // namespace chromeos
#endif // CHROMEOS_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_SERVICE_CONTEXT_H_
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