/* * Copyright 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 #include #include #include #include #include "AndroidSLESMediaPlayer/AndroidSLESSpeaker.h" /// String to identify log entries originating from this file. static const std::string TAG{"AndroidSLESSpeakerTest"}; /** * 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) namespace alexaClientSDK { namespace mediaPlayer { namespace android { namespace test { using namespace ::testing; using namespace applicationUtilities::androidUtilities; using namespace applicationUtilities::androidUtilities::test; using namespace avsCommon::avs::speakerConstants; using MockVolumeInterface = MockInterfaceImpl; /// Represents an invalid device maximum value. OpenSL ES determines that device max volume is 0 or above. static constexpr SLmillibel INVALID_MAX_VOLUME = -10; static SLmillibel g_volume; static SLmillibel g_maxVolume; static SLboolean g_mute; /// Mock @c GetVolume succeeds. static SLresult mockGetVolume(SLVolumeItf self, SLmillibel* volume) { *volume = g_volume; return SL_RESULT_SUCCESS; } /// Mock @c GetVolume fails. static SLresult mockGetVolumeFailed(SLVolumeItf self, SLmillibel* volume) { return SL_RESULT_INTERNAL_ERROR; } /// Mock @c SetVolume succeeds. static SLresult mockSetVolume(SLVolumeItf self, SLmillibel volume) { g_volume = volume; return SL_RESULT_SUCCESS; } /// Mock @c SetVolume fails. static SLresult mockSetVolumeFailed(SLVolumeItf self, SLmillibel volume) { return SL_RESULT_INTERNAL_ERROR; } /// Mock @c GetMute succeeds. static SLresult mockGetMute(SLVolumeItf self, SLboolean* mute) { *mute = g_mute; return SL_RESULT_SUCCESS; } /// Mock @c GetMute fails. static SLresult mockGetMuteFailed(SLVolumeItf self, SLboolean* mute) { return SL_RESULT_INTERNAL_ERROR; } /// Mock @c SetMute succeeds. static SLresult mockSetMute(SLVolumeItf self, SLboolean mute) { g_mute = mute; return SL_RESULT_SUCCESS; } /// Mock @c SetMute fails. static SLresult mockSetMuteFailed(SLVolumeItf self, SLboolean mute) { return SL_RESULT_INTERNAL_ERROR; } /// Mock @c GetMaxVolume succeeds. static SLresult mockGetMaxVolume(SLVolumeItf self, SLmillibel* volume) { *volume = g_maxVolume; return SL_RESULT_SUCCESS; } class AndroidSLESSpeakerTest : public Test { protected: void SetUp() override; /// Pointer to android engine. std::shared_ptr m_engine; /// Mock the output mix object. std::shared_ptr m_outputMix; /// Mock the OpenSL ES speaker wrapper. std::shared_ptr m_objectMock; /// Mock the actual OpenSL ES speaker object. std::shared_ptr m_slObject; /// Mock the OpenSL ES volume interface. std::shared_ptr m_volumeMock; /// The speaker that is under test. std::unique_ptr m_speaker; }; void AndroidSLESSpeakerTest::SetUp() { g_volume = 0; g_mute = 0; g_maxVolume = 0; m_engine = AndroidSLESEngine::create(); m_outputMix = AndroidSLESObject::create(MockAndroidSLESObject().getObject()); m_objectMock = std::make_shared(); m_volumeMock = std::make_shared(); m_slObject = AndroidSLESObject::create(m_objectMock->getObject()); m_objectMock->mockGetInterface(SL_IID_VOLUME, m_volumeMock); m_volumeMock->get().GetVolumeLevel = mockGetVolume; m_volumeMock->get().SetVolumeLevel = mockSetVolume; m_volumeMock->get().GetMaxVolumeLevel = mockGetMaxVolume; m_volumeMock->get().GetMute = mockGetMute; m_volumeMock->get().SetMute = mockSetMute; m_speaker = AndroidSLESSpeaker::create(m_engine, m_outputMix, m_slObject); ASSERT_NE(m_speaker, nullptr); } /// Test speaker create with null engine. TEST_F(AndroidSLESSpeakerTest, test_createNullEngine) { auto speaker = AndroidSLESSpeaker::create(nullptr, m_outputMix, m_slObject); EXPECT_EQ(speaker, nullptr); } /// Test speaker create with null output mix. TEST_F(AndroidSLESSpeakerTest, test_createNullSpeaker) { auto speaker = AndroidSLESSpeaker::create(m_engine, m_outputMix, nullptr); EXPECT_EQ(speaker, nullptr); } /// Test speaker create with null engine. TEST_F(AndroidSLESSpeakerTest, test_createInterfaceUnavailable) { m_objectMock->mockGetInterface(SL_IID_VOLUME, nullptr); auto speaker = AndroidSLESSpeaker::create(m_engine, m_outputMix, m_slObject); EXPECT_EQ(speaker, nullptr); } /// Test speaker create with invalid device configuration. TEST_F(AndroidSLESSpeakerTest, test_createInvalidMaxVolume) { auto mockInvalidMaxVolume = [](SLVolumeItf self, SLmillibel* volume) -> SLresult { *volume = INVALID_MAX_VOLUME; return SL_RESULT_SUCCESS; }; m_volumeMock->get().GetMaxVolumeLevel = mockInvalidMaxVolume; auto speaker = AndroidSLESSpeaker::create(m_engine, m_outputMix, m_slObject); EXPECT_EQ(speaker, nullptr); } /// Test set and get volume succeed. TEST_F(AndroidSLESSpeakerTest, test_setVolumeSucceed) { int8_t volume = (AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) / 2; // Set volume to 50% of max. EXPECT_TRUE(m_speaker->setVolume(volume)); AndroidSLESSpeaker::SpeakerSettings settings; EXPECT_TRUE(m_speaker->getSpeakerSettings(&settings)); EXPECT_EQ(settings.volume, volume); } /// Test set volume failed. TEST_F(AndroidSLESSpeakerTest, test_setVolumeFailed) { m_volumeMock->get().SetVolumeLevel = mockSetVolumeFailed; int8_t volume = (AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) / 2; // Set volume to 50% of max. EXPECT_FALSE(m_speaker->setVolume(volume)); } /// Test get volume failed. TEST_F(AndroidSLESSpeakerTest, test_getVolumeFailed) { m_volumeMock->get().GetVolumeLevel = mockGetVolumeFailed; AndroidSLESSpeaker::SpeakerSettings settings; EXPECT_FALSE(m_speaker->getSpeakerSettings(&settings)); } /// Test set and get mute succeed. TEST_F(AndroidSLESSpeakerTest, test_setMuteSucceed) { bool mute = !g_mute; // Toggle mute. EXPECT_TRUE(m_speaker->setMute(mute)); AndroidSLESSpeaker::SpeakerSettings settings; EXPECT_TRUE(m_speaker->getSpeakerSettings(&settings)); EXPECT_EQ(settings.mute, mute); } /// Test set mute failed. TEST_F(AndroidSLESSpeakerTest, test_setMuteFailed) { m_volumeMock->get().SetMute = mockSetMuteFailed; EXPECT_FALSE(m_speaker->setMute(!g_mute)); } /// Test get mute failed. TEST_F(AndroidSLESSpeakerTest, test_getMuteFailed) { m_volumeMock->get().GetMute = mockGetMuteFailed; AndroidSLESSpeaker::SpeakerSettings settings; EXPECT_FALSE(m_speaker->getSpeakerSettings(&settings)); } /// Test set and get volume on values in different ranges to guarantee accuracy. TEST_F(AndroidSLESSpeakerTest, test_setVolumeAccuracy) { auto speakerPtr = m_speaker.get(); auto check = [speakerPtr](int8_t avsVolume) { AndroidSLESSpeaker::SpeakerSettings settings; EXPECT_TRUE(speakerPtr->setVolume(avsVolume)); EXPECT_TRUE(speakerPtr->getSpeakerSettings(&settings)); EXPECT_EQ(settings.volume, avsVolume); }; check(AVS_SET_VOLUME_MAX); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.99); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.95); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.90); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.50); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.10); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.05); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.01); check(AVS_SET_VOLUME_MIN); } /// Test that the conversion from avs volume to device volume. TEST_F(AndroidSLESSpeakerTest, test_setDeviceVolume) { auto speakerPtr = m_speaker.get(); auto check = [speakerPtr](int8_t avsVolume, SLmillibel expected) { EXPECT_TRUE(speakerPtr->setVolume(avsVolume)); EXPECT_EQ(g_volume, expected); }; check(AVS_SET_VOLUME_MAX, g_maxVolume); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.99, -8); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.95, -44); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.90, -91); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.50, -602); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.10, -2000); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.05, -2602); check((AVS_SET_VOLUME_MAX - AVS_SET_VOLUME_MIN) * 0.01, -4000); check(AVS_SET_VOLUME_MIN, SL_MILLIBEL_MIN); } } // namespace test } // namespace android } // namespace mediaPlayer } // namespace alexaClientSDK