Skip to content
This repository has been archived by the owner on Jan 16, 2024. It is now read-only.

Commit

Permalink
Verison 1.6 of the avs-device-sdk
Browse files Browse the repository at this point in the history
Changes in this update:

**Enhancements**
* `rapidJson` is now included with "make install".
* Updated the `TemplateRuntimeObserverInterface` to support clearing of `displayCards`.
* Added Windows SDK support, along with an installation script (MinGW-w64).
* Updated `ContextManager` to ignore context reported by a state provider.
* The `SharedDataStream` object is now associated by playlist, rather than by URL.
* Added the `RegistrationManager` component. Now, when a user logs out all persistent user-specific data is cleared from the SDK. The log out functionality can be exercised in the sample app with the new command: `k`.

**Bug Fixes**
* [Issue 400](#400) Fixed a bug where the alert reminder did not iterate as intended after loss of network connection.
* [Issue 477](#477) Fixed a bug in which Alexa's weather response was being truncated.
* Fixed an issue in which there were reports of instability related to the Sensory engine. To correct this, the `portAudio` [`suggestedLatency`](https://github.com/alexa/avs-device-sdk/blob/master/Integration/AlexaClientSDKConfig.json#L62) value can now be configured.

**Known Issues**
* The `ACL` may encounter issues if audio attachments are received but not consumed.
* `SpeechSynthesizerState` currently uses `GAINING_FOCUS` and `LOSING_FOCUS` as a workaround for handling intermediate state. These states may be removed in a future release.
* Music playback doesn't immediately stop when a user barges-in on iHeartRadio.
* The Windows sample app sometimes hangs on exit.
* GDP receives a `SIGPIPE` when troubleshooting the Windows sample app.
  • Loading branch information
sanjayrd committed Mar 9, 2018
1 parent 5545936 commit 46fd548
Show file tree
Hide file tree
Showing 227 changed files with 9,092 additions and 2,482 deletions.
11 changes: 11 additions & 0 deletions ACL/include/ACL/Transport/HTTP2Stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include <AVSCommon/AVS/Attachment/AttachmentManager.h>
#include <AVSCommon/Utils/LibcurlUtils/CurlEasyHandleWrapper.h>
#include <AVSCommon/Utils/Logger/LogStringFormatter.h>
#include <AVSCommon/AVS/MessageRequest.h>
#include <AVSCommon/SDKInterfaces/MessageRequestObserverInterface.h>

Expand Down Expand Up @@ -202,6 +203,14 @@ class HTTP2Stream {
*/
bool hasProgressTimedOut() const;

/**
* Return a reference to the LogStringFormatter owned by this object. This is to allow a callback that uses this
* object to get access to a known good LogStringFormatter.
*
* @return A reference to a LogStringFormatter.
*/
const avsCommon::utils::logger::LogStringFormatter& getLogFormatter() const;

private:
/**
* Configure the associated curl easy handle with options common to GET and POST
Expand Down Expand Up @@ -273,6 +282,8 @@ class HTTP2Stream {
std::atomic<std::chrono::steady_clock::rep> m_progressTimeout;
/// Last time something was transferred.
std::atomic<std::chrono::steady_clock::rep> m_timeOfLastTransfer;
/// Object to format log strings correctly.
avsCommon::utils::logger::LogStringFormatter m_logFormatter;
};

template <class TickType, class TickPeriod>
Expand Down
2 changes: 2 additions & 0 deletions ACL/include/ACL/Transport/TransportObserverInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#define ALEXA_CLIENT_SDK_ACL_INCLUDE_ACL_TRANSPORT_TRANSPORTOBSERVERINTERFACE_H_

#include <memory>

#include <ACL/Transport/TransportInterface.h>
#include <AVSCommon/SDKInterfaces/ConnectionStatusObserverInterface.h>

namespace alexaClientSDK {
Expand Down
7 changes: 6 additions & 1 deletion ACL/src/Transport/HTTP2Stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,10 @@ bool HTTP2Stream::hasProgressTimedOut() const {
return (getNow() - m_timeOfLastTransfer) > m_progressTimeout;
}

const avsCommon::utils::logger::LogStringFormatter& HTTP2Stream::getLogFormatter() const {
return m_logFormatter;
}

template <typename ParamType>
bool HTTP2Stream::setopt(CURLoption option, const char* optionName, ParamType value) {
auto result = curl_easy_setopt(m_transfer.getCurlHandle(), option, value);
Expand Down Expand Up @@ -563,7 +567,8 @@ int HTTP2Stream::debugFunction(CURL* handle, curl_infotype type, char* data, siz
return 0;
}
if (stream->m_streamLog) {
(*stream->m_streamLog) << logger::formatLogString(
auto logFormatter = stream->getLogFormatter();
(*stream->m_streamLog) << logFormatter.format(
logger::Level::INFO,
std::chrono::system_clock::now(),
logger::ThreadMoniker::getThisThreadMoniker().c_str(),
Expand Down
5 changes: 5 additions & 0 deletions ACL/test/Transport/MimeParserTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,5 +315,10 @@ TEST_F(MimeParserTest, testDuplicateBounaries) {

int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);

// ACSDK-1051 - MimeParser tests with attachments fail on Windows
#if defined(_WIN32) && !defined(RESOLVED_ACSDK_1051)
::testing::GTEST_FLAG(filter) = "-MimeParserTest*Attachment*";
#endif
return RUN_ALL_TESTS();
}
16 changes: 16 additions & 0 deletions ADSL/include/ADSL/DirectiveProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,19 @@ class DirectiveProcessor {
*/
void shutdown();

/**
* Disable the DirectiveProcessor, queues all outstanding @c AVSDirectives for cancellation and
* blocks until the processing of all @c AVSDirectives has completed.
*/
void disable();

/**
* Enable the DirectiveProcessor.
*
* @return Whether it succeeded to enable the directive processor.
*/
bool enable();

private:
/**
* Handle used to identify @c DirectiveProcessor instances referenced by @c DirectiveHandlerResult.
Expand Down Expand Up @@ -222,6 +235,9 @@ class DirectiveProcessor {
/// Whether or not the @c DirectiveProcessor is shutting down.
bool m_isShuttingDown;

/// Whether or not the @c DirectiveProcessor is enabled.
bool m_isEnabled;

/// The current @c dialogRequestId
std::string m_dialogRequestId;

Expand Down
7 changes: 7 additions & 0 deletions ADSL/include/ADSL/DirectiveSequencer.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ class DirectiveSequencer : public avsCommon::sdkInterfaces::DirectiveSequencerIn

bool onDirective(std::shared_ptr<avsCommon::avs::AVSDirective> directive) override;

void disable() override;

void enable() override;

private:
/**
* Constructor.
Expand Down Expand Up @@ -93,6 +97,9 @@ class DirectiveSequencer : public avsCommon::sdkInterfaces::DirectiveSequencerIn
/// Whether or not the @c DirectiveReceiver is shutting down.
bool m_isShuttingDown;

/// Whether or not the @c DirectiveSequencer is enabled.
bool m_isEnabled;

/// Object used to route directives to their assigned handler.
DirectiveRouter m_directiveRouter;

Expand Down
19 changes: 17 additions & 2 deletions ADSL/src/DirectiveProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ std::unordered_map<DirectiveProcessor::ProcessorHandle, DirectiveProcessor*> Dir
DirectiveProcessor::DirectiveProcessor(DirectiveRouter* directiveRouter) :
m_directiveRouter{directiveRouter},
m_isShuttingDown{false},
m_isEnabled{true},
m_isHandlingDirective{false} {
std::lock_guard<std::mutex> lock(m_handleMapMutex);
m_handle = ++m_nextProcessorHandle;
Expand All @@ -70,11 +71,11 @@ bool DirectiveProcessor::onDirective(std::shared_ptr<AVSDirective> directive) {
}
std::lock_guard<std::mutex> onDirectiveLock(m_onDirectiveMutex);
std::unique_lock<std::mutex> lock(m_mutex);
if (m_isShuttingDown) {
if (m_isShuttingDown || !m_isEnabled) {
ACSDK_WARN(LX("onDirectiveFailed")
.d("messageId", directive->getMessageId())
.d("action", "ignored")
.d("reason", "shuttingDown"));
.d("reason", m_isShuttingDown ? "shuttingDown" : "disabled"));
return false;
}
if (!directive->getDialogRequestId().empty() && directive->getDialogRequestId() != m_dialogRequestId) {
Expand Down Expand Up @@ -118,6 +119,20 @@ void DirectiveProcessor::shutdown() {
}
}

void DirectiveProcessor::disable() {
std::lock_guard<std::mutex> lock(m_mutex);
ACSDK_DEBUG(LX("disable"));
queueAllDirectivesForCancellationLocked();
m_isEnabled = false;
m_wakeProcessingLoop.notify_one();
}

bool DirectiveProcessor::enable() {
std::lock_guard<std::mutex> lock{m_mutex};
m_isEnabled = true;
return m_isEnabled;
}

DirectiveProcessor::DirectiveHandlerResult::DirectiveHandlerResult(
DirectiveProcessor::ProcessorHandle processorHandle,
std::shared_ptr<AVSDirective> directive) :
Expand Down
24 changes: 21 additions & 3 deletions ADSL/src/DirectiveSequencer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ bool DirectiveSequencer::onDirective(std::shared_ptr<AVSDirective> directive) {
return false;
}
std::lock_guard<std::mutex> lock(m_mutex);
if (m_isShuttingDown) {
if (m_isShuttingDown || !m_isEnabled) {
ACSDK_WARN(LX("onDirectiveFailed")
.d("directive", directive->getHeaderAsString())
.d("action", "ignored")
.d("reason", "isShuttingDown"));
.d("reason", m_isShuttingDown ? "isShuttingDown" : "disabled"));
return false;
}
ACSDK_INFO(LX("onDirective").d("directive", directive->getHeaderAsString()));
Expand All @@ -86,7 +86,8 @@ DirectiveSequencer::DirectiveSequencer(
DirectiveSequencerInterface{"DirectiveSequencer"},
m_mutex{},
m_exceptionSender{exceptionSender},
m_isShuttingDown{false} {
m_isShuttingDown{false},
m_isEnabled{true} {
m_directiveProcessor = std::make_shared<DirectiveProcessor>(&m_directiveRouter);
m_receivingThread = std::thread(&DirectiveSequencer::receivingLoop, this);
}
Expand All @@ -106,6 +107,23 @@ void DirectiveSequencer::doShutdown() {
m_exceptionSender.reset();
}

void DirectiveSequencer::disable() {
ACSDK_DEBUG9(LX("disable"));
std::lock_guard<std::mutex> lock(m_mutex);
m_isEnabled = false;
m_directiveProcessor->setDialogRequestId("");
m_directiveProcessor->disable();
m_wakeReceivingLoop.notify_one();
}

void DirectiveSequencer::enable() {
ACSDK_DEBUG9(LX("disable"));
std::lock_guard<std::mutex> lock(m_mutex);
m_isEnabled = true;
m_directiveProcessor->enable();
m_wakeReceivingLoop.notify_one();
}

void DirectiveSequencer::receivingLoop() {
auto wake = [this]() { return !m_receivingQueue.empty() || m_isShuttingDown; };

Expand Down
4 changes: 4 additions & 0 deletions ADSL/test/ADSL/MockDirectiveSequencer.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ class MockDirectiveSequencer : public avsCommon::sdkInterfaces::DirectiveSequenc
MOCK_METHOD1(setDialogRequestId, void(const std::string& dialogRequestId));

MOCK_METHOD1(onDirective, bool(std::shared_ptr<avsCommon::avs::AVSDirective> directive));

MOCK_METHOD0(disable, void());

MOCK_METHOD0(enable, void());
};

inline MockDirectiveSequencer::MockDirectiveSequencer() :
Expand Down
13 changes: 13 additions & 0 deletions ADSL/test/DirectiveProcessorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,19 @@ TEST_F(DirectiveProcessorTest, testSetDialogRequestIdCancelsOutstandingDirective
ASSERT_TRUE(handler2->waitUntilCompleted());
}

TEST_F(DirectiveProcessorTest, testAddDirectiveWhileDisabled) {
m_processor->disable();
ASSERT_FALSE(m_processor->onDirective(m_directive_0_0));
}

TEST_F(DirectiveProcessorTest, testAddDirectiveAfterReEnabled) {
m_processor->disable();
ASSERT_FALSE(m_processor->onDirective(m_directive_0_0));

m_processor->enable();
ASSERT_TRUE(m_processor->onDirective(m_directive_0_0));
}

} // namespace test
} // namespace adsl
} // namespace alexaClientSDK
104 changes: 104 additions & 0 deletions ADSL/test/DirectiveSequencerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,110 @@ TEST_F(DirectiveSequencerTest, testHandleBlockingThenImmediatelyThenNonBockingOn
ASSERT_TRUE(handler2->waitUntilCompleted());
}

/**
* Check that the @ DirectiveSequencer does not handle directives when it is disabled
*/
TEST_F(DirectiveSequencerTest, testAddDirectiveAfterDisabled) {
auto avsMessageHeader =
std::make_shared<AVSMessageHeader>(NAMESPACE_SPEECH_SYNTHESIZER, NAME_SPEAK, MESSAGE_ID_0, DIALOG_REQUEST_ID_0);
std::shared_ptr<AVSDirective> directive = AVSDirective::create(
UNPARSED_DIRECTIVE, avsMessageHeader, PAYLOAD_TEST, m_attachmentManager, TEST_ATTACHMENT_CONTEXT_ID);

DirectiveHandlerConfiguration handlerConfig;
handlerConfig[{NAMESPACE_SPEECH_SYNTHESIZER, NAME_SPEAK}] = BlockingPolicy::BLOCKING;
auto handler = MockDirectiveHandler::create(handlerConfig, LONG_HANDLING_TIME_MS);

EXPECT_CALL(*handler, handleDirectiveImmediately(_)).Times(0);
EXPECT_CALL(*handler, preHandleDirective(directive, _)).Times(0);
EXPECT_CALL(*handler, handleDirective(MESSAGE_ID_2)).Times(0);
EXPECT_CALL(*handler, cancelDirective(_)).Times(0);

ASSERT_TRUE(m_sequencer->addDirectiveHandler(handler));
m_sequencer->disable();
m_sequencer->setDialogRequestId(DIALOG_REQUEST_ID_0);
ASSERT_FALSE(m_sequencer->onDirective(directive));

// Tear down method expects the sequencer to be enabled
m_sequencer->enable();
}

/**
* Check that the @ DirectiveSequencer.disable() cancel directive being handled
*/
TEST_F(DirectiveSequencerTest, testDisableCancelsDirective) {
auto avsMessageHeader =
std::make_shared<AVSMessageHeader>(NAMESPACE_SPEECH_SYNTHESIZER, NAME_SPEAK, MESSAGE_ID_0, DIALOG_REQUEST_ID_0);
std::shared_ptr<AVSDirective> directive = AVSDirective::create(
UNPARSED_DIRECTIVE, avsMessageHeader, PAYLOAD_TEST, m_attachmentManager, TEST_ATTACHMENT_CONTEXT_ID);

DirectiveHandlerConfiguration handlerConfig;
handlerConfig[{NAMESPACE_SPEECH_SYNTHESIZER, NAME_SPEAK}] = BlockingPolicy::BLOCKING;
auto handler = MockDirectiveHandler::create(handlerConfig, LONG_HANDLING_TIME_MS);

EXPECT_CALL(*handler, handleDirectiveImmediately(_)).Times(0);
EXPECT_CALL(*handler, preHandleDirective(directive, _)).Times(1);
EXPECT_CALL(*handler, handleDirective(MESSAGE_ID_0)).Times(AtMost(1));
EXPECT_CALL(*handler, cancelDirective(_)).Times(1);

// Add directive and wait till prehandling
ASSERT_TRUE(m_sequencer->addDirectiveHandler(handler));
m_sequencer->setDialogRequestId(DIALOG_REQUEST_ID_0);
ASSERT_TRUE(m_sequencer->onDirective(directive));
ASSERT_TRUE(handler->waitUntilPreHandling());

// Disable
m_sequencer->disable();
ASSERT_TRUE(handler->waitUntilCanceling());

// Tear down method expects the sequencer to be enabled
m_sequencer->enable();
}

/**
* Check that the @ DirectiveSequencer can handle directives after being re-enabled
*/
TEST_F(DirectiveSequencerTest, testAddDirectiveAfterReEnabled) {
auto avsMessageHeader0 =
std::make_shared<AVSMessageHeader>(NAMESPACE_AUDIO_PLAYER, NAME_PLAY, MESSAGE_ID_0, DIALOG_REQUEST_ID_0);
std::shared_ptr<AVSDirective> directive0 = AVSDirective::create(
UNPARSED_DIRECTIVE, avsMessageHeader0, PAYLOAD_TEST, m_attachmentManager, TEST_ATTACHMENT_CONTEXT_ID);
auto avsMessageHeader1 =
std::make_shared<AVSMessageHeader>(NAMESPACE_AUDIO_PLAYER, NAME_PLAY, MESSAGE_ID_1, DIALOG_REQUEST_ID_1);
std::shared_ptr<AVSDirective> ignoredDirective1 = AVSDirective::create(
"ignoreDirective", avsMessageHeader1, PAYLOAD_TEST, m_attachmentManager, TEST_ATTACHMENT_CONTEXT_ID);
auto avsMessageHeader2 =
std::make_shared<AVSMessageHeader>(NAMESPACE_AUDIO_PLAYER, NAME_PLAY, MESSAGE_ID_2, DIALOG_REQUEST_ID_2);
std::shared_ptr<AVSDirective> ignoredDirective2 = AVSDirective::create(
"anotherIgnored", avsMessageHeader2, PAYLOAD_TEST, m_attachmentManager, TEST_ATTACHMENT_CONTEXT_ID);

DirectiveHandlerConfiguration handlerConfig;
handlerConfig[{NAMESPACE_AUDIO_PLAYER, NAME_PLAY}] = BlockingPolicy::NON_BLOCKING;
auto handler = MockDirectiveHandler::create(handlerConfig);

// No handle calls are expected
EXPECT_CALL(*handler, handleDirectiveImmediately(_)).Times(0);
EXPECT_CALL(*handler, preHandleDirective(_, _)).Times(0);
EXPECT_CALL(*handler, handleDirective(_)).Times(0);
EXPECT_CALL(*handler, cancelDirective(_)).Times(0);

// Except for the ones handling the directive0
EXPECT_CALL(*handler, preHandleDirective(directive0, _)).Times(1);
EXPECT_CALL(*handler, handleDirective(MESSAGE_ID_0)).Times(1);

ASSERT_TRUE(m_sequencer->addDirectiveHandler(handler));
m_sequencer->disable();

// Make sure these directives are ignored and never processed
ASSERT_FALSE(m_sequencer->onDirective(ignoredDirective1));
ASSERT_FALSE(m_sequencer->onDirective(ignoredDirective2));

m_sequencer->enable();
m_sequencer->setDialogRequestId(DIALOG_REQUEST_ID_0);

ASSERT_TRUE(m_sequencer->onDirective(directive0));
ASSERT_TRUE(handler->waitUntilCompleted());
}

} // namespace test
} // namespace adsl
} // namespace alexaClientSDK
Loading

0 comments on commit 46fd548

Please sign in to comment.