Commit 9fcd5ca2 authored by David Black's avatar David Black Committed by Commit Bot

Adds AssistantResponse.

Previously, Assistant response text/cards/suggestions were streamed in
and rendered immediately. We actually want to cache them until all
renderable elements for an interaction are received, and then show them
all at once.

This is a prerequisite for motion specs which require animating the
response in as a whole and resizing the container smoothly.

To accomplish this, this CL adds:
- AssistantResponse object to hold the renderable elements.
- A cached AssistantResponse in AssistantInteractionController that is
  not added to the model until it is finalized.
- Notification of TTS started event to AssistantInteractionController.
  This is used as an early indication that we have received all
  renderable elements for an interaction.

Bug: b:111932420
Change-Id: I0cc84079183fc30b8c949491e5e2bc4d0b4365b1
Reviewed-on: https://chromium-review.googlesource.com/1153626Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Commit-Queue: David Black <dmblack@google.com>
Cr-Commit-Position: refs/heads/master@{#579859}
parent 0b6da642
...@@ -113,6 +113,8 @@ component("ash") { ...@@ -113,6 +113,8 @@ component("ash") {
"assistant/model/assistant_interaction_model_observer.h", "assistant/model/assistant_interaction_model_observer.h",
"assistant/model/assistant_query.cc", "assistant/model/assistant_query.cc",
"assistant/model/assistant_query.h", "assistant/model/assistant_query.h",
"assistant/model/assistant_response.cc",
"assistant/model/assistant_response.h",
"assistant/model/assistant_screen_context_model.cc", "assistant/model/assistant_screen_context_model.cc",
"assistant/model/assistant_screen_context_model.h", "assistant/model/assistant_screen_context_model.h",
"assistant/model/assistant_screen_context_model_observer.h", "assistant/model/assistant_screen_context_model_observer.h",
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "ash/assistant/assistant_ui_controller.h" #include "ash/assistant/assistant_ui_controller.h"
#include "ash/assistant/model/assistant_interaction_model_observer.h" #include "ash/assistant/model/assistant_interaction_model_observer.h"
#include "ash/assistant/model/assistant_query.h" #include "ash/assistant/model/assistant_query.h"
#include "ash/assistant/model/assistant_response.h"
#include "ash/assistant/model/assistant_ui_element.h" #include "ash/assistant/model/assistant_ui_element.h"
#include "ash/assistant/util/deep_link_util.h" #include "ash/assistant/util/deep_link_util.h"
#include "ash/shell.h" #include "ash/shell.h"
...@@ -172,19 +173,24 @@ void AssistantInteractionController::OnInteractionStarted( ...@@ -172,19 +173,24 @@ void AssistantInteractionController::OnInteractionStarted(
// Clear the interaction to wipe the stage. // Clear the interaction to wipe the stage.
assistant_interaction_model_.ClearInteraction( assistant_interaction_model_.ClearInteraction(
/*retain_committed_query=*/true); /*retain_committed_query=*/true,
/*retain_pending_query=*/false);
} }
// Start caching a new Assistant response for the interaction.
assistant_interaction_model_.SetPendingResponse(
std::make_unique<AssistantResponse>());
} }
void AssistantInteractionController::OnInteractionFinished( void AssistantInteractionController::OnInteractionFinished(
AssistantInteractionResolution resolution) { AssistantInteractionResolution resolution) {
assistant_interaction_model_.SetInteractionState(InteractionState::kInactive); assistant_interaction_model_.SetInteractionState(InteractionState::kInactive);
// When a voice query is interrupted we do not receive any follow up speech
// recognition events but the mic is closed.
if (resolution == AssistantInteractionResolution::kInterruption) {
assistant_interaction_model_.SetMicState(MicState::kClosed); assistant_interaction_model_.SetMicState(MicState::kClosed);
}
// The interaction has finished, so we finalize the pending response if it
// hasn't already been finalized.
if (assistant_interaction_model_.pending_response())
assistant_interaction_model_.FinalizePendingResponse();
} }
void AssistantInteractionController::OnHtmlResponse( void AssistantInteractionController::OnHtmlResponse(
...@@ -194,13 +200,13 @@ void AssistantInteractionController::OnHtmlResponse( ...@@ -194,13 +200,13 @@ void AssistantInteractionController::OnHtmlResponse(
return; return;
} }
assistant_interaction_model_.AddUiElement( assistant_interaction_model_.pending_response()->AddUiElement(
std::make_unique<AssistantCardElement>(response)); std::make_unique<AssistantCardElement>(response));
} }
void AssistantInteractionController::OnSuggestionChipPressed(int id) { void AssistantInteractionController::OnSuggestionChipPressed(int id) {
const AssistantSuggestion* suggestion = const AssistantSuggestion* suggestion =
assistant_interaction_model_.GetSuggestionById(id); assistant_interaction_model_.response()->GetSuggestionById(id);
// If the suggestion contains a non-empty action url, we will handle the // If the suggestion contains a non-empty action url, we will handle the
// suggestion chip pressed event by launching the action url in the browser. // suggestion chip pressed event by launching the action url in the browser.
...@@ -220,7 +226,8 @@ void AssistantInteractionController::OnSuggestionsResponse( ...@@ -220,7 +226,8 @@ void AssistantInteractionController::OnSuggestionsResponse(
return; return;
} }
assistant_interaction_model_.AddSuggestions(std::move(response)); assistant_interaction_model_.pending_response()->AddSuggestions(
std::move(response));
} }
void AssistantInteractionController::OnTextResponse( void AssistantInteractionController::OnTextResponse(
...@@ -230,7 +237,7 @@ void AssistantInteractionController::OnTextResponse( ...@@ -230,7 +237,7 @@ void AssistantInteractionController::OnTextResponse(
return; return;
} }
assistant_interaction_model_.AddUiElement( assistant_interaction_model_.pending_response()->AddUiElement(
std::make_unique<AssistantTextElement>(response)); std::make_unique<AssistantTextElement>(response));
} }
...@@ -261,13 +268,27 @@ void AssistantInteractionController::OnSpeechRecognitionFinalResult( ...@@ -261,13 +268,27 @@ void AssistantInteractionController::OnSpeechRecognitionFinalResult(
// Clear the interaction to wipe the stage. // Clear the interaction to wipe the stage.
assistant_interaction_model_.ClearInteraction( assistant_interaction_model_.ClearInteraction(
/*retain_committed_query=*/true); /*retain_committed_query=*/true,
/*retain_pending_response=*/true);
} }
void AssistantInteractionController::OnSpeechLevelUpdated(float speech_level) { void AssistantInteractionController::OnSpeechLevelUpdated(float speech_level) {
assistant_interaction_model_.SetSpeechLevel(speech_level); assistant_interaction_model_.SetSpeechLevel(speech_level);
} }
void AssistantInteractionController::OnTtsStarted() {
if (assistant_interaction_model_.interaction_state() !=
InteractionState::kActive) {
return;
}
// We have an agreement with the server that TTS will always be the last part
// of an interaction to be processed. To be timely in updating UI, we use
// this as an opportunity to finalize the Assistant response and update the
// interaction model.
assistant_interaction_model_.FinalizePendingResponse();
}
void AssistantInteractionController::OnOpenUrlResponse(const GURL& url) { void AssistantInteractionController::OnOpenUrlResponse(const GURL& url) {
if (assistant_interaction_model_.interaction_state() != if (assistant_interaction_model_.interaction_state() !=
InteractionState::kActive) { InteractionState::kActive) {
...@@ -329,6 +350,11 @@ void AssistantInteractionController::StopActiveInteraction() { ...@@ -329,6 +350,11 @@ void AssistantInteractionController::StopActiveInteraction() {
assistant_interaction_model_.SetInteractionState(InteractionState::kInactive); assistant_interaction_model_.SetInteractionState(InteractionState::kInactive);
assistant_interaction_model_.ClearPendingQuery(); assistant_interaction_model_.ClearPendingQuery();
assistant_->StopActiveInteraction(); assistant_->StopActiveInteraction();
// Because we are stopping an interaction in progress, we discard any pending
// response for it that is cached to prevent it from being finalized when the
// interaction is finished.
assistant_interaction_model_.ClearPendingResponse();
} }
} // namespace ash } // namespace ash
...@@ -87,6 +87,7 @@ class AssistantInteractionController ...@@ -87,6 +87,7 @@ class AssistantInteractionController
void OnSpeechRecognitionEndOfUtterance() override; void OnSpeechRecognitionEndOfUtterance() override;
void OnSpeechRecognitionFinalResult(const std::string& final_result) override; void OnSpeechRecognitionFinalResult(const std::string& final_result) override;
void OnSpeechLevelUpdated(float speech_level) override; void OnSpeechLevelUpdated(float speech_level) override;
void OnTtsStarted() override;
// DialogPlateObserver: // DialogPlateObserver:
void OnDialogPlateButtonPressed(DialogPlateButtonId id) override; void OnDialogPlateButtonPressed(DialogPlateButtonId id) override;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include "ash/assistant/model/assistant_interaction_model_observer.h" #include "ash/assistant/model/assistant_interaction_model_observer.h"
#include "ash/assistant/model/assistant_query.h" #include "ash/assistant/model/assistant_query.h"
#include "ash/assistant/model/assistant_ui_element.h" #include "ash/assistant/model/assistant_response.h"
namespace ash { namespace ash {
...@@ -26,13 +26,22 @@ void AssistantInteractionModel::RemoveObserver( ...@@ -26,13 +26,22 @@ void AssistantInteractionModel::RemoveObserver(
observers_.RemoveObserver(observer); observers_.RemoveObserver(observer);
} }
void AssistantInteractionModel::ClearInteraction(bool retain_committed_query) { void AssistantInteractionModel::ClearInteraction() {
ClearInteraction(/*retain_committed_query=*/false,
/*retain_pending_response=*/false);
}
void AssistantInteractionModel::ClearInteraction(bool retain_committed_query,
bool retain_pending_response) {
if (!retain_committed_query) if (!retain_committed_query)
ClearCommittedQuery(); ClearCommittedQuery();
ClearPendingQuery(); ClearPendingQuery();
ClearUiElements();
ClearSuggestions(); if (!retain_pending_response)
ClearPendingResponse();
ClearResponse();
} }
void AssistantInteractionModel::SetInteractionState( void AssistantInteractionModel::SetInteractionState(
...@@ -93,44 +102,24 @@ void AssistantInteractionModel::ClearPendingQuery() { ...@@ -93,44 +102,24 @@ void AssistantInteractionModel::ClearPendingQuery() {
NotifyPendingQueryCleared(); NotifyPendingQueryCleared();
} }
void AssistantInteractionModel::AddUiElement( void AssistantInteractionModel::SetPendingResponse(
std::unique_ptr<AssistantUiElement> ui_element) { std::unique_ptr<AssistantResponse> pending_response) {
AssistantUiElement* ptr = ui_element.get(); pending_response_ = std::move(pending_response);
ui_element_list_.push_back(std::move(ui_element));
NotifyUiElementAdded(ptr);
} }
void AssistantInteractionModel::ClearUiElements() { void AssistantInteractionModel::FinalizePendingResponse() {
ui_element_list_.clear(); DCHECK(pending_response_);
NotifyUiElementsCleared(); response_ = std::move(pending_response_);
} NotifyResponseChanged();
void AssistantInteractionModel::AddSuggestions(
std::vector<AssistantSuggestionPtr> suggestions) {
std::map<int, AssistantSuggestion*> ptrs;
// We use vector index to uniquely identify a given suggestion. This means
// that suggestion ids will reset with each call to |ClearSuggestions|, but
// that is acceptable.
for (AssistantSuggestionPtr& suggestion : suggestions) {
int id = suggestions_.size();
suggestions_.push_back(std::move(suggestion));
ptrs[id] = suggestions_.back().get();
}
NotifySuggestionsAdded(ptrs);
} }
const AssistantInteractionModel::AssistantSuggestion* void AssistantInteractionModel::ClearPendingResponse() {
AssistantInteractionModel::GetSuggestionById(int id) const { pending_response_.reset();
return id >= 0 && id < static_cast<int>(suggestions_.size())
? suggestions_.at(id).get()
: nullptr;
} }
void AssistantInteractionModel::ClearSuggestions() { void AssistantInteractionModel::ClearResponse() {
suggestions_.clear(); response_.reset();
NotifySuggestionsCleared(); NotifyResponseCleared();
} }
void AssistantInteractionModel::SetSpeechLevel(float speech_level_db) { void AssistantInteractionModel::SetSpeechLevel(float speech_level_db) {
...@@ -172,26 +161,14 @@ void AssistantInteractionModel::NotifyPendingQueryCleared() { ...@@ -172,26 +161,14 @@ void AssistantInteractionModel::NotifyPendingQueryCleared() {
observer.OnPendingQueryCleared(); observer.OnPendingQueryCleared();
} }
void AssistantInteractionModel::NotifyUiElementAdded( void AssistantInteractionModel::NotifyResponseChanged() {
const AssistantUiElement* ui_element) {
for (AssistantInteractionModelObserver& observer : observers_)
observer.OnUiElementAdded(ui_element);
}
void AssistantInteractionModel::NotifyUiElementsCleared() {
for (AssistantInteractionModelObserver& observer : observers_)
observer.OnUiElementsCleared();
}
void AssistantInteractionModel::NotifySuggestionsAdded(
const std::map<int, AssistantSuggestion*>& suggestions) {
for (AssistantInteractionModelObserver& observer : observers_) for (AssistantInteractionModelObserver& observer : observers_)
observer.OnSuggestionsAdded(suggestions); observer.OnResponseChanged(*response_);
} }
void AssistantInteractionModel::NotifySuggestionsCleared() { void AssistantInteractionModel::NotifyResponseCleared() {
for (AssistantInteractionModelObserver& observer : observers_) for (AssistantInteractionModelObserver& observer : observers_)
observer.OnSuggestionsCleared(); observer.OnResponseCleared();
} }
void AssistantInteractionModel::NotifySpeechLevelChanged( void AssistantInteractionModel::NotifySpeechLevelChanged(
......
...@@ -11,13 +11,12 @@ ...@@ -11,13 +11,12 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
namespace ash { namespace ash {
class AssistantInteractionModelObserver; class AssistantInteractionModelObserver;
class AssistantQuery; class AssistantQuery;
class AssistantUiElement; class AssistantResponse;
// Enumeration of interaction input modalities. // Enumeration of interaction input modalities.
enum class InputModality { enum class InputModality {
...@@ -42,13 +41,9 @@ enum class MicState { ...@@ -42,13 +41,9 @@ enum class MicState {
}; };
// Models the Assistant interaction. This includes query state, state of speech // Models the Assistant interaction. This includes query state, state of speech
// recognition, as well as renderable AssistantUiElements and suggestions. // recognition, as well as a renderable AssistantResponse.
class AssistantInteractionModel { class AssistantInteractionModel {
public: public:
using AssistantSuggestion = chromeos::assistant::mojom::AssistantSuggestion;
using AssistantSuggestionPtr =
chromeos::assistant::mojom::AssistantSuggestionPtr;
AssistantInteractionModel(); AssistantInteractionModel();
~AssistantInteractionModel(); ~AssistantInteractionModel();
...@@ -56,10 +51,16 @@ class AssistantInteractionModel { ...@@ -56,10 +51,16 @@ class AssistantInteractionModel {
void AddObserver(AssistantInteractionModelObserver* observer); void AddObserver(AssistantInteractionModelObserver* observer);
void RemoveObserver(AssistantInteractionModelObserver* observer); void RemoveObserver(AssistantInteractionModelObserver* observer);
// Resets the interaction to its initial state.
void ClearInteraction();
// Resets the interaction to its initial state. There are instances in which // Resets the interaction to its initial state. There are instances in which
// we wish to clear the interaction but retain the committed query. As such, // we wish to clear the interaction but retain the committed query. Similarly,
// |retain_committed_query| is provided but defaults to |false|. // there are instances in which we wish to retain the pending response that is
void ClearInteraction(bool retain_committed_query = false); // currently cached. For such instances, use |retain_committed_query| and
// |retain_pending_response| respectively.
void ClearInteraction(bool retain_committed_query,
bool retain_pending_response);
// Sets the interaction state. // Sets the interaction state.
void SetInteractionState(InteractionState interaction_state); void SetInteractionState(InteractionState interaction_state);
...@@ -97,23 +98,23 @@ class AssistantInteractionModel { ...@@ -97,23 +98,23 @@ class AssistantInteractionModel {
// Clears the pending query for the interaction. // Clears the pending query for the interaction.
void ClearPendingQuery(); void ClearPendingQuery();
// Adds the specified |ui_element| that should be rendered for the // Sets the pending response for the interaction.
// interaction. void SetPendingResponse(std::unique_ptr<AssistantResponse> response);
void AddUiElement(std::unique_ptr<AssistantUiElement> ui_element);
// Returns the pending response for the interaction.
AssistantResponse* pending_response() { return pending_response_.get(); }
// Clears all UI elements for the interaction. // Finalizes the pending response for the interaction.
void ClearUiElements(); void FinalizePendingResponse();
// Adds the specified |suggestions| that should be rendered for the // Clears the pending response for the interaction.
// interaction. void ClearPendingResponse();
void AddSuggestions(std::vector<AssistantSuggestionPtr> suggestions);
// Returns the suggestion uniquely identified by the specified |id|, or // Returns the finalized response for the interaction.
// |nullptr| if no matching suggestion is found. const AssistantResponse* response() const { return response_.get(); }
const AssistantSuggestion* GetSuggestionById(int id) const;
// Clears all suggestions for the interaction. // Clears the finalized response for the interaction.
void ClearSuggestions(); void ClearResponse();
// Updates the speech level in dB. // Updates the speech level in dB.
void SetSpeechLevel(float speech_level_db); void SetSpeechLevel(float speech_level_db);
...@@ -126,11 +127,8 @@ class AssistantInteractionModel { ...@@ -126,11 +127,8 @@ class AssistantInteractionModel {
void NotifyCommittedQueryCleared(); void NotifyCommittedQueryCleared();
void NotifyPendingQueryChanged(); void NotifyPendingQueryChanged();
void NotifyPendingQueryCleared(); void NotifyPendingQueryCleared();
void NotifyUiElementAdded(const AssistantUiElement* ui_element); void NotifyResponseChanged();
void NotifyUiElementsCleared(); void NotifyResponseCleared();
void NotifySuggestionsAdded(
const std::map<int, AssistantSuggestion*>& suggestions);
void NotifySuggestionsCleared();
void NotifySpeechLevelChanged(float speech_level_db); void NotifySpeechLevelChanged(float speech_level_db);
InteractionState interaction_state_ = InteractionState::kInactive; InteractionState interaction_state_ = InteractionState::kInactive;
...@@ -138,8 +136,8 @@ class AssistantInteractionModel { ...@@ -138,8 +136,8 @@ class AssistantInteractionModel {
MicState mic_state_ = MicState::kClosed; MicState mic_state_ = MicState::kClosed;
std::unique_ptr<AssistantQuery> committed_query_; std::unique_ptr<AssistantQuery> committed_query_;
std::unique_ptr<AssistantQuery> pending_query_; std::unique_ptr<AssistantQuery> pending_query_;
std::vector<AssistantSuggestionPtr> suggestions_; std::unique_ptr<AssistantResponse> pending_response_;
std::vector<std::unique_ptr<AssistantUiElement>> ui_element_list_; std::unique_ptr<AssistantResponse> response_;
base::ObserverList<AssistantInteractionModelObserver> observers_; base::ObserverList<AssistantInteractionModelObserver> observers_;
......
...@@ -11,18 +11,10 @@ ...@@ -11,18 +11,10 @@
#include "base/macros.h" #include "base/macros.h"
namespace chromeos {
namespace assistant {
namespace mojom {
class AssistantSuggestion;
} // namespace mojom
} // namespace assistant
} // namespace chromeos
namespace ash { namespace ash {
class AssistantQuery; class AssistantQuery;
class AssistantUiElement; class AssistantResponse;
enum class InputModality; enum class InputModality;
enum class InteractionState; enum class InteractionState;
enum class MicState; enum class MicState;
...@@ -31,8 +23,6 @@ enum class MicState; ...@@ -31,8 +23,6 @@ enum class MicState;
// interaction. // interaction.
class AssistantInteractionModelObserver { class AssistantInteractionModelObserver {
public: public:
using AssistantSuggestion = chromeos::assistant::mojom::AssistantSuggestion;
// Invoked when the interaction state is changed. // Invoked when the interaction state is changed.
virtual void OnInteractionStateChanged(InteractionState interaction_state) {} virtual void OnInteractionStateChanged(InteractionState interaction_state) {}
...@@ -56,21 +46,11 @@ class AssistantInteractionModelObserver { ...@@ -56,21 +46,11 @@ class AssistantInteractionModelObserver {
// Invoked when the pending query associated with the interaction is cleared. // Invoked when the pending query associated with the interaction is cleared.
virtual void OnPendingQueryCleared() {} virtual void OnPendingQueryCleared() {}
// Invoked when a UI element associated with the interaction is added. // Invoked when the response associated with the interaction is changed.
virtual void OnUiElementAdded(const AssistantUiElement* ui_element) {} virtual void OnResponseChanged(const AssistantResponse& response) {}
// Invoked when all UI elements associated with the interaction are cleared.
virtual void OnUiElementsCleared() {}
// Invoked when the specified |suggestions| are added to the associated
// interaction. The key for the map is the unique identifier by which the
// interaction model identifies each suggestion before the next
// |OnSuggestionsCleared| call.
virtual void OnSuggestionsAdded(
const std::map<int, AssistantSuggestion*>& suggestions) {}
// Invoked when all suggestions associated with the interaction are cleared. // Invoked when the response associated with the interaction is cleared.
virtual void OnSuggestionsCleared() {} virtual void OnResponseCleared() {}
// Invoked when the speech level is changed. // Invoked when the speech level is changed.
virtual void OnSpeechLevelChanged(float speech_level_db) {} virtual void OnSpeechLevelChanged(float speech_level_db) {}
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/assistant/model/assistant_response.h"
#include "ash/assistant/model/assistant_ui_element.h"
namespace ash {
AssistantResponse::AssistantResponse() = default;
AssistantResponse::~AssistantResponse() = default;
void AssistantResponse::AddUiElement(
std::unique_ptr<AssistantUiElement> ui_element) {
ui_elements_.push_back(std::move(ui_element));
}
const std::vector<std::unique_ptr<AssistantUiElement>>&
AssistantResponse::GetUiElements() const {
return ui_elements_;
}
void AssistantResponse::AddSuggestions(
std::vector<AssistantSuggestionPtr> suggestions) {
for (AssistantSuggestionPtr& suggestion : suggestions)
suggestions_.push_back(std::move(suggestion));
}
const chromeos::assistant::mojom::AssistantSuggestion*
AssistantResponse::GetSuggestionById(int id) const {
// We consider the index of a suggestion within our backing vector to be its
// unique identifier.
DCHECK_GE(id, 0);
DCHECK_LT(id, static_cast<int>(suggestions_.size()));
return suggestions_.at(id).get();
}
std::map<int, const chromeos::assistant::mojom::AssistantSuggestion*>
AssistantResponse::GetSuggestions() const {
std::map<int, const AssistantSuggestion*> suggestions;
// We use index within our backing vector to represent the unique identifier
// for a suggestion.
int id = 0;
for (const AssistantSuggestionPtr& suggestion : suggestions_)
suggestions[id++] = suggestion.get();
return suggestions;
}
} // namespace ash
\ No newline at end of file
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_ASSISTANT_MODEL_ASSISTANT_RESPONSE_H_
#define ASH_ASSISTANT_MODEL_ASSISTANT_RESPONSE_H_
#include <map>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
namespace ash {
class AssistantUiElement;
// Models a renderable Assistant response.
class AssistantResponse {
public:
using AssistantSuggestion = chromeos::assistant::mojom::AssistantSuggestion;
using AssistantSuggestionPtr =
chromeos::assistant::mojom::AssistantSuggestionPtr;
AssistantResponse();
~AssistantResponse();
// Adds the specified |ui_element| that should be rendered for the
// interaction.
void AddUiElement(std::unique_ptr<AssistantUiElement> ui_element);
// Returns all UI elements belonging to the response.
const std::vector<std::unique_ptr<AssistantUiElement>>& GetUiElements() const;
// Adds the specified |suggestions| that should be rendered for the
// interaction.
void AddSuggestions(std::vector<AssistantSuggestionPtr> suggestions);
// Returns the suggestion uniquely identified by |id|, or |nullptr| if no
// matching suggestion exists.
const AssistantSuggestion* GetSuggestionById(int id) const;
// Returns all suggestions belongs to the response, mapped to a unique id.
std::map<int, const AssistantSuggestion*> GetSuggestions() const;
private:
std::vector<std::unique_ptr<AssistantUiElement>> ui_elements_;
std::vector<AssistantSuggestionPtr> suggestions_;
DISALLOW_COPY_AND_ASSIGN(AssistantResponse);
};
} // namespace ash
#endif // ASH_ASSISTANT_MODEL_ASSISTANT_RESPONSE_H_
...@@ -114,13 +114,13 @@ void DialogPlate::InitLayout() { ...@@ -114,13 +114,13 @@ void DialogPlate::InitLayout() {
input_modality_layout_container->SetPaintToLayer(); input_modality_layout_container->SetPaintToLayer();
input_modality_layout_container->layer()->SetFillsBoundsOpaquely(false); input_modality_layout_container->layer()->SetFillsBoundsOpaquely(false);
input_modality_layout_container->layer()->SetMasksToBounds(true); input_modality_layout_container->layer()->SetMasksToBounds(true);
AddChildView(input_modality_layout_container);
layout_manager->SetFlexForView(input_modality_layout_container, 1);
InitKeyboardLayoutContainer(input_modality_layout_container); InitKeyboardLayoutContainer(input_modality_layout_container);
InitVoiceLayoutContainer(input_modality_layout_container); InitVoiceLayoutContainer(input_modality_layout_container);
layout_manager->SetFlexForView(input_modality_layout_container, 1);
AddChildView(input_modality_layout_container);
// Settings. // Settings.
views::ImageButton* settings_button = new views::ImageButton(this); views::ImageButton* settings_button = new views::ImageButton(this);
settings_button->set_id(static_cast<int>(DialogPlateButtonId::kSettings)); settings_button->set_id(static_cast<int>(DialogPlateButtonId::kSettings));
......
...@@ -107,8 +107,7 @@ void AssistantHeaderView::OnCommittedQueryChanged( ...@@ -107,8 +107,7 @@ void AssistantHeaderView::OnCommittedQueryChanged(
progress_indicator_->SetVisible(true); progress_indicator_->SetVisible(true);
} }
void AssistantHeaderView::OnUiElementAdded( void AssistantHeaderView::OnResponseChanged(const AssistantResponse& response) {
const AssistantUiElement* ui_element) {
progress_indicator_->SetVisible(false); progress_indicator_->SetVisible(false);
} }
......
...@@ -36,7 +36,7 @@ class AssistantHeaderView : public views::View, ...@@ -36,7 +36,7 @@ class AssistantHeaderView : public views::View,
// AssistantInteractionModelObserver: // AssistantInteractionModelObserver:
void OnCommittedQueryChanged(const AssistantQuery& committed_query) override; void OnCommittedQueryChanged(const AssistantQuery& committed_query) override;
void OnUiElementAdded(const AssistantUiElement* ui_element) override; void OnResponseChanged(const AssistantResponse& response) override;
// AssistantUiModelObserver: // AssistantUiModelObserver:
void OnUiVisibilityChanged(bool visible, AssistantSource source) override; void OnUiVisibilityChanged(bool visible, AssistantSource source) override;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "ash/assistant/assistant_controller.h" #include "ash/assistant/assistant_controller.h"
#include "ash/assistant/assistant_interaction_controller.h" #include "ash/assistant/assistant_interaction_controller.h"
#include "ash/assistant/model/assistant_response.h"
#include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/ui/assistant_ui_constants.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "ui/views/controls/scrollbar/overlay_scroll_bar.h" #include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
...@@ -81,9 +82,11 @@ void SuggestionContainerView::InitLayout() { ...@@ -81,9 +82,11 @@ void SuggestionContainerView::InitLayout() {
SetVerticalScrollBar(new InvisibleScrollBar(/*horizontal=*/false)); SetVerticalScrollBar(new InvisibleScrollBar(/*horizontal=*/false));
} }
void SuggestionContainerView::OnSuggestionsAdded( void SuggestionContainerView::OnResponseChanged(
const std::map<int, AssistantSuggestion*>& suggestions) { const AssistantResponse& response) {
for (const std::pair<int, AssistantSuggestion*>& suggestion : suggestions) { using AssistantSuggestion = chromeos::assistant::mojom::AssistantSuggestion;
for (const std::pair<int, const AssistantSuggestion*>& suggestion :
response.GetSuggestions()) {
// We will use the same identifier by which the Assistant interaction model // We will use the same identifier by which the Assistant interaction model
// uniquely identifies a suggestion to uniquely identify its corresponding // uniquely identifies a suggestion to uniquely identify its corresponding
// suggestion chip view. // suggestion chip view.
...@@ -120,10 +123,11 @@ void SuggestionContainerView::OnSuggestionsAdded( ...@@ -120,10 +123,11 @@ void SuggestionContainerView::OnSuggestionsAdded(
contents_view_->AddChildView(suggestion_chip_view); contents_view_->AddChildView(suggestion_chip_view);
} }
UpdateContentsBounds(); UpdateContentsBounds();
} }
void SuggestionContainerView::OnSuggestionsCleared() { void SuggestionContainerView::OnResponseCleared() {
// Abort any download requests in progress. // Abort any download requests in progress.
download_request_weak_factory_.InvalidateWeakPtrs(); download_request_weak_factory_.InvalidateWeakPtrs();
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "ash/app_list/views/suggestion_chip_view.h" #include "ash/app_list/views/suggestion_chip_view.h"
#include "ash/assistant/model/assistant_interaction_model_observer.h" #include "ash/assistant/model/assistant_interaction_model_observer.h"
#include "base/macros.h" #include "base/macros.h"
#include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
#include "ui/views/controls/scroll_view.h" #include "ui/views/controls/scroll_view.h"
namespace ash { namespace ash {
...@@ -33,9 +34,8 @@ class SuggestionContainerView : public views::ScrollView, ...@@ -33,9 +34,8 @@ class SuggestionContainerView : public views::ScrollView,
int GetHeightForWidth(int width) const override; int GetHeightForWidth(int width) const override;
// AssistantInteractionModelObserver: // AssistantInteractionModelObserver:
void OnSuggestionsAdded( void OnResponseChanged(const AssistantResponse& response) override;
const std::map<int, AssistantSuggestion*>& suggestions) override; void OnResponseCleared() override;
void OnSuggestionsCleared() override;
// views::ButtonListener: // views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override; void ButtonPressed(views::Button* sender, const ui::Event& event) override;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "ash/assistant/assistant_controller.h" #include "ash/assistant/assistant_controller.h"
#include "ash/assistant/assistant_interaction_controller.h" #include "ash/assistant/assistant_interaction_controller.h"
#include "ash/assistant/model/assistant_response.h"
#include "ash/assistant/model/assistant_ui_element.h" #include "ash/assistant/model/assistant_ui_element.h"
#include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/ui/assistant_ui_constants.h"
#include "ash/assistant/ui/main_stage/assistant_header_view.h" #include "ash/assistant/ui/main_stage/assistant_header_view.h"
...@@ -63,26 +64,24 @@ void UiElementContainerView::InitLayout() { ...@@ -63,26 +64,24 @@ void UiElementContainerView::InitLayout() {
AddChildView(assistant_header_view_.get()); AddChildView(assistant_header_view_.get());
} }
void UiElementContainerView::OnUiElementAdded( void UiElementContainerView::OnResponseChanged(
const AssistantUiElement* ui_element) { const AssistantResponse& response) {
// If we are processing a UI element we need to pend the incoming element OnResponseCleared();
// instead of handling it immediately.
for (const std::unique_ptr<AssistantUiElement>& ui_element :
response.GetUiElements()) {
// If we are processing a UI element we need to pend the incoming elements
// instead of handling them immediately.
if (is_processing_ui_element_) { if (is_processing_ui_element_) {
pending_ui_element_list_.push_back(ui_element); pending_ui_element_list_.push_back(ui_element.get());
return; continue;
} }
switch (ui_element->GetType()) { OnUiElementAdded(ui_element.get());
case AssistantUiElementType::kCard:
OnCardElementAdded(static_cast<const AssistantCardElement*>(ui_element));
break;
case AssistantUiElementType::kText:
OnTextElementAdded(static_cast<const AssistantTextElement*>(ui_element));
break;
} }
} }
void UiElementContainerView::OnUiElementsCleared() { void UiElementContainerView::OnResponseCleared() {
// Prevent any in-flight card rendering requests from returning. // Prevent any in-flight card rendering requests from returning.
render_request_weak_factory_.InvalidateWeakPtrs(); render_request_weak_factory_.InvalidateWeakPtrs();
...@@ -98,6 +97,18 @@ void UiElementContainerView::OnUiElementsCleared() { ...@@ -98,6 +97,18 @@ void UiElementContainerView::OnUiElementsCleared() {
SetProcessingUiElement(false); SetProcessingUiElement(false);
} }
void UiElementContainerView::OnUiElementAdded(
const AssistantUiElement* ui_element) {
switch (ui_element->GetType()) {
case AssistantUiElementType::kCard:
OnCardElementAdded(static_cast<const AssistantCardElement*>(ui_element));
break;
case AssistantUiElementType::kText:
OnTextElementAdded(static_cast<const AssistantTextElement*>(ui_element));
break;
}
}
void UiElementContainerView::OnCardElementAdded( void UiElementContainerView::OnCardElementAdded(
const AssistantCardElement* card_element) { const AssistantCardElement* card_element) {
DCHECK(!is_processing_ui_element_); DCHECK(!is_processing_ui_element_);
......
...@@ -18,6 +18,7 @@ namespace ash { ...@@ -18,6 +18,7 @@ namespace ash {
class AssistantCardElement; class AssistantCardElement;
class AssistantController; class AssistantController;
class AssistantHeaderView; class AssistantHeaderView;
class AssistantResponse;
class AssistantTextElement; class AssistantTextElement;
class AssistantUiElement; class AssistantUiElement;
...@@ -34,12 +35,13 @@ class UiElementContainerView : public views::View, ...@@ -34,12 +35,13 @@ class UiElementContainerView : public views::View,
void ChildPreferredSizeChanged(views::View* child) override; void ChildPreferredSizeChanged(views::View* child) override;
// AssistantInteractionModelObserver: // AssistantInteractionModelObserver:
void OnUiElementAdded(const AssistantUiElement* ui_element) override; void OnResponseChanged(const AssistantResponse& response) override;
void OnUiElementsCleared() override; void OnResponseCleared() override;
private: private:
void InitLayout(); void InitLayout();
void OnUiElementAdded(const AssistantUiElement* ui_element);
void OnCardElementAdded(const AssistantCardElement* card_element); void OnCardElementAdded(const AssistantCardElement* card_element);
void OnCardReady(const base::Optional<base::UnguessableToken>& embed_token); void OnCardReady(const base::Optional<base::UnguessableToken>& embed_token);
void OnTextElementAdded(const AssistantTextElement* text_element); void OnTextElementAdded(const AssistantTextElement* text_element);
......
...@@ -371,6 +371,14 @@ void AssistantManagerServiceImpl::OnRecognitionStateChanged( ...@@ -371,6 +371,14 @@ void AssistantManagerServiceImpl::OnRecognitionStateChanged(
weak_factory_.GetWeakPtr(), state, recognition_result)); weak_factory_.GetWeakPtr(), state, recognition_result));
} }
void AssistantManagerServiceImpl::OnRespondingStarted(bool is_error_response) {
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&AssistantManagerServiceImpl::OnRespondingStartedOnMainThread,
weak_factory_.GetWeakPtr()));
}
void AssistantManagerServiceImpl::OnSpeechLevelUpdated( void AssistantManagerServiceImpl::OnSpeechLevelUpdated(
const float speech_level) { const float speech_level) {
main_thread_task_runner_->PostTask( main_thread_task_runner_->PostTask(
...@@ -715,6 +723,10 @@ void AssistantManagerServiceImpl::OnRecognitionStateChangedOnMainThread( ...@@ -715,6 +723,10 @@ void AssistantManagerServiceImpl::OnRecognitionStateChangedOnMainThread(
} }
} }
void AssistantManagerServiceImpl::OnRespondingStartedOnMainThread() {
interaction_subscribers_.ForAllPtrs([](auto* ptr) { ptr->OnTtsStarted(); });
}
void AssistantManagerServiceImpl::OnSpeechLevelUpdatedOnMainThread( void AssistantManagerServiceImpl::OnSpeechLevelUpdatedOnMainThread(
const float speech_level) { const float speech_level) {
interaction_subscribers_.ForAllPtrs( interaction_subscribers_.ForAllPtrs(
......
...@@ -119,6 +119,7 @@ class AssistantManagerServiceImpl ...@@ -119,6 +119,7 @@ class AssistantManagerServiceImpl
assistant_client::ConversationStateListener::RecognitionState state, assistant_client::ConversationStateListener::RecognitionState state,
const assistant_client::ConversationStateListener::RecognitionResult& const assistant_client::ConversationStateListener::RecognitionResult&
recognition_result) override; recognition_result) override;
void OnRespondingStarted(bool is_error_response) override;
// AssistantManagerDelegate overrides // AssistantManagerDelegate overrides
assistant_client::ActionModule::Result HandleModifySettingClientOp( assistant_client::ActionModule::Result HandleModifySettingClientOp(
...@@ -177,6 +178,7 @@ class AssistantManagerServiceImpl ...@@ -177,6 +178,7 @@ class AssistantManagerServiceImpl
assistant_client::ConversationStateListener::RecognitionState state, assistant_client::ConversationStateListener::RecognitionState state,
const assistant_client::ConversationStateListener::RecognitionResult& const assistant_client::ConversationStateListener::RecognitionResult&
recognition_result); recognition_result);
void OnRespondingStartedOnMainThread();
void OnSpeechLevelUpdatedOnMainThread(const float speech_level); void OnSpeechLevelUpdatedOnMainThread(const float speech_level);
void OnModifySettingsAction(const std::string& modify_setting_args_proto); void OnModifySettingsAction(const std::string& modify_setting_args_proto);
......
...@@ -90,6 +90,9 @@ interface AssistantInteractionSubscriber { ...@@ -90,6 +90,9 @@ interface AssistantInteractionSubscriber {
// Assistant got an instantaneous speech level update in dB. // Assistant got an instantaneous speech level update in dB.
OnSpeechLevelUpdated(float speech_level); OnSpeechLevelUpdated(float speech_level);
// Assistant has started speaking.
OnTtsStarted();
}; };
// Subscribes to assistant's notification event. These events are server // Subscribes to assistant's notification event. These events are server
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment