aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/core
diff options
context:
space:
mode:
authorNaveen Bobbili <nbobbili@amazon.com>2018-11-12 16:12:38 -0800
committerNaveen Bobbili <nbobbili@amazon.com>2018-11-13 15:05:41 -0800
commitb6abca2edcb36c0c0848d1cd8dc291f23293aa80 (patch)
treea838812e0b66f0695cb6cf0f8bebfa38315ce8b8 /src/plugins/core
parentbe70712f89eacd20dca413bcce46e4aa26b5709e (diff)
SPEC-1924: AGL Speech Framework's Voice Service High Level 1.0 Release.
Details: 1) Control plugin implementation for VSHL 1.0 2) Exposed APIs that are documented in the confluence page https://confluence.automotivelinux.org/display/SPE/Speech+EG+Architecture 3) Implemented 39 unit tests based on GTest framework to test all the low level components of VSHL binding. 4) Implemented a HTML5 based VSHL API tester application to test VSHL APIs. API specification: https://confluence.automotivelinux.org/display/SPE/Speech+EG+Architecture#SpeechEGArchitecture-HighLevelVoiceService Test performed: 1) Tested AGL service running Alexa Auto SDK https://github.com/alexa/aac-sdk on Ubuntu 16.04 and Renesas R-Car M3 board. License: Apache 2.0 Developers/Owners: Naveen Bobbili (nbobbili@amazon.com) Prakash Buddhiraja (buddhip@amazon.com) Shotaro Uchida (shotaru@amazon.co.jp) Change-Id: I3370f4ad65aff030f24f4ad571fb02d525bbfbca Signed-off-by: Naveen Bobbili <nbobbili@amazon.com>
Diffstat (limited to 'src/plugins/core')
-rw-r--r--src/plugins/core/VRRequestProcessor.h75
-rw-r--r--src/plugins/core/VRRequestProcessorImpl.cpp72
-rw-r--r--src/plugins/core/include/VRAgentsObserver.h67
-rw-r--r--src/plugins/core/include/VRRequest.h80
-rw-r--r--src/plugins/core/include/VRRequestProcessorDelegate.h88
-rw-r--r--src/plugins/core/src/VRAgentsObserverImpl.cpp54
-rw-r--r--src/plugins/core/src/VRRequestImpl.cpp92
-rw-r--r--src/plugins/core/src/VRRequestProcessorDelegateImpl.cpp93
-rw-r--r--src/plugins/core/test/VRRequestProcessorTest.cpp213
-rw-r--r--src/plugins/core/test/VRRequestTest.cpp101
10 files changed, 935 insertions, 0 deletions
diff --git a/src/plugins/core/VRRequestProcessor.h b/src/plugins/core/VRRequestProcessor.h
new file mode 100644
index 0000000..c349a19
--- /dev/null
+++ b/src/plugins/core/VRRequestProcessor.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+#ifndef VSHL_CORE_INCLUDE_VR_REQUESTPROCESSOR_H_
+#define VSHL_CORE_INCLUDE_VR_REQUESTPROCESSOR_H_
+
+#include <memory>
+#include <unordered_map>
+
+#include "core/include/VRRequest.h"
+#include "core/include/VRRequestProcessorDelegate.h"
+#include "interfaces/afb/IAFBApi.h"
+#include "interfaces/utilities/logging/ILogger.h"
+#include "interfaces/voiceagents/IVoiceAgentsChangeObserver.h"
+
+using namespace std;
+
+namespace vshl {
+namespace core {
+/*
+ * This class is the entry point for all the voice recognition request
+ * creation and arbitration.
+ */
+class VRRequestProcessor {
+public:
+ // Create a VRRequestProcessor.
+ static unique_ptr<VRRequestProcessor> create(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::core::VRRequestProcessorDelegate> delegate);
+
+ // Triggers a voiceagent to start listening to user speech input.
+ // Returns the request ID. If start fails, then empty request ID
+ // is returned.
+ string startListening();
+
+ // Cancels all the active requests
+ void cancel();
+
+ // Returns the voiceagents observer that belongs to the core module.
+ shared_ptr<vshl::common::interfaces::IVoiceAgentsChangeObserver> getVoiceAgentsChangeObserver() const;
+
+ // Destructor
+ ~VRRequestProcessor();
+
+private:
+ // Constructor
+ VRRequestProcessor(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::core::VRRequestProcessorDelegate> delegate);
+
+ // Voiceagents observer
+ shared_ptr<vshl::common::interfaces::IVoiceAgentsChangeObserver> mVoiceAgentsChangeObserver;
+
+ // Request Processor Delegate
+ shared_ptr<vshl::core::VRRequestProcessorDelegate> mDelegate;
+
+ // Logger
+ shared_ptr<vshl::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace core
+} // namespace vshl
+
+#endif // VSHL_CORE_INCLUDE_VR_REQUESTPROCESSOR_H_
diff --git a/src/plugins/core/VRRequestProcessorImpl.cpp b/src/plugins/core/VRRequestProcessorImpl.cpp
new file mode 100644
index 0000000..7441a7d
--- /dev/null
+++ b/src/plugins/core/VRRequestProcessorImpl.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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 "core/VRRequestProcessor.h"
+
+#include "core/include/VRAgentsObserver.h"
+
+static string TAG = "vshl::core::VRRequestProcessor";
+
+using Level = vshl::utilities::logging::Logger::Level;
+
+namespace vshl {
+namespace core {
+// Create a VRRequestProcessor.
+unique_ptr<VRRequestProcessor> VRRequestProcessor::create(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::core::VRRequestProcessorDelegate> delegate) {
+ auto processor = std::unique_ptr<VRRequestProcessor>(new VRRequestProcessor(logger, delegate));
+ return processor;
+}
+
+VRRequestProcessor::VRRequestProcessor(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::core::VRRequestProcessorDelegate> delegate) :
+ mLogger(logger),
+ mDelegate(delegate) {
+ mVoiceAgentsChangeObserver = VRAgentsObserver::create(mDelegate);
+}
+
+VRRequestProcessor::~VRRequestProcessor() {
+ mDelegate->cancelAllRequests();
+}
+
+string VRRequestProcessor::startListening() {
+ // Currently start is simply going to send the request to
+ // the default voice agent as the wake word detection is not
+ // enabled.
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> defaultVA = mDelegate->getDefaultVoiceAgent();
+ if (!defaultVA) {
+ mLogger->log(Level::ERROR, TAG, "Failed to start. No default voiceagent found.");
+ return "";
+ }
+
+ // If the requests container is not empty, then clear the
+ // existing requests in flight and create a new request.
+ mDelegate->cancelAllRequests();
+ return mDelegate->startRequestForVoiceAgent(defaultVA);
+}
+
+void VRRequestProcessor::cancel() {
+ // Cancel all pending requests
+ mDelegate->cancelAllRequests();
+}
+
+shared_ptr<vshl::common::interfaces::IVoiceAgentsChangeObserver> VRRequestProcessor::getVoiceAgentsChangeObserver()
+ const {
+ return mVoiceAgentsChangeObserver;
+}
+
+} // namespace core
+} // namespace vshl
diff --git a/src/plugins/core/include/VRAgentsObserver.h b/src/plugins/core/include/VRAgentsObserver.h
new file mode 100644
index 0000000..d4c0c7b
--- /dev/null
+++ b/src/plugins/core/include/VRAgentsObserver.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+#ifndef VSHL_CORE_INCLUDE_VR_AGENTS_OBSERVER_H_
+#define VSHL_CORE_INCLUDE_VR_AGENTS_OBSERVER_H_
+
+#include <memory>
+
+#include "core/include/VRRequestProcessorDelegate.h"
+#include "interfaces/voiceagents/IVoiceAgentsChangeObserver.h"
+#include "utilities/logging/Logger.h"
+
+using namespace std;
+
+namespace vshl {
+namespace core {
+/*
+ * This class will observe the changes to the voiceagents data and transfers
+ * the actual handling responsibility to its delegate.
+ */
+class VRAgentsObserver
+ : public vshl::common::interfaces::IVoiceAgentsChangeObserver {
+public:
+ // Create a VRAgentsObserver.
+ static shared_ptr<VRAgentsObserver>
+ create(weak_ptr<VRRequestProcessorDelegate> delegate);
+
+ ~VRAgentsObserver();
+
+protected:
+ void OnDefaultVoiceAgentChanged(
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> defaultVoiceAgent)
+ override;
+ void OnVoiceAgentAdded(
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) override;
+ void OnVoiceAgentRemoved(
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) override;
+ void OnVoiceAgentActiveWakeWordChanged(
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) override;
+ void OnVoiceAgentActivated(
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) override;
+ void OnVoiceAgentDeactivated(
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) override;
+
+private:
+ // Constructor
+ VRAgentsObserver(weak_ptr<VRRequestProcessorDelegate> delegate);
+
+ // Delegate that needs to be informed of the voiceagent data changes.
+ weak_ptr<VRRequestProcessorDelegate> mWeakDelegate;
+};
+
+} // namespace core
+} // namespace vshl
+
+#endif // VSHL_CORE_INCLUDE_VR_AGENTS_OBSERVER_H_
diff --git a/src/plugins/core/include/VRRequest.h b/src/plugins/core/include/VRRequest.h
new file mode 100644
index 0000000..522ec78
--- /dev/null
+++ b/src/plugins/core/include/VRRequest.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+#ifndef VSHL_CORE_INCLUDE_VR_REQUEST_H_
+#define VSHL_CORE_INCLUDE_VR_REQUEST_H_
+
+#include <memory>
+
+#include "interfaces/afb/IAFBApi.h"
+#include "interfaces/utilities/logging/ILogger.h"
+#include "interfaces/voiceagents/IVoiceAgent.h"
+
+using namespace std;
+
+namespace vshl {
+namespace core {
+/*
+ * This class implements the notion of a Voice Recognition Request.
+ * Each VR Request is currently mapped to one voice agent.
+ */
+class VRRequest {
+public:
+ // API Verbs
+ static std::string VA_VERB_STARTLISTENING;
+ static std::string VA_VERB_CANCEL;
+
+ // Create a VRRequest.
+ static unique_ptr<VRRequest> create(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::common::interfaces::IAFBApi> afbApi,
+ string requestId,
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent);
+
+ // Destructor
+ ~VRRequest();
+
+ // Invokes the underlying voiceagent's startlistening API.
+ // Returns true if started successfully. False otherwise.
+ bool startListening();
+
+ // Cancels the voice recognition in the unlerlying voiceagent.
+ // Returns true if canceled successfully. False otherwise.
+ bool cancel();
+
+private:
+ // Constructor
+ VRRequest(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::common::interfaces::IAFBApi> afbApi,
+ const string requestId,
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent);
+
+ // Binding API reference.
+ shared_ptr<vshl::common::interfaces::IAFBApi> mApi;
+
+ // Voice agent associated with this request
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> mVoiceAgent;
+
+ // Request ID
+ string mRequestId;
+
+ // Logger
+ shared_ptr<vshl::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace core
+} // namespace vshl
+
+#endif // VSHL_CORE_INCLUDE_VR_REQUEST_H_
diff --git a/src/plugins/core/include/VRRequestProcessorDelegate.h b/src/plugins/core/include/VRRequestProcessorDelegate.h
new file mode 100644
index 0000000..94b7304
--- /dev/null
+++ b/src/plugins/core/include/VRRequestProcessorDelegate.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+#ifndef VSHL_CORE_INCLUDE_VR_REQUESTPROCESSORDELEGATE_H_
+#define VSHL_CORE_INCLUDE_VR_REQUESTPROCESSORDELEGATE_H_
+
+#include <memory>
+#include <unordered_map>
+
+#include "core/include/VRRequest.h"
+#include "interfaces/afb/IAFBApi.h"
+#include "interfaces/utilities/logging/ILogger.h"
+#include "interfaces/voiceagents/IVoiceAgent.h"
+#include "utilities/uuid/UUIDGeneration.h"
+
+using namespace std;
+
+namespace vshl {
+namespace core {
+/*
+ * This is a delegate for VRRequestProcessor actions.
+ * The lifetime and dependencies of this object is managed
+ * by VRRequestProcessor. It plays the role of a Delegate in
+ * Delegate pattern and a one shop stop for most of the core
+ * module's state.
+ */
+class VRRequestProcessorDelegate {
+public:
+ // create method
+ static shared_ptr<VRRequestProcessorDelegate> create(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::common::interfaces::IAFBApi> afbApi);
+
+ // Destructor
+ ~VRRequestProcessorDelegate();
+
+ // Set default voiceagent
+ void setDefaultVoiceAgent(shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent);
+
+ // Get the default voiceagent
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> getDefaultVoiceAgent() const;
+
+ // Add new request to the list and start processing it.
+ // New request is created and startListening on the
+ // voiceagent is called.
+ string startRequestForVoiceAgent(shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent);
+
+ // Cancel all requests
+ void cancelAllRequests();
+
+ // Get All outstanding requests
+ // Used only by Test
+ unordered_map<string, shared_ptr<VRRequest>> getAllRequests();
+
+private:
+ // Constructor
+ VRRequestProcessorDelegate(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::common::interfaces::IAFBApi> afbApi);
+
+ // Binding API reference
+ shared_ptr<vshl::common::interfaces::IAFBApi> mApi;
+
+ // Default voiceagent
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> mDefaultVoiceAgent;
+
+ // A map of voiceagent IDs and their respective VR Request objects.
+ unordered_map<string, shared_ptr<VRRequest>> mVRRequests;
+
+ // Logger
+ shared_ptr<vshl::common::interfaces::ILogger> mLogger;
+};
+
+} // namespace core
+} // namespace vshl
+
+#endif // VSHL_CORE_INCLUDE_VR_REQUESTPROCESSORDELEGATE_H_
diff --git a/src/plugins/core/src/VRAgentsObserverImpl.cpp b/src/plugins/core/src/VRAgentsObserverImpl.cpp
new file mode 100644
index 0000000..7ee4a7e
--- /dev/null
+++ b/src/plugins/core/src/VRAgentsObserverImpl.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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 "core/include/VRAgentsObserver.h"
+
+namespace vshl {
+namespace core {
+
+shared_ptr<VRAgentsObserver> VRAgentsObserver::create(weak_ptr<VRRequestProcessorDelegate> delegate) {
+ auto observer = std::shared_ptr<VRAgentsObserver>(new VRAgentsObserver(delegate));
+ return observer;
+}
+
+VRAgentsObserver::VRAgentsObserver(weak_ptr<VRRequestProcessorDelegate> delegate) {
+ mWeakDelegate = delegate;
+}
+
+VRAgentsObserver::~VRAgentsObserver() {
+}
+
+void VRAgentsObserver::OnDefaultVoiceAgentChanged(shared_ptr<vshl::common::interfaces::IVoiceAgent> defaultVoiceAgent) {
+ if (auto delegate = mWeakDelegate.lock()) {
+ delegate->setDefaultVoiceAgent(defaultVoiceAgent);
+ }
+}
+
+void VRAgentsObserver::OnVoiceAgentAdded(shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) {
+}
+
+void VRAgentsObserver::OnVoiceAgentRemoved(shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) {
+}
+
+void VRAgentsObserver::OnVoiceAgentActiveWakeWordChanged(shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) {
+ // Not Implemented
+}
+
+void VRAgentsObserver::OnVoiceAgentActivated(shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) {
+}
+
+void VRAgentsObserver::OnVoiceAgentDeactivated(shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) {
+}
+} // namespace core
+} // namespace vshl
diff --git a/src/plugins/core/src/VRRequestImpl.cpp b/src/plugins/core/src/VRRequestImpl.cpp
new file mode 100644
index 0000000..00adf96
--- /dev/null
+++ b/src/plugins/core/src/VRRequestImpl.cpp
@@ -0,0 +1,92 @@
+/*
+ * 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 "core/include/VRRequest.h"
+
+#define FREEIF(x) \
+ if (!x) { \
+ free(x); \
+ }
+#define BREAKIF(x) \
+ if (x) { \
+ result = false; \
+ break; \
+ }
+
+static string TAG = "vshl::core::VRRequest";
+
+using Level = vshl::common::interfaces::ILogger::Level;
+
+namespace vshl {
+namespace core {
+
+string VRRequest::VA_VERB_STARTLISTENING = "startListening";
+string VRRequest::VA_VERB_CANCEL = "cancel";
+
+unique_ptr<VRRequest> VRRequest::create(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::common::interfaces::IAFBApi> afbApi,
+ const string requestId,
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) {
+ if (logger == nullptr) {
+ return nullptr;
+ }
+
+ if (afbApi == nullptr) {
+ logger->log(Level::ERROR, TAG, "Invalid AFB API");
+ return nullptr;
+ }
+
+ auto request = std::unique_ptr<VRRequest>(new VRRequest(logger, afbApi, requestId, voiceAgent));
+ return request;
+}
+
+VRRequest::VRRequest(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::common::interfaces::IAFBApi> afbApi,
+ string requestId,
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) :
+ mApi(afbApi),
+ mRequestId(requestId),
+ mVoiceAgent(voiceAgent),
+ mLogger(logger) {
+}
+
+VRRequest::~VRRequest() {
+}
+
+bool VRRequest::startListening() {
+ json_object* object = NULL;
+ std::string error, info;
+ bool result = true;
+ int rc = mApi->callSync(mVoiceAgent->getApi(), VA_VERB_STARTLISTENING, NULL, &object, error, info);
+
+ FREEIF(object);
+
+ return true;
+}
+
+bool VRRequest::cancel() {
+ json_object* object = NULL;
+ std::string error, info;
+ bool result = true;
+ int rc = mApi->callSync(mVoiceAgent->getApi(), VA_VERB_CANCEL, NULL, &object, error, info);
+
+ FREEIF(object);
+
+ return true;
+}
+
+} // namespace core
+} // namespace vshl
diff --git a/src/plugins/core/src/VRRequestProcessorDelegateImpl.cpp b/src/plugins/core/src/VRRequestProcessorDelegateImpl.cpp
new file mode 100644
index 0000000..e20b22e
--- /dev/null
+++ b/src/plugins/core/src/VRRequestProcessorDelegateImpl.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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 "core/include/VRRequestProcessorDelegate.h"
+
+static string TAG = "vshl::core::VRRequestProcessorDelegate";
+
+using Level = vshl::common::interfaces::ILogger::Level;
+
+namespace vshl {
+namespace core {
+shared_ptr<VRRequestProcessorDelegate> VRRequestProcessorDelegate::create(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::common::interfaces::IAFBApi> afbApi) {
+ auto delegate = std::shared_ptr<VRRequestProcessorDelegate>(new VRRequestProcessorDelegate(logger, afbApi));
+ return delegate;
+}
+
+VRRequestProcessorDelegate::VRRequestProcessorDelegate(
+ shared_ptr<vshl::common::interfaces::ILogger> logger,
+ shared_ptr<vshl::common::interfaces::IAFBApi> afbApi) :
+ mApi(afbApi),
+ mLogger(logger) {
+}
+
+VRRequestProcessorDelegate::~VRRequestProcessorDelegate() {
+ mVRRequests.clear();
+}
+
+string VRRequestProcessorDelegate::startRequestForVoiceAgent(
+ shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) {
+ if (!mApi) {
+ mLogger->log(Level::ERROR, TAG, "Failed to startRequestForVoiceAgent: " + voiceAgent->getId() + ", No API.");
+ return "";
+ }
+
+ // Generate a new request ID.
+ string newReqId = vshl::utilities::uuid::generateUUID();
+
+ // Create a new request and start listening.
+ shared_ptr<VRRequest> newRequest = VRRequest::create(mLogger, mApi, newReqId, voiceAgent);
+
+ // mLogger->log(Level::DEBUG, TAG, "Starting request with ID: " + newReqId);
+ if (!newRequest->startListening()) {
+ mLogger->log(Level::ERROR, TAG, "Failed to start listening.");
+ return "";
+ }
+
+ // Insert only if its started successfully.
+ mVRRequests.insert(make_pair(voiceAgent->getId(), newRequest));
+
+ return newReqId;
+}
+
+void VRRequestProcessorDelegate::cancelAllRequests() {
+ // Cancel Pending requests
+ if (!mVRRequests.empty()) {
+ auto vrRequestsIt = mVRRequests.begin();
+ while (vrRequestsIt != mVRRequests.end()) {
+ if (!vrRequestsIt->second->cancel()) {
+ mLogger->log(Level::WARNING, TAG, "Failed to cancel request: " + vrRequestsIt->first);
+ }
+ vrRequestsIt++;
+ }
+ mVRRequests.clear();
+ }
+}
+
+unordered_map<string, shared_ptr<VRRequest>> VRRequestProcessorDelegate::getAllRequests() {
+ return mVRRequests;
+}
+
+void VRRequestProcessorDelegate::setDefaultVoiceAgent(shared_ptr<vshl::common::interfaces::IVoiceAgent> voiceAgent) {
+ mDefaultVoiceAgent = voiceAgent;
+}
+
+shared_ptr<vshl::common::interfaces::IVoiceAgent> VRRequestProcessorDelegate::getDefaultVoiceAgent() const {
+ return mDefaultVoiceAgent;
+}
+
+} // namespace core
+} // namespace vshl
diff --git a/src/plugins/core/test/VRRequestProcessorTest.cpp b/src/plugins/core/test/VRRequestProcessorTest.cpp
new file mode 100644
index 0000000..c1a37df
--- /dev/null
+++ b/src/plugins/core/test/VRRequestProcessorTest.cpp
@@ -0,0 +1,213 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include "core/VRRequestProcessor.h"
+#include "voiceagents/include/VoiceAgent.h"
+#include "voiceagents/test/VoiceAgentsTestData.h"
+
+#include "test/common/ConsoleLogger.h"
+#include "test/mocks/AFBApiMock.h"
+
+using namespace vshl::core;
+using namespace vshl::voiceagents;
+using namespace vshl::test::common;
+
+namespace vshl {
+namespace test {
+
+class VRRequestProcessorTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ mConsoleLogger = std::make_shared<ConsoleLogger>();
+ mAfbApi = std::make_shared<::testing::StrictMock<AFBApiMock>>();
+
+ auto vaTestData = *(getVoiceAgentsTestData().begin());
+ mVoiceAgent = VoiceAgent::create(
+ mConsoleLogger,
+ vaTestData.id,
+ vaTestData.name,
+ vaTestData.description,
+ vaTestData.api,
+ vaTestData.vendor,
+ vaTestData.activeWakeword,
+ vaTestData.isActive,
+ vaTestData.wakewords);
+
+ mVRReqProcessorDelegate = VRRequestProcessorDelegate::create(mConsoleLogger, mAfbApi);
+ mVRRequestProcessor = VRRequestProcessor::create(mConsoleLogger, mVRReqProcessorDelegate);
+ }
+
+ std::shared_ptr<::testing::StrictMock<AFBApiMock>> mAfbApi;
+ std::shared_ptr<ConsoleLogger> mConsoleLogger;
+ std::shared_ptr<VoiceAgent> mVoiceAgent;
+
+ std::shared_ptr<VRRequestProcessorDelegate> mVRReqProcessorDelegate;
+ std::shared_ptr<VRRequestProcessor> mVRRequestProcessor;
+};
+
+TEST_F(VRRequestProcessorTest, initializesCorrectly) {
+ ASSERT_NE(mVRRequestProcessor, nullptr);
+}
+
+TEST_F(VRRequestProcessorTest, startListeningFailsOnLackOfDefaultAgent) {
+ auto requestId = mVRRequestProcessor->startListening();
+ ASSERT_EQ(requestId, "");
+}
+
+TEST_F(VRRequestProcessorTest, startListeningAndCancelWorks) {
+ mVRReqProcessorDelegate->setDefaultVoiceAgent(mVoiceAgent);
+
+ {
+ ::testing::InSequence dummy;
+
+ EXPECT_CALL(
+ *mAfbApi,
+ callSync(
+ mVoiceAgent->getApi(),
+ VRRequest::VA_VERB_STARTLISTENING,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_))
+ .Times(1);
+
+ EXPECT_CALL(
+ *mAfbApi,
+ callSync(
+ mVoiceAgent->getApi(),
+ VRRequest::VA_VERB_CANCEL,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_))
+ .Times(1);
+ }
+
+ mVRRequestProcessor->startListening();
+ auto requests = mVRReqProcessorDelegate->getAllRequests();
+ ASSERT_EQ(requests.size(), 1);
+
+ mVRRequestProcessor->cancel();
+ requests = mVRReqProcessorDelegate->getAllRequests();
+ ASSERT_EQ(requests.size(), 0);
+}
+
+TEST_F(VRRequestProcessorTest, requestIsCancelledOnObjectDestruction) {
+ auto delegate = VRRequestProcessorDelegate::create(mConsoleLogger, mAfbApi);
+ auto processor = VRRequestProcessor::create(mConsoleLogger, delegate);
+
+ delegate->setDefaultVoiceAgent(mVoiceAgent);
+
+ {
+ ::testing::InSequence dummy;
+
+ EXPECT_CALL(
+ *mAfbApi,
+ callSync(
+ mVoiceAgent->getApi(),
+ VRRequest::VA_VERB_STARTLISTENING,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_))
+ .Times(1);
+
+ EXPECT_CALL(
+ *mAfbApi,
+ callSync(
+ mVoiceAgent->getApi(),
+ VRRequest::VA_VERB_CANCEL,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_))
+ .Times(1);
+ }
+
+ auto requestId = processor->startListening();
+ ASSERT_NE(requestId, "");
+
+ auto requests = delegate->getAllRequests();
+ ASSERT_EQ(requests.size(), 1);
+}
+
+TEST_F(VRRequestProcessorTest, backToBackStartListeningCancelsEarlierRequest) {
+ mVRReqProcessorDelegate->setDefaultVoiceAgent(mVoiceAgent);
+
+ {
+ ::testing::InSequence dummy;
+
+ EXPECT_CALL(
+ *mAfbApi,
+ callSync(
+ mVoiceAgent->getApi(),
+ VRRequest::VA_VERB_STARTLISTENING,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_))
+ .Times(1);
+
+ EXPECT_CALL(
+ *mAfbApi,
+ callSync(
+ mVoiceAgent->getApi(),
+ VRRequest::VA_VERB_CANCEL,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_))
+ .Times(1);
+
+ EXPECT_CALL(
+ *mAfbApi,
+ callSync(
+ mVoiceAgent->getApi(),
+ VRRequest::VA_VERB_STARTLISTENING,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_))
+ .Times(1);
+
+ EXPECT_CALL(
+ *mAfbApi,
+ callSync(
+ mVoiceAgent->getApi(),
+ VRRequest::VA_VERB_CANCEL,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_))
+ .Times(1);
+ }
+
+ mVRRequestProcessor->startListening();
+ auto requests = mVRReqProcessorDelegate->getAllRequests();
+ ASSERT_EQ(requests.size(), 1);
+
+ mVRRequestProcessor->startListening();
+ requests = mVRReqProcessorDelegate->getAllRequests();
+ ASSERT_EQ(requests.size(), 1);
+
+ mVRRequestProcessor->cancel();
+ requests = mVRReqProcessorDelegate->getAllRequests();
+ ASSERT_EQ(requests.size(), 0);
+}
+
+} // namespace test
+} // namespace vshl \ No newline at end of file
diff --git a/src/plugins/core/test/VRRequestTest.cpp b/src/plugins/core/test/VRRequestTest.cpp
new file mode 100644
index 0000000..b1cd0a6
--- /dev/null
+++ b/src/plugins/core/test/VRRequestTest.cpp
@@ -0,0 +1,101 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include "core/include/VRRequest.h"
+#include "voiceagents/include/VoiceAgent.h"
+#include "voiceagents/test/VoiceAgentsTestData.h"
+
+#include "test/common/ConsoleLogger.h"
+#include "test/mocks/AFBApiMock.h"
+
+using namespace vshl::core;
+using namespace vshl::voiceagents;
+using namespace vshl::test::common;
+
+namespace vshl {
+namespace test {
+
+class VRRequestTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ mRequestId = "Req-0001";
+
+ mConsoleLogger = std::make_shared<ConsoleLogger>();
+ mAfbApi = std::make_shared<::testing::StrictMock<AFBApiMock>>();
+
+ auto vaTestData = *(getVoiceAgentsTestData().begin());
+ mVoiceAgent = VoiceAgent::create(
+ mConsoleLogger,
+ vaTestData.id,
+ vaTestData.name,
+ vaTestData.description,
+ vaTestData.api,
+ vaTestData.vendor,
+ vaTestData.activeWakeword,
+ vaTestData.isActive,
+ vaTestData.wakewords);
+
+ mVRRequest = VRRequest::create(mConsoleLogger, mAfbApi, mRequestId, mVoiceAgent);
+ }
+
+ std::string mRequestId;
+ std::shared_ptr<::testing::StrictMock<AFBApiMock>> mAfbApi;
+ std::shared_ptr<ConsoleLogger> mConsoleLogger;
+ std::shared_ptr<VoiceAgent> mVoiceAgent;
+
+ std::shared_ptr<VRRequest> mVRRequest;
+};
+
+TEST_F(VRRequestTest, initializesCorrectly) {
+ ASSERT_NE(mVRRequest, nullptr);
+}
+
+TEST_F(VRRequestTest, failsCreationOnInvalidParams) {
+ auto vrRequest = VRRequest::create(mConsoleLogger, nullptr, mRequestId, mVoiceAgent);
+ ASSERT_EQ(vrRequest, nullptr);
+
+ vrRequest = VRRequest::create(nullptr, mAfbApi, mRequestId, mVoiceAgent);
+ ASSERT_EQ(vrRequest, nullptr);
+}
+
+TEST_F(VRRequestTest, startsListeningSuccessfully) {
+ EXPECT_CALL(
+ *mAfbApi,
+ callSync(
+ mVoiceAgent->getApi(),
+ VRRequest::VA_VERB_STARTLISTENING,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_,
+ ::testing::_))
+ .Times(1);
+
+ ASSERT_TRUE(mVRRequest->startListening());
+}
+
+TEST_F(VRRequestTest, cancelsSuccessfully) {
+ EXPECT_CALL(
+ *mAfbApi,
+ callSync(
+ mVoiceAgent->getApi(), VRRequest::VA_VERB_CANCEL, ::testing::_, ::testing::_, ::testing::_, ::testing::_))
+ .Times(1);
+
+ ASSERT_TRUE(mVRRequest->cancel());
+}
+
+} // namespace test
+} // namespace vshl \ No newline at end of file