avs-device-sdk/Settings/test/SharedAVSSettingProtocolTes...

650 lines
26 KiB
C++
Raw Normal View History

Version 1.15 alexa-client-sdk Changes in this update: **Enhancements** * Added `SystemSoundPlayer` to [ApplicationUtilities](https://alexa.github.io/avs-device-sdk/namespacealexa_client_s_d_k_1_1application_utilities.html). `SystemSoundPlayer` is a new class that plays pre-defined sounds. Sounds currently supported include the wake word notification and the end of speech tone. This change is internal and you don't need to update your code. * Removed [Echo Spatial Perception (ESP)](https://developer.amazon.com/blogs/alexa/post/042be85c-5a62-4c55-a18d-d7a82cf394df/esp-moves-to-the-cloud-for-alexa-enabled-devices) functionality from the Alexa Voice Service (AVS) device SDK. Make sure you download and test your devices using the new AVS SDK sample app. If you're using an older version of the sample app, manually remove any references to ESP or errors occur during compile. * Added `onNotificationReceived` to `NotificationsObserverInterface`. `onNotificationReceived` broadcasts when `NotificationsObserverInterface` receives a new notification, instead of only sending the indicator state. This is important if you support a feature that requires a distinct signal for each notification received. See [NotificationsObserverInterface](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1avs_common_1_1sdk_interfaces_1_1_notifications_observer_interface.html) for more details. * Added support for [Multilingual Mode](https://developer.amazon.com/docs/alexa-voice-service/system.html#localecombinations). With this enabled, Alexa automatically detects what language a user speaks by analyzing the spoken wake word and proceeding utterances. Once Alexa identifies the language, all corresponding responses are in the same language. The current supported language pairs are: - `[ "en-US", "es-US" ]` - `[ "es-US", "en-US" ]` - `[ "en-IN", "hi-IN" ]` - `[ "hi-IN", "en-IN" ]` - `[ "en-CA", "fr-CA" ]` - `[ "fr-CA", "en-CA" ]` <br/> **IMPORTANT**: Specify the locales your device supports in the [localeCombinations](https://developer.amazon.com/docs/alexa-voice-service/system.html#localecombinations) field in AlexaClientSDKConfig.json. This field can't be empty. If you don't set these values, the sample app fails to run. * Added two new system settings, [Timezone](https://developer.amazon.com/docs/alexa-voice-service/system.html#settimezone) and [Locale](https://developer.amazon.com/docs/alexa-voice-service/system.html#locales). - Timezone: For example, you can set the `defaultTimezone` to `America/Vancouver`. If you don't set a value, `GMT` is set as the default value. If you set a new timezone, make sure that your AVS system settings and default timezone stay in sync. To handle this, use the new class `SystemTimeZoneInterface`. See [System Interface > SetTimeZone](https://developer.amazon.com/docs/alexa-voice-service/system.html#settimezone) for more information. - Locale: For example, you can set `defaultLocale` to `en-GB`, instead of the default `en-US`. * The [SpeechRecognizer](https://developer.amazon.com/docs/alexa-voice-service/speechrecognizer.html) interface now supports the following functionalities. - Change wake word (`Alexa` supported for now). - Toggle start of request tone on/off. - Toggle End of request tone on/off. * Deprecated the [CapabilityAgents](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1avs_common_1_1avs_1_1_capability_agent.html) `Settings{…}` library. `Settings {…}` now maps to an interface that's no longer supported. You might need to update your code to handle these changes. Read [Settings Interface](https://developer.amazon.com/docs/alexa-voice-service/per-interface-settings.html) for more details. * Added support for three new locals: Spanish - United States (ES_US), Hindi - India (HI_IN), and Brazilian - Portuguese (PT_BR). * Linked the atomic library to the sample app to prevent build errors on Raspberry Pi. **Bug Fixes** * Fixed resource leaking in [EqualizerCapabilityAgent](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1capability_agents_1_1equalizer_1_1_equalizer_capability_agent.html) after engine shutdown. * [Issue 1391:](https://github.com/alexa/avs-device-sdk/pull/1391) Fixed an issue where [SQLiteDeviceSettingsStorage::open](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1settings_1_1storage_1_1_s_q_lite_device_setting_storage.html#a7733e56145916f7ff265c5c950add492) tries to acquire a mutex twice, resulting in deadlock. * [Issue 1468:](https://github.com/alexa/avs-device-sdk/issues/1468) Fixed a bug in [AudioPlayer::cancelDirective](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1capability_agents_1_1audio_player_1_1_audio_player.html#a2c710c16f3627790fcc3238d34da9361) that causes a crash. * Fixed Windows install script that caused the sample app build to fail - removed pip, flask, requests, and commentjson dependencies from the mingw.sh helper script. * Fixed issue: notifications failed to sync upon device initialization. For example, let's say you had two devices - one turned on and the other turned off. After clearing the notification on the first device, it still showed up on the second device after turning it on. * Fixed issue: barging in on a reminder caused it to stick in an inconsistent state, blocking subsequent reminders. For example, if a reminder was going off and you interrupted it, the reminder would get persist indefinitely. You could schedule future reminders, but they wouldn't play. Saying “Alexa stop” or rebooting the device fixed the “stuck” reminder. **Known Issues** * Music playback history isn't displayed in the Alexa app for certain account and device types. * When using Gnu Compiler Collection 8+ (GCC 8+), `-Wclass-memaccess` triggers warnings. You can ignore these, they don't cause the build to fail. * Android error `libDefaultClient.so not found` might occur. Resolve this by upgrading to ADB version 1.0.40. * If a device loses a network connection, the lost connection status isn't returned via local TTS. * ACL encounters issues if it receives audio attachments but doesn't consume them. * `SpeechSynthesizerState` uses `GAINING_FOCUS` and `LOSING_FOCUS` as a workaround for handling intermediate states. * Media steamed through Bluetooth might abruptly stop. To restart playback, resume the media in the source application or toggle next/previous. * If a connected Bluetooth device is inactive, the Alexa app might indicates that audio is playing. * The Bluetooth agent assumes that the Bluetooth adapter is always connected to a power source. Disconnecting from a power source during operation isn't yet supported. * When using some products, interrupted Bluetooth playback might not resume if other content is locally streamed. * `make integration` isn't available for Android. To run Android integration tests, manually upload the test binary and input file and run ADB. * Alexa might truncate the beginning of speech when responding to text-to-speech (TTS) user events. This only impacts Raspberry Pi devices running Android Things with HDMI output audio. * A reminder TTS message doesn't play if the sample app restarts and loses a network connection. Instead, the default alarm tone plays twice. * `ServerDisconnectIntegratonTest` tests are disabled until they are updated to reflect new service behavior. * Bluetooth initialization must complete before connecting devices, otherwise devices are ignored. * The `DirectiveSequencerTest.test_handleBlockingThenImmediatelyThenNonBockingOnSameDialogId` test fails intermittently.
2019-09-25 18:49:09 +00:00
/*
* Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#include <memory>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <AVSCommon/SDKInterfaces/MockAVSConnectionManager.h>
#include <AVSCommon/Utils/WaitEvent.h>
#include <Settings/SharedAVSSettingProtocol.h>
#include <Settings/SettingEventMetadata.h>
#include <Settings/SettingObserverInterface.h>
#include "Settings/MockSettingEventSender.h"
#include "Settings/MockDeviceSettingStorage.h"
namespace alexaClientSDK {
namespace settings {
namespace test {
using namespace testing;
using namespace storage::test;
using namespace avsCommon::utils;
using namespace avsCommon::sdkInterfaces::test;
/// A dummy setting metadata.
const SettingEventMetadata METADATA = {"namespace", "ChangedName", "ReportName", "setting"};
/// Constant representing a valid database value.
static const std::string DB_VALUE = R"("db-value")";
/// Constant representing a default value.
static const std::string DEFAULT_VALUE = R"("default-value")";
/// Constant representing a valid new value.
static const std::string NEW_VALUE = R"("new-value")";
/// Empty string used to represent invalid value by the protocol.
static const std::string INVALID_VALUE = "";
/// The database key to be used by the protocol given the @c METADATA object.
static const std::string key = METADATA.eventNamespace + "::" + METADATA.settingName;
/// The timeout used throughout the tests.
static const auto TEST_TIMEOUT = std::chrono::seconds(5);
/**
* Object that allow us to mock the callback functions.
*/
class MockCallbacks {
public:
MOCK_METHOD0(applyChange, std::pair<bool, std::string>());
MOCK_METHOD0(revertChange, std::string());
MOCK_METHOD1(applyDbChange, std::pair<bool, std::string>(const std::string& dbValue));
MOCK_METHOD1(notifyObservers, void(SettingNotifications));
};
/**
* The test class.
*/
class SharedAVSSettingProtocolTest : public Test {
protected:
/**
* Create protocol object and dependencies mocks.
*/
void SetUp() override;
/**
* A helper method to change the value of the setting.
*
* @param value The string value of the setting.
* @param isLocal True means the setting changed is done locally, otherwise, it is a cloud-driven change.
*/
void modifySetting(std::string value, bool isLocal);
/**
* A helper method to test multiple value changes of the setting.
*
*/
void testMultipleChanges(bool isLocal);
/// Mock event sender.
std::shared_ptr<MockSettingEventSender> m_senderMock;
/// Mock setting storage
std::shared_ptr<MockDeviceSettingStorage> m_storageMock;
/// Pointer to a mock protocol.
std::unique_ptr<SharedAVSSettingProtocol> m_protocol;
/// Mock callbacks.
StrictMock<MockCallbacks> m_callbacksMock;
/// Mock connection manager;
std::shared_ptr<MockAVSConnectionManager> m_mockConnectionManager;
};
void SharedAVSSettingProtocolTest::SetUp() {
m_senderMock = std::make_shared<StrictMock<MockSettingEventSender>>();
m_storageMock = std::make_shared<StrictMock<MockDeviceSettingStorage>>();
m_mockConnectionManager = std::make_shared<NiceMock<MockAVSConnectionManager>>();
m_protocol = SharedAVSSettingProtocol::create(METADATA, m_senderMock, m_storageMock, m_mockConnectionManager);
}
void SharedAVSSettingProtocolTest::modifySetting(std::string value, bool isLocal) {
auto executeSet = [value] { return std::make_pair(true, value); };
auto revertChange = [] { return INVALID_VALUE; };
auto notifyObservers = [](SettingNotifications notification) {};
if (isLocal) {
m_protocol->localChange(executeSet, revertChange, notifyObservers);
} else {
m_protocol->avsChange(executeSet, revertChange, notifyObservers);
}
}
void SharedAVSSettingProtocolTest::testMultipleChanges(bool isLocal) {
// The number of setting value changes.
const int numValuesToSet = 10;
// Event notification that all the setting changes has been requested.
WaitEvent lastValueSet;
// Event notification when the AVS event for the last setting change has been sent.
WaitEvent lastValueSentEvent;
// Make all storage operations successful.
EXPECT_CALL(*m_storageMock, storeSetting(key, _, _)).WillRepeatedly(Return(true));
EXPECT_CALL(*m_storageMock, updateSettingStatus(_, _)).WillRepeatedly(Return(true));
// It is expected that one of the intermediate values may be sent or it may not be sent at all, since they are
// replaced by the last value.
if (isLocal) {
EXPECT_CALL(*m_senderMock, sendChangedEvent(_))
.Times(Between(0, 1))
.WillRepeatedly(InvokeWithoutArgs([&lastValueSet] {
// Simulate a delay in sending the event by blocking until all setting changes has been set.
// This cause any pending events to merge.
lastValueSet.wait(TEST_TIMEOUT);
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
} else {
EXPECT_CALL(*m_senderMock, sendReportEvent(_))
.Times(Between(0, 1))
.WillRepeatedly(InvokeWithoutArgs([&lastValueSet] {
// Simulate a delay in sending the event by blocking until all setting changes has been set.
// This cause any pending events to merge.
lastValueSet.wait(TEST_TIMEOUT);
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
}
// Last value should be sent.
if (isLocal) {
EXPECT_CALL(*m_senderMock, sendChangedEvent(std::to_string(numValuesToSet)))
.WillOnce(InvokeWithoutArgs([&lastValueSentEvent] {
lastValueSentEvent.wakeUp();
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
} else {
EXPECT_CALL(*m_senderMock, sendReportEvent(std::to_string(numValuesToSet)))
.WillOnce(InvokeWithoutArgs([&lastValueSentEvent] {
lastValueSentEvent.wakeUp();
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
}
// Change the setting value multiple times.
for (int i = 1; i <= numValuesToSet; i++) {
modifySetting(std::to_string(i), isLocal);
}
lastValueSet.wakeUp();
// This expectation verifies the merging action.
EXPECT_TRUE(lastValueSentEvent.wait(TEST_TIMEOUT));
// Below is an extra sanity test to verify that we can still send another event after sending a merged event.
// Send another value and see if it still can be sent.
const int newValue = numValuesToSet + 1;
WaitEvent sentEvent;
if (isLocal) {
EXPECT_CALL(*m_senderMock, sendChangedEvent(std::to_string(newValue))).WillOnce(InvokeWithoutArgs([&sentEvent] {
sentEvent.wakeUp();
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
} else {
EXPECT_CALL(*m_senderMock, sendReportEvent(std::to_string(newValue))).WillOnce(InvokeWithoutArgs([&sentEvent] {
sentEvent.wakeUp();
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
}
modifySetting(std::to_string(newValue), isLocal);
EXPECT_TRUE(sentEvent.wait(TEST_TIMEOUT));
}
/// Test create with null event sender.
TEST_F(SharedAVSSettingProtocolTest, test_nullEventSender) {
ASSERT_FALSE(SharedAVSSettingProtocol::create(METADATA, nullptr, m_storageMock, m_mockConnectionManager));
}
/// Test create with null storage.
TEST_F(SharedAVSSettingProtocolTest, test_nullStorage) {
ASSERT_FALSE(SharedAVSSettingProtocol::create(METADATA, m_senderMock, nullptr, m_mockConnectionManager));
}
/// Test restore when value is not available in the database.
TEST_F(SharedAVSSettingProtocolTest, test_restoreValueNotAvailable) {
WaitEvent settingsUpdatedEvent;
EXPECT_CALL(*m_storageMock, loadSetting(key)).WillOnce(Return(std::make_pair(SettingStatus::NOT_AVAILABLE, "")));
EXPECT_CALL(*m_storageMock, storeSetting(_, _, _)).WillOnce(Return(true));
EXPECT_CALL(*m_storageMock, updateSettingStatus(_, _)).WillOnce(InvokeWithoutArgs([&settingsUpdatedEvent] {
settingsUpdatedEvent.wakeUp();
return true;
}));
EXPECT_CALL(m_callbacksMock, applyDbChange(INVALID_VALUE)).WillOnce(Return(std::make_pair(true, DEFAULT_VALUE)));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::LOCAL_CHANGE_IN_PROGRESS));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::LOCAL_CHANGE));
EXPECT_CALL(*m_senderMock, sendChangedEvent(_)).WillOnce(InvokeWithoutArgs([&]() {
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
m_protocol->restoreValue(
std::bind(&MockCallbacks::applyDbChange, &m_callbacksMock, std::placeholders::_1),
std::bind(&MockCallbacks::notifyObservers, &m_callbacksMock, std::placeholders::_1));
settingsUpdatedEvent.wait(TEST_TIMEOUT);
}
Version 1.18.0 alexa-client-sdk Changes in this update: **Enhancements** * Added support for [Bluetooth Interface 2.0](https://developer.amazon.com/docs/alexa/alexa-voice-service/bluetooth.html). This interface adds support for multiple simultaneous connections to Bluetooth peripherals. * Added support for [Audio Focus Manager Library (AFML) Multi Activity](https://developer.amazon.com/docs/alexa/avs-device-sdk/sdk-interaction-model.html). This interface enhances the behavior of a device so it can handle more than one Activity per Channel. * Added the `obfuscatePrivateData` logging method to help remove certain data from logs. * Updated `MediaPlayerObserverInterface` to include metadata about playback states. * Added SDK extension point. You can integrate CMake projects into the SDK without cloning those projects into a subdirectory. **Bug fixes** * Fixed Mac/OSX issue that caused an unresponsive Sample App when not connected to the internet. * Fixed issue that prevented sample app from exiting various states. * Fixed `UIManager` issue that caused an error in the logs when the device with built without the wake word enabled. * Fixed volume issue that caused timers to ascend in volume when setting up ascending alarms. * Fixed alert volume issue that caused any changes to the alert volume to notify observers. * Fixed EQ issue where changes to the EQ band levels didn't notify observers. * Fixed Bluetooth bug that caused short notification sounds from a connected phone to stop audio playback on the device. **Known Issues** * Build errors can occur on the Raspberry Pi due to incorrect linking of the atomic library. A suggested workaround is to add the following `set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -latomic")` to the top most CMake file. * The WebVTT dependency required for `captions` isn't supported for Windows/Android. * Exiting from the setting option takes you back to the Options Menu directly. It doesn't provide a message to indicate that you're back in the main menu. * Failing Unit Tests and AIP Unit tests are disabled on Windows * `AudioInputProcessor` unit tests don't build on Windows when with the `-DCMAKE_BUILD_TYPE=DEBUG` cmake parameter. * Music playback history isn't displayed in the Alexa app for certain account and device types. * When using Gnu Compiler Collection 8+ (GCC 8+), `-Wclass-memaccess` triggers warnings. You can ignore these, they don't cause the build to fail. * Android error `libDefaultClient.so not found` might occur. Resolve this by upgrading to ADB version 1.0.40. * If a device loses a network connection, the lost connection status isn't returned though local TTS. * ACL encounters issues if it receives audio attachments but doesn't consume them. * Media streamed through Bluetooth might abruptly stop. To restart playback, resume the media in the source application or toggle next/previous. * If a connected Bluetooth device is inactive, the Alexa app might indicates that audio is playing. * The Bluetooth agent assumes that the Bluetooth adapter is always connected to a power source. Disconnecting from a power source during operation isn't yet supported. * When using some products, interrupted Bluetooth playback might not resume if other content is locally streamed. * `make integration` isn't available for Android. To run Android integration tests, manually upload the test binary and input file and run ADB. * Alexa might truncate the beginning of speech when responding to text-to-speech (TTS) user events. This only impacts Raspberry Pi devices running Android Things with HDMI output audio. * A reminder TTS message doesn't play if the sample app restarts and loses a network connection. Instead, the default alarm tone plays twice. * `ServerDisconnectIntegratonTest` tests are disabled until they are updated to reflect new service behavior. * The `DirectiveSequencerTest.test_handleBlockingThenImmediatelyThenNonBockingOnSameDialogId` test fails intermittently.
2020-02-19 18:35:26 +00:00
/// Test restore when value is not available in the database for a setting that use cloud authoritative default value.
TEST_F(SharedAVSSettingProtocolTest, test_restoreValueNotAvailableCloudAuthoritative) {
WaitEvent settingsUpdatedEvent;
EXPECT_CALL(*m_storageMock, loadSetting(key)).WillOnce(Return(std::make_pair(SettingStatus::NOT_AVAILABLE, "")));
EXPECT_CALL(*m_storageMock, storeSetting(_, _, _)).WillOnce(Return(true));
EXPECT_CALL(*m_storageMock, updateSettingStatus(_, _)).WillOnce(InvokeWithoutArgs([&settingsUpdatedEvent] {
settingsUpdatedEvent.wakeUp();
return true;
}));
EXPECT_CALL(m_callbacksMock, applyDbChange(INVALID_VALUE)).WillOnce(Return(std::make_pair(true, DEFAULT_VALUE)));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE_IN_PROGRESS));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE));
EXPECT_CALL(*m_senderMock, sendReportEvent(_)).WillOnce(InvokeWithoutArgs([&]() {
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
auto protocol =
SharedAVSSettingProtocol::create(METADATA, m_senderMock, m_storageMock, m_mockConnectionManager, true);
protocol->restoreValue(
std::bind(&MockCallbacks::applyDbChange, &m_callbacksMock, std::placeholders::_1),
std::bind(&MockCallbacks::notifyObservers, &m_callbacksMock, std::placeholders::_1));
settingsUpdatedEvent.wait(TEST_TIMEOUT);
}
Version 1.15 alexa-client-sdk Changes in this update: **Enhancements** * Added `SystemSoundPlayer` to [ApplicationUtilities](https://alexa.github.io/avs-device-sdk/namespacealexa_client_s_d_k_1_1application_utilities.html). `SystemSoundPlayer` is a new class that plays pre-defined sounds. Sounds currently supported include the wake word notification and the end of speech tone. This change is internal and you don't need to update your code. * Removed [Echo Spatial Perception (ESP)](https://developer.amazon.com/blogs/alexa/post/042be85c-5a62-4c55-a18d-d7a82cf394df/esp-moves-to-the-cloud-for-alexa-enabled-devices) functionality from the Alexa Voice Service (AVS) device SDK. Make sure you download and test your devices using the new AVS SDK sample app. If you're using an older version of the sample app, manually remove any references to ESP or errors occur during compile. * Added `onNotificationReceived` to `NotificationsObserverInterface`. `onNotificationReceived` broadcasts when `NotificationsObserverInterface` receives a new notification, instead of only sending the indicator state. This is important if you support a feature that requires a distinct signal for each notification received. See [NotificationsObserverInterface](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1avs_common_1_1sdk_interfaces_1_1_notifications_observer_interface.html) for more details. * Added support for [Multilingual Mode](https://developer.amazon.com/docs/alexa-voice-service/system.html#localecombinations). With this enabled, Alexa automatically detects what language a user speaks by analyzing the spoken wake word and proceeding utterances. Once Alexa identifies the language, all corresponding responses are in the same language. The current supported language pairs are: - `[ "en-US", "es-US" ]` - `[ "es-US", "en-US" ]` - `[ "en-IN", "hi-IN" ]` - `[ "hi-IN", "en-IN" ]` - `[ "en-CA", "fr-CA" ]` - `[ "fr-CA", "en-CA" ]` <br/> **IMPORTANT**: Specify the locales your device supports in the [localeCombinations](https://developer.amazon.com/docs/alexa-voice-service/system.html#localecombinations) field in AlexaClientSDKConfig.json. This field can't be empty. If you don't set these values, the sample app fails to run. * Added two new system settings, [Timezone](https://developer.amazon.com/docs/alexa-voice-service/system.html#settimezone) and [Locale](https://developer.amazon.com/docs/alexa-voice-service/system.html#locales). - Timezone: For example, you can set the `defaultTimezone` to `America/Vancouver`. If you don't set a value, `GMT` is set as the default value. If you set a new timezone, make sure that your AVS system settings and default timezone stay in sync. To handle this, use the new class `SystemTimeZoneInterface`. See [System Interface > SetTimeZone](https://developer.amazon.com/docs/alexa-voice-service/system.html#settimezone) for more information. - Locale: For example, you can set `defaultLocale` to `en-GB`, instead of the default `en-US`. * The [SpeechRecognizer](https://developer.amazon.com/docs/alexa-voice-service/speechrecognizer.html) interface now supports the following functionalities. - Change wake word (`Alexa` supported for now). - Toggle start of request tone on/off. - Toggle End of request tone on/off. * Deprecated the [CapabilityAgents](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1avs_common_1_1avs_1_1_capability_agent.html) `Settings{…}` library. `Settings {…}` now maps to an interface that's no longer supported. You might need to update your code to handle these changes. Read [Settings Interface](https://developer.amazon.com/docs/alexa-voice-service/per-interface-settings.html) for more details. * Added support for three new locals: Spanish - United States (ES_US), Hindi - India (HI_IN), and Brazilian - Portuguese (PT_BR). * Linked the atomic library to the sample app to prevent build errors on Raspberry Pi. **Bug Fixes** * Fixed resource leaking in [EqualizerCapabilityAgent](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1capability_agents_1_1equalizer_1_1_equalizer_capability_agent.html) after engine shutdown. * [Issue 1391:](https://github.com/alexa/avs-device-sdk/pull/1391) Fixed an issue where [SQLiteDeviceSettingsStorage::open](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1settings_1_1storage_1_1_s_q_lite_device_setting_storage.html#a7733e56145916f7ff265c5c950add492) tries to acquire a mutex twice, resulting in deadlock. * [Issue 1468:](https://github.com/alexa/avs-device-sdk/issues/1468) Fixed a bug in [AudioPlayer::cancelDirective](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1capability_agents_1_1audio_player_1_1_audio_player.html#a2c710c16f3627790fcc3238d34da9361) that causes a crash. * Fixed Windows install script that caused the sample app build to fail - removed pip, flask, requests, and commentjson dependencies from the mingw.sh helper script. * Fixed issue: notifications failed to sync upon device initialization. For example, let's say you had two devices - one turned on and the other turned off. After clearing the notification on the first device, it still showed up on the second device after turning it on. * Fixed issue: barging in on a reminder caused it to stick in an inconsistent state, blocking subsequent reminders. For example, if a reminder was going off and you interrupted it, the reminder would get persist indefinitely. You could schedule future reminders, but they wouldn't play. Saying “Alexa stop” or rebooting the device fixed the “stuck” reminder. **Known Issues** * Music playback history isn't displayed in the Alexa app for certain account and device types. * When using Gnu Compiler Collection 8+ (GCC 8+), `-Wclass-memaccess` triggers warnings. You can ignore these, they don't cause the build to fail. * Android error `libDefaultClient.so not found` might occur. Resolve this by upgrading to ADB version 1.0.40. * If a device loses a network connection, the lost connection status isn't returned via local TTS. * ACL encounters issues if it receives audio attachments but doesn't consume them. * `SpeechSynthesizerState` uses `GAINING_FOCUS` and `LOSING_FOCUS` as a workaround for handling intermediate states. * Media steamed through Bluetooth might abruptly stop. To restart playback, resume the media in the source application or toggle next/previous. * If a connected Bluetooth device is inactive, the Alexa app might indicates that audio is playing. * The Bluetooth agent assumes that the Bluetooth adapter is always connected to a power source. Disconnecting from a power source during operation isn't yet supported. * When using some products, interrupted Bluetooth playback might not resume if other content is locally streamed. * `make integration` isn't available for Android. To run Android integration tests, manually upload the test binary and input file and run ADB. * Alexa might truncate the beginning of speech when responding to text-to-speech (TTS) user events. This only impacts Raspberry Pi devices running Android Things with HDMI output audio. * A reminder TTS message doesn't play if the sample app restarts and loses a network connection. Instead, the default alarm tone plays twice. * `ServerDisconnectIntegratonTest` tests are disabled until they are updated to reflect new service behavior. * Bluetooth initialization must complete before connecting devices, otherwise devices are ignored. * The `DirectiveSequencerTest.test_handleBlockingThenImmediatelyThenNonBockingOnSameDialogId` test fails intermittently.
2019-09-25 18:49:09 +00:00
/// Test restore when the value is available and synchronized.
TEST_F(SharedAVSSettingProtocolTest, test_restoreSynchronized) {
EXPECT_CALL(*m_storageMock, loadSetting(key))
.WillOnce(Return(std::make_pair(SettingStatus::SYNCHRONIZED, DB_VALUE)));
EXPECT_CALL(m_callbacksMock, applyDbChange(DB_VALUE)).WillOnce(Return(std::make_pair(true, DB_VALUE)));
m_protocol->restoreValue(
std::bind(&MockCallbacks::applyDbChange, &m_callbacksMock, std::placeholders::_1),
std::bind(&MockCallbacks::notifyObservers, &m_callbacksMock, std::placeholders::_1));
}
/// Test success flow for AVS request.
TEST_F(SharedAVSSettingProtocolTest, test_AVSChangeRequest) {
WaitEvent event;
InSequence inSequence;
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE_IN_PROGRESS));
EXPECT_CALL(m_callbacksMock, applyChange()).WillOnce(Return(std::make_pair(true, NEW_VALUE)));
EXPECT_CALL(*m_storageMock, storeSetting(key, NEW_VALUE, SettingStatus::AVS_CHANGE_IN_PROGRESS))
.WillOnce(Return(true));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE));
EXPECT_CALL(*m_senderMock, sendReportEvent(NEW_VALUE)).WillOnce(InvokeWithoutArgs([&] {
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
EXPECT_CALL(*m_storageMock, updateSettingStatus(key, SettingStatus::SYNCHRONIZED))
.WillOnce(InvokeWithoutArgs([&event] {
event.wakeUp();
return true;
}));
m_protocol->avsChange(
std::bind(&MockCallbacks::applyChange, &m_callbacksMock),
std::bind(&MockCallbacks::revertChange, &m_callbacksMock),
std::bind(&MockCallbacks::notifyObservers, &m_callbacksMock, std::placeholders::_1));
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
}
/// Test set value failed for AVS request.
TEST_F(SharedAVSSettingProtocolTest, test_AVSChangeRequestSetFailed) {
WaitEvent event;
InSequence inSequence;
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE_IN_PROGRESS));
EXPECT_CALL(m_callbacksMock, applyChange()).WillOnce(Return(std::make_pair(false, DB_VALUE)));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE_FAILED));
EXPECT_CALL(*m_senderMock, sendReportEvent(DB_VALUE)).WillOnce(InvokeWithoutArgs([&] {
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
EXPECT_CALL(*m_storageMock, updateSettingStatus(key, SettingStatus::SYNCHRONIZED))
.WillOnce(InvokeWithoutArgs([&event] {
event.wakeUp();
return true;
}));
m_protocol->avsChange(
std::bind(&MockCallbacks::applyChange, &m_callbacksMock),
std::bind(&MockCallbacks::revertChange, &m_callbacksMock),
std::bind(&MockCallbacks::notifyObservers, &m_callbacksMock, std::placeholders::_1));
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
}
/// Test store value failed. Revert should be called and AVS notified of previous value.
TEST_F(SharedAVSSettingProtocolTest, test_AVSChangeRequestStoreFailed) {
WaitEvent event;
InSequence inSequence;
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE_IN_PROGRESS));
EXPECT_CALL(m_callbacksMock, applyChange()).WillOnce(Return(std::make_pair(true, NEW_VALUE)));
EXPECT_CALL(*m_storageMock, storeSetting(key, NEW_VALUE, SettingStatus::AVS_CHANGE_IN_PROGRESS))
.WillOnce(Return(false));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE_FAILED));
EXPECT_CALL(m_callbacksMock, revertChange()).WillOnce(Return(DEFAULT_VALUE));
EXPECT_CALL(*m_senderMock, sendReportEvent(DEFAULT_VALUE)).WillOnce(InvokeWithoutArgs([&] {
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
EXPECT_CALL(*m_storageMock, updateSettingStatus(key, SettingStatus::SYNCHRONIZED))
.WillOnce(InvokeWithoutArgs([&event] {
event.wakeUp();
return true;
}));
m_protocol->avsChange(
std::bind(&MockCallbacks::applyChange, &m_callbacksMock),
std::bind(&MockCallbacks::revertChange, &m_callbacksMock),
std::bind(&MockCallbacks::notifyObservers, &m_callbacksMock, std::placeholders::_1));
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
}
/// Test send event failed for avs request.
TEST_F(SharedAVSSettingProtocolTest, test_AVSChangeRequestSendEventFailed) {
WaitEvent event;
InSequence inSequence;
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE_IN_PROGRESS));
EXPECT_CALL(m_callbacksMock, applyChange()).WillOnce(Return(std::make_pair(true, NEW_VALUE)));
EXPECT_CALL(*m_storageMock, storeSetting(key, NEW_VALUE, SettingStatus::AVS_CHANGE_IN_PROGRESS))
.WillOnce(Return(true));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE));
EXPECT_CALL(*m_senderMock, sendReportEvent(NEW_VALUE)).WillOnce(InvokeWithoutArgs([&event] {
event.wakeUp();
std::promise<bool> retPromise;
retPromise.set_value(false);
return retPromise.get_future();
}));
m_protocol->avsChange(
std::bind(&MockCallbacks::applyChange, &m_callbacksMock),
std::bind(&MockCallbacks::revertChange, &m_callbacksMock),
std::bind(&MockCallbacks::notifyObservers, &m_callbacksMock, std::placeholders::_1));
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
}
/// Test success flow for local request.
TEST_F(SharedAVSSettingProtocolTest, test_localRequest) {
WaitEvent event;
InSequence inSequence;
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::LOCAL_CHANGE_IN_PROGRESS));
EXPECT_CALL(m_callbacksMock, applyChange()).WillOnce(Return(std::make_pair(true, NEW_VALUE)));
EXPECT_CALL(*m_storageMock, storeSetting(key, NEW_VALUE, SettingStatus::LOCAL_CHANGE_IN_PROGRESS))
.WillOnce(Return(true));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::LOCAL_CHANGE));
EXPECT_CALL(*m_senderMock, sendChangedEvent(NEW_VALUE)).WillOnce(InvokeWithoutArgs([&]() {
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
EXPECT_CALL(*m_storageMock, updateSettingStatus(key, SettingStatus::SYNCHRONIZED))
.WillOnce(InvokeWithoutArgs([&event] {
event.wakeUp();
return true;
}));
m_protocol->localChange(
std::bind(&MockCallbacks::applyChange, &m_callbacksMock),
std::bind(&MockCallbacks::revertChange, &m_callbacksMock),
std::bind(&MockCallbacks::notifyObservers, &m_callbacksMock, std::placeholders::_1));
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
}
/// Test set value failed during local request.
TEST_F(SharedAVSSettingProtocolTest, test_localRequestSetFailed) {
InSequence inSequence;
EXPECT_CALL(m_callbacksMock, applyChange()).WillOnce(Return(std::make_pair(false, DB_VALUE)));
WaitEvent event;
auto notifyObservers = [&event](SettingNotifications notification) {
switch (notification) {
case SettingNotifications::AVS_CHANGE_IN_PROGRESS:
case SettingNotifications::LOCAL_CHANGE:
case SettingNotifications::AVS_CHANGE:
case SettingNotifications::AVS_CHANGE_FAILED:
case SettingNotifications::LOCAL_CHANGE_CANCELLED:
case SettingNotifications::AVS_CHANGE_CANCELLED:
FAIL() << notification;
break;
case SettingNotifications::LOCAL_CHANGE_IN_PROGRESS:
break;
case SettingNotifications::LOCAL_CHANGE_FAILED:
event.wakeUp();
break;
}
};
m_protocol->localChange(
std::bind(&MockCallbacks::applyChange, &m_callbacksMock),
std::bind(&MockCallbacks::revertChange, &m_callbacksMock),
notifyObservers);
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
}
/// Test store value to database failed for local request.
TEST_F(SharedAVSSettingProtocolTest, test_localRequestStoreFailed) {
InSequence inSequence;
EXPECT_CALL(m_callbacksMock, applyChange()).WillOnce(Return(std::make_pair(true, NEW_VALUE)));
EXPECT_CALL(*m_storageMock, storeSetting(key, NEW_VALUE, SettingStatus::LOCAL_CHANGE_IN_PROGRESS))
.WillOnce(Return(false));
EXPECT_CALL(m_callbacksMock, revertChange()).WillOnce(Return(DEFAULT_VALUE));
WaitEvent event;
auto notifyObservers = [&event](SettingNotifications notification) {
switch (notification) {
case SettingNotifications::AVS_CHANGE_IN_PROGRESS:
case SettingNotifications::LOCAL_CHANGE:
case SettingNotifications::AVS_CHANGE:
case SettingNotifications::AVS_CHANGE_FAILED:
case SettingNotifications::LOCAL_CHANGE_CANCELLED:
case SettingNotifications::AVS_CHANGE_CANCELLED:
FAIL() << notification;
break;
case SettingNotifications::LOCAL_CHANGE_IN_PROGRESS:
break;
case SettingNotifications::LOCAL_CHANGE_FAILED:
event.wakeUp();
break;
}
};
m_protocol->localChange(
std::bind(&MockCallbacks::applyChange, &m_callbacksMock),
std::bind(&MockCallbacks::revertChange, &m_callbacksMock),
notifyObservers);
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
}
/// Test send changed event failed for local request. In this case, we should not update the database with SYNCHRONIZED.
TEST_F(SharedAVSSettingProtocolTest, test_localRequestSendEventFailed) {
WaitEvent event;
InSequence inSequence;
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::LOCAL_CHANGE_IN_PROGRESS));
EXPECT_CALL(m_callbacksMock, applyChange()).WillOnce(Return(std::make_pair(true, NEW_VALUE)));
EXPECT_CALL(*m_storageMock, storeSetting(key, NEW_VALUE, SettingStatus::LOCAL_CHANGE_IN_PROGRESS))
.WillOnce(Return(true));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::LOCAL_CHANGE));
EXPECT_CALL(*m_senderMock, sendChangedEvent(NEW_VALUE)).WillOnce(InvokeWithoutArgs([&event] {
event.wakeUp();
std::promise<bool> retPromise;
retPromise.set_value(false);
return retPromise.get_future();
}));
m_protocol->localChange(
std::bind(&MockCallbacks::applyChange, &m_callbacksMock),
std::bind(&MockCallbacks::revertChange, &m_callbacksMock),
std::bind(&MockCallbacks::notifyObservers, &m_callbacksMock, std::placeholders::_1));
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
}
/// Verify that after network disconnect / reconnect will send out setting events that was changed locally while
/// disconnected.
TEST_F(SharedAVSSettingProtocolTest, test_localChangeSettingOfflineSynchronization) {
WaitEvent event;
InSequence inSequence;
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::LOCAL_CHANGE_IN_PROGRESS));
EXPECT_CALL(m_callbacksMock, applyChange()).WillOnce(Return(std::make_pair(true, NEW_VALUE)));
EXPECT_CALL(*m_storageMock, storeSetting(key, NEW_VALUE, SettingStatus::LOCAL_CHANGE_IN_PROGRESS))
.WillOnce(Return(true));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::LOCAL_CHANGE));
// Return false to simulate a disconnected network.
EXPECT_CALL(*m_senderMock, sendChangedEvent(NEW_VALUE)).WillOnce(InvokeWithoutArgs([&event] {
event.wakeUp();
std::promise<bool> retPromise;
retPromise.set_value(false);
return retPromise.get_future();
}));
m_protocol->localChange(
std::bind(&MockCallbacks::applyChange, &m_callbacksMock),
std::bind(&MockCallbacks::revertChange, &m_callbacksMock),
std::bind(&MockCallbacks::notifyObservers, &m_callbacksMock, std::placeholders::_1));
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
event.reset();
EXPECT_CALL(*m_storageMock, loadSetting(key))
.WillOnce(Return(std::make_pair(SettingStatus::LOCAL_CHANGE_IN_PROGRESS, NEW_VALUE)));
EXPECT_CALL(*m_senderMock, sendChangedEvent(_)).WillOnce(InvokeWithoutArgs([] {
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
EXPECT_CALL(*m_storageMock, updateSettingStatus(key, SettingStatus::SYNCHRONIZED))
.WillOnce(InvokeWithoutArgs([&event] {
event.wakeUp();
return true;
}));
m_protocol->connectionStatusChangeCallback(true);
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
event.reset();
}
/// Verify that after network disconnect / reconnect will send out setting events that was changed through AVS
/// directive.
TEST_F(SharedAVSSettingProtocolTest, test_avsChangeSettingOfflineSynchronization) {
WaitEvent event;
InSequence inSequence;
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE_IN_PROGRESS));
EXPECT_CALL(m_callbacksMock, applyChange()).WillOnce(Return(std::make_pair(true, NEW_VALUE)));
EXPECT_CALL(*m_storageMock, storeSetting(key, NEW_VALUE, SettingStatus::AVS_CHANGE_IN_PROGRESS))
.WillOnce(Return(true));
EXPECT_CALL(m_callbacksMock, notifyObservers(SettingNotifications::AVS_CHANGE));
// Return false to simulate a disconnected network.
EXPECT_CALL(*m_senderMock, sendReportEvent(NEW_VALUE)).WillOnce(InvokeWithoutArgs([&event] {
event.wakeUp();
std::promise<bool> retPromise;
retPromise.set_value(false);
return retPromise.get_future();
}));
m_protocol->avsChange(
std::bind(&MockCallbacks::applyChange, &m_callbacksMock),
std::bind(&MockCallbacks::revertChange, &m_callbacksMock),
std::bind(&MockCallbacks::notifyObservers, &m_callbacksMock, std::placeholders::_1));
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
event.reset();
EXPECT_CALL(*m_storageMock, loadSetting(key))
.WillOnce(Return(std::make_pair(SettingStatus::AVS_CHANGE_IN_PROGRESS, NEW_VALUE)));
EXPECT_CALL(*m_senderMock, sendReportEvent(NEW_VALUE)).WillOnce(InvokeWithoutArgs([] {
std::promise<bool> retPromise;
retPromise.set_value(true);
return retPromise.get_future();
}));
EXPECT_CALL(*m_storageMock, updateSettingStatus(key, SettingStatus::SYNCHRONIZED))
.WillOnce(InvokeWithoutArgs([&event] {
event.wakeUp();
return true;
}));
m_protocol->connectionStatusChangeCallback(true);
EXPECT_TRUE(event.wait(TEST_TIMEOUT));
}
/// Verify that multiple AVS setting changes will be merged.
/// The setting will be changed multiple times immediately one after the other.
/// It's expected that only at most 2 settings are sent, that is, at least 1 has been canceled and the last value sent
/// is the latest one.
TEST_F(SharedAVSSettingProtocolTest, test_multipleAVSChanges) {
testMultipleChanges(false);
}
/// Verify that multiple local setting changes will be merged.
/// The setting will be changed multiple times immediately one after the other.
/// It's expected that only at most 2 settings are sent, that is, at least 1 has been canceled and the last value sent
/// is the latest one.
TEST_F(SharedAVSSettingProtocolTest, test_multipleLocalChanges) {
testMultipleChanges(true);
}
} // namespace test
} // namespace settings
} // namespace alexaClientSDK