avs-device-sdk/AVSCommon/Utils/test/PooledMediaPlayerFactoryTes...

194 lines
6.3 KiB
C++
Raw Normal View History

Version 1.16 alexa-client-sdk Changes in this update: **Enhancements** - Added support for SpeechSynthesizer v.1.2 which includes the new `playBehaviour` directive. For more information, see [SpeechSynthesizer v1.2](https://github.com/alexa/avs-device-sdk/wiki/SpeechSynthesizer-Interface-v1.2). - Added support for pre-buffering in [AudioPlayer](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1capability_agents_1_1audio_player_1_1_audio_player.html). You can optionally choose the number of instances MediaPlayer uses in the [AlexaClientSDKconfig.json](https://github.com/alexa/avs-device-sdk/blob/master/Integration/AlexaClientSDKConfig.json). Important: the contract for [MediaPlayerInterface](https://alexa.github.io/avs-device-sdk/classalexa_client_s_d_k_1_1avs_common_1_1utils_1_1media_player_1_1_media_player_interface.html) has changed. You must now make sure that the `SourceId` value returned by `setSource()` is unique across all instances. - AudioPlayer is now licensed under the Amazon Software License instead of the Apache Software License. **Bug Fixes** - Fixed Android issue that caused the build script to ignore PKG_CONFIG_PATH. This sometimes caused the build to use a preinstalled dependency instead of the specific version downloaded by the Android script (e.g - openssl). - Fixed Android issue that prevented the Sample app from running at the same time as other applications using the microphone. Android doesn't inherently allow two applications to use the microphone. Pressing the mute button now temporarily stops Alexa from accessing the microphone. - Added 'quit' (– q) to the settings sub menu. - Fixed outdated dependencies issue in the Windows install script. - Fixed reminders issue that caused Notification LEDs to stay on, even after dismissing the alert. **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. * On some devices, Alexa gets stuck in a permanent listening state. Pressing `t` and `h` in the Sample App doesn't exit the listening state. * Exiting the `settings` menu doesn't provide a message to indicate that you are back in the main menu.
2019-10-25 20:19:44 +00:00
/*
* Copyright 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 <AVSCommon/Utils/MediaPlayer/PooledMediaPlayerFactory.h>
#include <AVSCommon/Utils/Logger/Logger.h>
#include <AVSCommon/Utils/MediaPlayer/MockMediaPlayer.h>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
namespace alexaClientSDK {
namespace mediaPlayer {
namespace test {
using namespace ::testing;
using namespace avsCommon::utils::mediaPlayer;
using namespace avsCommon::utils::mediaPlayer::test;
/// String to identify log entries originating from this file.
static const std::string TAG("PooledMediaPlayerFactoryTest");
/**
* Create a LogEntry using this file's TAG and the specified event string.
*
* @param The event string for this @c LogEntry.
*/
#define LX(event) alexaClientSDK::avsCommon::utils::logger::LogEntry(TAG, event)
class TestFactoryObserver : public MediaPlayerFactoryObserverInterface {
public:
TestFactoryObserver() = default;
virtual ~TestFactoryObserver() = default;
MOCK_METHOD0(onReadyToProvideNextPlayer, void());
};
class PooledMediaPlayerFactoryTest : public ::testing::Test {
public:
PooledMediaPlayerFactoryTest() = default;
virtual ~PooledMediaPlayerFactoryTest() = default;
void SetUp() override;
void TearDown() override;
const std::vector<std::shared_ptr<MediaPlayerInterface>> createPlayers(int playerCnt);
std::shared_ptr<TestFactoryObserver> m_mockObserver;
std::shared_ptr<PooledMediaPlayerFactory> m_factory;
std::vector<std::shared_ptr<MediaPlayerInterface>> m_playerList;
};
void PooledMediaPlayerFactoryTest::SetUp() {
MockMediaPlayer::enableConcurrentMediaPlayers();
m_mockObserver = std::make_shared<TestFactoryObserver>();
}
void PooledMediaPlayerFactoryTest::TearDown() {
for (std::shared_ptr<MediaPlayerInterface> player : m_playerList) {
static_cast<MockMediaPlayer*>(player.get())->shutdown();
}
m_playerList.clear();
if (m_factory) {
m_factory.reset();
}
m_mockObserver.reset();
}
const std::vector<std::shared_ptr<MediaPlayerInterface>> PooledMediaPlayerFactoryTest::createPlayers(int playerCnt) {
for (int i = 0; i < playerCnt; i++) {
m_playerList.push_back(MockMediaPlayer::create());
}
return m_playerList;
}
TEST_F(PooledMediaPlayerFactoryTest, test_acquirePlayers) {
for (int i = 1; i <= 3; i++) {
m_factory = PooledMediaPlayerFactory::create(createPlayers(i));
for (int j = 0; j < i; j++) {
auto player = m_factory->acquireMediaPlayer();
ASSERT_NE(player, nullptr);
}
auto player = m_factory->acquireMediaPlayer();
ASSERT_EQ(player, nullptr);
m_playerList.clear();
}
}
TEST_F(PooledMediaPlayerFactoryTest, test_releasePlayers) {
m_factory = PooledMediaPlayerFactory::create(createPlayers(1));
auto player = m_factory->acquireMediaPlayer();
ASSERT_NE(player, nullptr);
ASSERT_TRUE(m_factory->releaseMediaPlayer(player));
// double release
ASSERT_FALSE(m_factory->releaseMediaPlayer(player));
// not acquired
auto newPlayer = MockMediaPlayer::create();
ASSERT_FALSE(m_factory->releaseMediaPlayer(newPlayer));
newPlayer->shutdown();
// nullptr
ASSERT_FALSE(m_factory->releaseMediaPlayer(nullptr));
}
TEST_F(PooledMediaPlayerFactoryTest, test_recyclePlayers) {
for (int i = 1; i <= 10; i++) {
m_factory = PooledMediaPlayerFactory::create(createPlayers(i));
for (int j = 0; j < i; j++) {
auto player = m_factory->acquireMediaPlayer();
ASSERT_NE(player, nullptr);
ASSERT_TRUE(m_factory->releaseMediaPlayer(player));
}
for (int j = 0; j < i * 5; j++) {
auto player = m_factory->acquireMediaPlayer();
auto pos = std::find(m_playerList.begin(), m_playerList.end(), player);
ASSERT_NE(pos, m_playerList.end());
ASSERT_TRUE(m_factory->releaseMediaPlayer(player));
}
m_playerList.clear();
}
}
TEST_F(PooledMediaPlayerFactoryTest, test_onReadyCallback) {
m_factory = PooledMediaPlayerFactory::create(createPlayers(2));
m_factory->addObserver(m_mockObserver);
int count = 0;
// onReadyToProvideNextPlayer should only be called when the
// pool player count goes from 0 -> 1
EXPECT_CALL(*m_mockObserver, onReadyToProvideNextPlayer()).Times(2).WillRepeatedly(Invoke([&count]() { count++; }));
;
auto player1 = m_factory->acquireMediaPlayer();
ASSERT_NE(player1, nullptr);
auto player2 = m_factory->acquireMediaPlayer();
ASSERT_NE(player2, nullptr);
EXPECT_EQ(0, count);
ASSERT_TRUE(m_factory->releaseMediaPlayer(player1));
EXPECT_EQ(1, count);
ASSERT_TRUE(m_factory->releaseMediaPlayer(player2));
EXPECT_EQ(1, count);
player1 = m_factory->acquireMediaPlayer();
ASSERT_NE(player1, nullptr);
ASSERT_TRUE(m_factory->releaseMediaPlayer(player1));
EXPECT_EQ(1, count);
player1 = m_factory->acquireMediaPlayer();
ASSERT_NE(player1, nullptr);
player2 = m_factory->acquireMediaPlayer();
ASSERT_NE(player2, nullptr);
ASSERT_TRUE(m_factory->releaseMediaPlayer(player1));
EXPECT_EQ(2, count);
ASSERT_TRUE(m_factory->releaseMediaPlayer(player2));
EXPECT_EQ(2, count);
}
TEST_F(PooledMediaPlayerFactoryTest, test_isMediaPlayerAvailable) {
m_factory = PooledMediaPlayerFactory::create(createPlayers(2));
ASSERT_TRUE(m_factory->isMediaPlayerAvailable());
auto player1 = m_factory->acquireMediaPlayer();
ASSERT_TRUE(m_factory->isMediaPlayerAvailable());
auto player2 = m_factory->acquireMediaPlayer();
ASSERT_FALSE(m_factory->isMediaPlayerAvailable());
m_factory->releaseMediaPlayer(player1);
ASSERT_TRUE(m_factory->isMediaPlayerAvailable());
m_factory->releaseMediaPlayer(player2);
}
} // namespace test
} // namespace mediaPlayer
} // namespace alexaClientSDK