Commit 1a282780 authored by Jeroen Dhollander's avatar Jeroen Dhollander Committed by Commit Bot

Simplify initialization of AssistantManager

The code to initialize the |AssistantManager| was quite complex because
it had to handle the fact that |AssistantManager| was created on a
background thread, and that this background task could be triggered
multiple times before it ever finished.

To simplify this the |AssistantManager| (and its related classes) is now
owned by an |AssistantManagerController| that will:
   * Ensure the |done_callback| is invoked only once, even if multiple
     controllers are created (we achieve this by storing the controller
     in a unique_ptr and ensuring it only calls the callback if the
     controller was not deleted, meaning only the last controller will
     call the callback).
   * Not access the |assistant_manager_| field from the background
     thread, meaning it can always safely be accessed from the main
     thread.

This simplification will make it easier to move the Libassistant process
to a sandbox.

Bug: b/171748795
Test: chromeos_unittest --gtest_filter="AssistantManagerServiceTest.*"
Change-Id: Icfce1163d5253713094145b5d7e7c637057527c0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2500452
Commit-Queue: Jeroen Dhollander <jeroendh@chromium.org>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#823195}
parent a3df8027
......@@ -63,6 +63,8 @@ component("lib") {
sources += [
"assistant_device_settings_delegate.cc",
"assistant_device_settings_delegate.h",
"assistant_manager_controller.cc",
"assistant_manager_controller.h",
"assistant_manager_service_delegate.h",
"assistant_manager_service_delegate_impl.cc",
"assistant_manager_service_delegate_impl.h",
......
// Copyright 2020 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 "chromeos/services/assistant/assistant_manager_controller.h"
#include "base/feature_list.h"
#include "chromeos/assistant/internal/cros_display_connection.h"
#include "chromeos/assistant/internal/internal_util.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/services/assistant/assistant_manager_service_delegate.h"
#include "chromeos/services/assistant/assistant_manager_service_impl.h"
#include "chromeos/services/assistant/public/cpp/features.h"
#include "libassistant/shared/internal_api/assistant_manager_internal.h"
namespace chromeos {
namespace assistant {
namespace {
using DoneCallback =
base::OnceCallback<void(std::unique_ptr<CrosDisplayConnection>,
std::unique_ptr<assistant_client::AssistantManager>,
assistant_client::AssistantManagerInternal*)>;
constexpr base::Feature kChromeOSAssistantDogfood{
"ChromeOSAssistantDogfood", base::FEATURE_DISABLED_BY_DEFAULT};
constexpr char kServersideDogfoodExperimentId[] = "20347368";
constexpr char kServersideOpenAppExperimentId[] = "39651593";
constexpr char kServersideResponseProcessingV2ExperimentId[] = "1793869";
struct AssistantObjects {
std::unique_ptr<CrosDisplayConnection> display_connection;
std::unique_ptr<assistant_client::AssistantManager> assistant_manager;
assistant_client::AssistantManagerInternal* assistant_manager_internal =
nullptr;
};
void FillServerExperimentIds(std::vector<std::string>* server_experiment_ids) {
if (base::FeatureList::IsEnabled(kChromeOSAssistantDogfood)) {
server_experiment_ids->emplace_back(kServersideDogfoodExperimentId);
}
if (base::FeatureList::IsEnabled(features::kAssistantAppSupport))
server_experiment_ids->emplace_back(kServersideOpenAppExperimentId);
if (features::IsResponseProcessingV2Enabled()) {
server_experiment_ids->emplace_back(
kServersideResponseProcessingV2ExperimentId);
}
}
void SetServerExperiments(
assistant_client::AssistantManagerInternal* assistant_manager_internal) {
std::vector<std::string> server_experiment_ids;
FillServerExperimentIds(&server_experiment_ids);
if (server_experiment_ids.size() > 0) {
assistant_manager_internal->AddExtraExperimentIds(server_experiment_ids);
}
}
void SetAuthTokens(assistant_client::AssistantManager* assistant_manager,
const AssistantManagerController::AuthTokens& tokens) {
assistant_manager->SetAuthTokens(tokens);
}
void UpdateInternalOptions(
assistant_client::AssistantManagerInternal* assistant_manager_internal,
const std::string& locale,
bool spoken_feedback_enabled) {
// NOTE: this method is called on multiple threads, it needs to be
// thread-safe.
auto* internal_options =
assistant_manager_internal->CreateDefaultInternalOptions();
SetAssistantOptions(internal_options, locale, spoken_feedback_enabled);
internal_options->SetClientControlEnabled(
assistant::features::IsRoutinesEnabled());
if (!features::IsVoiceMatchDisabled())
internal_options->EnableRequireVoiceMatchVerification();
assistant_manager_internal->SetOptions(*internal_options, [](bool success) {
DVLOG(2) << "set options: " << success;
});
}
// Creates the Assistant on the current thread, and stores the resulting
// objects in |result|.
void CreateAssistantOnCurrentThread(
AssistantObjects* result,
AssistantManagerServiceDelegate* delegate,
assistant_client::PlatformApi* platform_api,
assistant_client::ActionModule* action_module,
assistant_client::FuchsiaApiDelegate* fuchsia_api_delegate,
AssistantManagerServiceImpl* service,
const std::string& libassistant_config,
const std::string& locale,
const std::string& locale_override,
bool spoken_feedback_enabled,
const AssistantManagerController::AuthTokens& auth_tokens) {
result->display_connection = std::make_unique<CrosDisplayConnection>(
service, /*feedback_ui_enabled=*/true,
assistant::features::IsMediaSessionIntegrationEnabled());
result->assistant_manager =
delegate->CreateAssistantManager(platform_api, libassistant_config);
result->assistant_manager_internal =
delegate->UnwrapAssistantManagerInternal(result->assistant_manager.get());
UpdateInternalOptions(result->assistant_manager_internal, locale,
spoken_feedback_enabled);
result->assistant_manager_internal->SetDisplayConnection(
result->display_connection.get());
result->assistant_manager_internal->SetLocaleOverride(locale_override);
result->assistant_manager_internal->RegisterActionModule(action_module);
result->assistant_manager_internal->SetAssistantManagerDelegate(service);
result->assistant_manager_internal->GetFuchsiaApiHelperOrDie()
->SetFuchsiaApiDelegate(fuchsia_api_delegate);
result->assistant_manager->AddConversationStateListener(service);
result->assistant_manager->AddDeviceStateListener(service);
SetServerExperiments(result->assistant_manager_internal);
SetAuthTokens(result->assistant_manager.get(), auth_tokens);
result->assistant_manager->Start();
}
// Creates the Assistant on the given (background) thread, and passes it to
// the callback on the current thread.
void CreateAssistantOnBackgroundThread(
scoped_refptr<base::SequencedTaskRunner> task_runner,
AssistantManagerServiceDelegate* delegate,
assistant_client::PlatformApi* platform_api,
assistant_client::ActionModule* action_module,
assistant_client::FuchsiaApiDelegate* fuchsia_api_delegate,
AssistantManagerServiceImpl* service,
const std::string& libassistant_config,
const std::string& locale,
const std::string& locale_override,
bool spoken_feedback_enabled,
const AssistantManagerController::AuthTokens& auth_tokens,
DoneCallback done_callback) {
auto result = std::make_unique<AssistantObjects>();
auto* result_pointer = result.get();
task_runner->PostTaskAndReply(
FROM_HERE,
BindOnce(CreateAssistantOnCurrentThread, result_pointer, delegate,
platform_api, action_module, fuchsia_api_delegate, service,
libassistant_config, locale, locale_override,
spoken_feedback_enabled, auth_tokens),
BindOnce(
[](std::unique_ptr<AssistantObjects> result, DoneCallback callback) {
std::move(callback).Run(std::move(result->display_connection),
std::move(result->assistant_manager),
result->assistant_manager_internal);
},
std::move(result), std::move(done_callback)));
}
} // namespace
AssistantManagerController::AssistantManagerController()
: weak_factory_(this) {}
AssistantManagerController::~AssistantManagerController() = default;
void AssistantManagerController::Initialize(
AssistantManagerServiceImpl* service,
scoped_refptr<base::SingleThreadTaskRunner> background_task_runner,
AssistantManagerServiceDelegate* delegate,
assistant_client::PlatformApi* platform_api,
assistant_client::ActionModule* action_module,
assistant_client::FuchsiaApiDelegate* fuchsia_api_delegate,
const std::string& libassistant_config,
const std::string& locale,
const std::string& locale_override,
bool spoken_feedback_enabled,
const AuthTokens& auth_tokens,
base::OnceClosure done_callback) {
CreateAssistantOnBackgroundThread(
background_task_runner, delegate, platform_api, action_module,
fuchsia_api_delegate, service, libassistant_config, locale,
locale_override, spoken_feedback_enabled, auth_tokens,
base::BindOnce(&AssistantManagerController::OnAssistantCreated,
weak_factory_.GetWeakPtr(), std::move(done_callback)));
}
void AssistantManagerController::UpdateInternalOptions(
const std::string& locale,
bool spoken_feedback_enabled) {
chromeos::assistant::UpdateInternalOptions(assistant_manager_internal(),
locale, spoken_feedback_enabled);
}
void AssistantManagerController::SetAuthTokens(const AuthTokens& tokens) {
chromeos::assistant::SetAuthTokens(assistant_manager(), tokens);
}
bool AssistantManagerController::IsInitialized() const {
return (display_connection_ != nullptr) && (assistant_manager_ != nullptr) &&
(assistant_manager_internal_ != nullptr);
}
void AssistantManagerController::OnAssistantCreated(
base::OnceClosure done_callback,
std::unique_ptr<CrosDisplayConnection> display_connection,
std::unique_ptr<assistant_client::AssistantManager> assistant_manager,
assistant_client::AssistantManagerInternal* assistant_manager_internal) {
DCHECK(display_connection);
DCHECK(assistant_manager);
DCHECK(assistant_manager_internal);
display_connection_ = std::move(display_connection);
assistant_manager_ = std::move(assistant_manager);
assistant_manager_internal_ = assistant_manager_internal;
std::move(done_callback).Run();
}
} // namespace assistant
} // namespace chromeos
// Copyright 2020 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 CHROMEOS_SERVICES_ASSISTANT_ASSISTANT_MANAGER_CONTROLLER_H_
#define CHROMEOS_SERVICES_ASSISTANT_ASSISTANT_MANAGER_CONTROLLER_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/check.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
namespace assistant_client {
class PlatformApi;
class ActionModule;
class FuchsiaApiDelegate;
class AssistantManager;
class AssistantManagerInternal;
} // namespace assistant_client
namespace chromeos {
namespace assistant {
class AssistantManagerServiceDelegate;
class CrosDisplayConnection;
class AssistantManagerServiceImpl;
class AssistantManagerController {
public:
// Each authentication token exists of a [gaia_id, access_token] tuple.
using AuthTokens = std::vector<std::pair<std::string, std::string>>;
AssistantManagerController();
AssistantManagerController(AssistantManagerController&) = delete;
AssistantManagerController& operator=(AssistantManagerController&) = delete;
~AssistantManagerController();
// Can not be invoked before initialization has finished.
// Both LibAssistant and Chrome threads may access |display_connection|.
// |display_connection| is thread safe.
CrosDisplayConnection* display_connection() {
DCHECK(IsInitialized());
return display_connection_.get();
}
// Can not be invoked before initialization has finished.
assistant_client::AssistantManager* assistant_manager() {
DCHECK(IsInitialized());
return assistant_manager_.get();
}
// Can not be invoked before initialization has finished.
assistant_client::AssistantManagerInternal* assistant_manager_internal() {
DCHECK(IsInitialized());
return assistant_manager_internal_;
}
// Initialize the |AssistantManager| by creating the objects (on a background
// task) and by calling their Start() methods. Will signal the objects exist
// and can be accessed by calling the |done_callback|.
//
// If the |AssistantManagerController| is destroyed before Initialize()
// finishes, the created objects will safely be destructed.
// However, if any of the passed in objects (|service|, |delegate|,
// |platform_api| and so on) are destroyed, the caller *must* destroy
// |background_task_runner| first or invalid memory might be accessed.
// Also, if a new instance of |AssistantManagerController| is immediately
// created and initialized before the background thread has had any chance to
// run, it is theoretically possible for 2 instances of |AssistantManager|
// to exist at the same time. However, this is prevented by the logic in
// |service.cc|.
void Initialize(
AssistantManagerServiceImpl* service,
scoped_refptr<base::SingleThreadTaskRunner> background_task_runner,
AssistantManagerServiceDelegate* delegate,
assistant_client::PlatformApi* platform_api,
assistant_client::ActionModule* action_module,
assistant_client::FuchsiaApiDelegate* fuchsia_api_delegate,
const std::string& libassistant_config,
const std::string& locale,
const std::string& locale_override,
bool spoken_feedback_enabled,
const AuthTokens& auth_tokens,
base::OnceClosure done_callback);
// Whether Initialize() has been called and has finished.
// Until this is true trying to access any of the getters will fail.
bool IsInitialized() const;
void UpdateInternalOptions(const std::string& locale,
bool spoken_feedback_enabled);
// Passing in an empty vector will start Libassistant in signed-out mode.
void SetAuthTokens(const AuthTokens& tokens);
private:
void OnAssistantCreated(
base::OnceClosure done_callback,
std::unique_ptr<CrosDisplayConnection> display_connection,
std::unique_ptr<assistant_client::AssistantManager> assistant_manager,
assistant_client::AssistantManagerInternal* assistant_manager_internal);
// NOTE: |display_connection_| is used by |assistant_manager_| and must be
// declared before so it will be destructed after.
std::unique_ptr<CrosDisplayConnection> display_connection_;
std::unique_ptr<assistant_client::AssistantManager> assistant_manager_;
assistant_client::AssistantManagerInternal* assistant_manager_internal_ =
nullptr;
base::WeakPtrFactory<AssistantManagerController> weak_factory_;
};
} // namespace assistant
} // namespace chromeos
#endif // CHROMEOS_SERVICES_ASSISTANT_ASSISTANT_MANAGER_CONTROLLER_H_
......@@ -15,6 +15,7 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/callback_forward.h"
#include "base/check.h"
#include "base/feature_list.h"
#include "base/i18n/rtl.h"
#include "base/logging.h"
......@@ -31,6 +32,7 @@
#include "chromeos/constants/chromeos_switches.h"
#include "chromeos/dbus/util/version_loader.h"
#include "chromeos/services/assistant/assistant_device_settings_delegate.h"
#include "chromeos/services/assistant/assistant_manager_controller.h"
#include "chromeos/services/assistant/assistant_manager_service_delegate.h"
#include "chromeos/services/assistant/media_session/assistant_media_session.h"
#include "chromeos/services/assistant/platform_api_impl.h"
......@@ -81,13 +83,6 @@ static bool is_first_init = true;
constexpr char kIntentActionView[] = "android.intent.action.VIEW";
constexpr base::Feature kChromeOSAssistantDogfood{
"ChromeOSAssistantDogfood", base::FEATURE_DISABLED_BY_DEFAULT};
constexpr char kServersideDogfoodExperimentId[] = "20347368";
constexpr char kServersideOpenAppExperimentId[] = "39651593";
constexpr char kServersideResponseProcessingV2ExperimentId[] = "1793869";
constexpr char kNextTrackClientOp[] = "media.NEXT";
constexpr char kPauseTrackClientOp[] = "media.PAUSE";
constexpr char kPlayMediaClientOp[] = "media.PLAY_MEDIA";
......@@ -117,7 +112,7 @@ CommunicationErrorType CommunicationErrorTypeFromLibassistantErrorCode(
return CommunicationErrorType::Other;
}
std::vector<std::pair<std::string, std::string>> ToAuthTokensOrEmpty(
AssistantManagerController::AuthTokens ToAuthTokensOrEmpty(
const base::Optional<AssistantManagerService::UserInfo>& user) {
if (!user.has_value())
return {};
......@@ -127,27 +122,6 @@ std::vector<std::pair<std::string, std::string>> ToAuthTokensOrEmpty(
return {std::make_pair(user.value().gaia_id, user.value().access_token)};
}
void UpdateInternalOptions(
assistant_client::AssistantManagerInternal* assistant_manager_internal,
const std::string& locale,
bool spoken_feedback_enabled) {
// NOTE: this method is called on multiple threads, it needs to be
// thread-safe.
auto* internal_options =
assistant_manager_internal->CreateDefaultInternalOptions();
SetAssistantOptions(internal_options, locale, spoken_feedback_enabled);
internal_options->SetClientControlEnabled(
assistant::features::IsRoutinesEnabled());
if (!features::IsVoiceMatchDisabled())
internal_options->EnableRequireVoiceMatchVerification();
assistant_manager_internal->SetOptions(*internal_options, [](bool success) {
DVLOG(2) << "set options: " << success;
});
}
const char* ToTriggerSource(AssistantEntryPoint entry_point) {
switch (entry_point) {
case AssistantEntryPoint::kUnspecified:
......@@ -223,7 +197,7 @@ AssistantManagerServiceImpl::~AssistantManagerServiceImpl() {
void AssistantManagerServiceImpl::Start(const base::Optional<UserInfo>& user,
bool enable_hotword) {
DCHECK(!assistant_manager_);
DCHECK(!assistant_manager_controller());
DCHECK_EQ(GetState(), State::STOPPED);
// Set the flag to avoid starting the service multiple times.
......@@ -242,15 +216,7 @@ void AssistantManagerServiceImpl::Start(const base::Optional<UserInfo>& user,
ash::AmbientUiVisibility::kClosed);
}
// LibAssistant creation will make file IO and sync wait. Post the creation to
// background thread to avoid DCHECK.
background_thread_.task_runner()->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&AssistantManagerServiceImpl::StartAssistantInternal,
base::Unretained(this), user,
assistant_state()->locale().value()),
base::BindOnce(&AssistantManagerServiceImpl::PostInitAssistant,
weak_factory_.GetWeakPtr()));
InitAssistant(user, assistant_state()->locale().value());
}
void AssistantManagerServiceImpl::Stop() {
......@@ -260,14 +226,12 @@ void AssistantManagerServiceImpl::Stop() {
SetStateAndInformObservers(State::STOPPED);
// When user disables the feature, we also deletes all data.
if (!assistant_state()->settings_enabled().value() && assistant_manager_)
assistant_manager_->ResetAllDataAndShutdown();
if (!assistant_state()->settings_enabled().value() && assistant_manager())
assistant_manager()->ResetAllDataAndShutdown();
media_controller_observer_receiver_.reset();
assistant_manager_internal_ = nullptr;
assistant_manager_.reset(nullptr);
display_connection_.reset(nullptr);
assistant_manager_controller_.reset(nullptr);
}
AssistantManagerService::State AssistantManagerServiceImpl::GetState() const {
......@@ -276,11 +240,11 @@ AssistantManagerService::State AssistantManagerServiceImpl::GetState() const {
void AssistantManagerServiceImpl::SetUser(
const base::Optional<UserInfo>& user) {
if (!assistant_manager_)
if (!IsInitialized())
return;
VLOG(1) << "Set user information (Gaia ID and access token).";
assistant_manager_->SetAuthTokens(ToAuthTokensOrEmpty(user));
assistant_manager_controller()->SetAuthTokens(ToAuthTokensOrEmpty(user));
}
void AssistantManagerServiceImpl::EnableAmbientMode(bool enabled) {
......@@ -291,13 +255,13 @@ void AssistantManagerServiceImpl::EnableAmbientMode(bool enabled) {
void AssistantManagerServiceImpl::RegisterFallbackMediaHandler() {
// This is a callback from LibAssistant, it is async from LibAssistant thread.
// It is possible that when it reaches here, the assistant_manager_ has
// It is possible that when it reaches here, the assistant_manager has
// been stopped.
if (!assistant_manager_internal_)
if (!assistant_manager_internal())
return;
// Register handler for media actions.
assistant_manager_internal_->RegisterFallbackMediaHandler(
assistant_manager_internal()->RegisterFallbackMediaHandler(
[this](std::string action_name, std::string media_action_args_proto) {
if (action_name == kPlayMediaClientOp) {
OnPlayMedia(media_action_args_proto);
......@@ -308,7 +272,8 @@ void AssistantManagerServiceImpl::RegisterFallbackMediaHandler() {
}
void AssistantManagerServiceImpl::WaitUntilStartIsFinishedForTesting() {
// First we wait until |StartAssistantInternal| is finished.
// First we wait until the |AssistantManager| is created on the background
// thread.
background_thread_.FlushForTesting();
// Then we wait until |PostInitAssistant| finishes.
// (which runs on the main thread).
......@@ -337,11 +302,11 @@ void AssistantManagerServiceImpl::RemoveMediaControllerObserver() {
}
void AssistantManagerServiceImpl::RegisterAlarmsTimersListener() {
if (!assistant_manager_internal_)
if (!assistant_manager_internal())
return;
auto* alarm_timer_manager =
assistant_manager_internal_->GetAlarmTimerManager();
assistant_manager_internal()->GetAlarmTimerManager();
// Can be nullptr during unittests.
if (!alarm_timer_manager)
......@@ -376,9 +341,9 @@ void AssistantManagerServiceImpl::RegisterAlarmsTimersListener() {
}
void AssistantManagerServiceImpl::EnableListening(bool enable) {
if (!assistant_manager_)
if (!assistant_manager())
return;
assistant_manager_->EnableListening(enable);
assistant_manager()->EnableListening(enable);
}
void AssistantManagerServiceImpl::EnableHotword(bool enable) {
......@@ -387,10 +352,8 @@ void AssistantManagerServiceImpl::EnableHotword(bool enable) {
void AssistantManagerServiceImpl::SetArcPlayStoreEnabled(bool enable) {
DCHECK(GetState() == State::RUNNING);
// Both LibAssistant and Chrome threads may access |display_connection_|.
// |display_connection_| is thread safe.
if (assistant::features::IsAppSupportEnabled())
display_connection_->SetArcPlayStoreEnabled(enable);
display_connection()->SetArcPlayStoreEnabled(enable);
}
void AssistantManagerServiceImpl::SetAssistantContextEnabled(bool enable) {
......@@ -403,9 +366,7 @@ void AssistantManagerServiceImpl::SetAssistantContextEnabled(bool enable) {
ResetMediaState();
}
// Both LibAssistant and Chrome threads may access |display_connection_|.
// |display_connection_| is thread safe.
display_connection_->SetAssistantContextEnabled(enable);
display_connection()->SetAssistantContextEnabled(enable);
}
AssistantSettings* AssistantManagerServiceImpl::GetAssistantSettings() {
......@@ -441,9 +402,9 @@ void AssistantManagerServiceImpl::SyncDeviceAppsStatus() {
void AssistantManagerServiceImpl::UpdateInternalMediaPlayerStatus(
MediaSessionAction action) {
if (!assistant_manager_)
if (!assistant_manager())
return;
auto* media_manager = assistant_manager_->GetMediaManager();
auto* media_manager = assistant_manager()->GetMediaManager();
if (!media_manager)
return;
......@@ -471,11 +432,11 @@ void AssistantManagerServiceImpl::UpdateInternalMediaPlayerStatus(
}
void AssistantManagerServiceImpl::StartVoiceInteraction() {
DCHECK(assistant_manager_);
DCHECK(assistant_manager());
DVLOG(1) << __func__;
platform_api_->SetMicState(true);
assistant_manager_->StartAssistantInteraction();
assistant_manager()->StartAssistantInteraction();
}
void AssistantManagerServiceImpl::StopActiveInteraction(
......@@ -483,11 +444,11 @@ void AssistantManagerServiceImpl::StopActiveInteraction(
DVLOG(1) << __func__;
platform_api_->SetMicState(false);
if (!assistant_manager_internal_) {
if (!assistant_manager_internal()) {
VLOG(1) << "Stopping interaction without assistant manager.";
return;
}
assistant_manager_internal_->StopAssistantInteractionInternal(
assistant_manager_internal()->StopAssistantInteractionInternal(
cancel_conversation);
}
......@@ -521,7 +482,7 @@ void AssistantManagerServiceImpl::StartScreenContextInteraction(
// Note: the value of |is_first_query| for screen context query is a no-op.
context_protos.emplace_back(CreateContextProto(assistant_screenshot,
/*is_first_query=*/true));
assistant_manager_internal_->SendScreenContextRequest(context_protos);
assistant_manager_internal()->SendScreenContextRequest(context_protos);
}
void AssistantManagerServiceImpl::StartTextInteraction(
......@@ -545,7 +506,7 @@ void AssistantManagerServiceImpl::StartTextInteraction(
NewPendingInteraction(AssistantInteractionType::kText, source, query);
std::string interaction = CreateTextQueryInteraction(query);
assistant_manager_internal_->SendVoicelessInteraction(
assistant_manager_internal()->SendVoicelessInteraction(
interaction, /*description=*/"text_query", options, [](auto) {});
}
......@@ -577,9 +538,9 @@ void AssistantManagerServiceImpl::RetrieveNotification(
void AssistantManagerServiceImpl::DismissNotification(
const AssistantNotification& notification) {
// |assistant_manager_internal_| may not exist if we are dismissing
// |assistant_manager_internal()| may not exist if we are dismissing
// notifications as part of a shutdown sequence.
if (!assistant_manager_internal_)
if (!assistant_manager_internal())
return;
const std::string& notification_id = notification.server_id;
......@@ -594,7 +555,7 @@ void AssistantManagerServiceImpl::DismissNotification(
assistant_client::VoicelessOptions options;
options.obfuscated_gaia_id = notification.obfuscated_gaia_id;
assistant_manager_internal_->SendVoicelessInteraction(
assistant_manager_internal()->SendVoicelessInteraction(
dismissed_interaction, /*description=*/"DismissNotification", options,
[](auto) {});
}
......@@ -820,7 +781,7 @@ void AssistantManagerServiceImpl::OnOpenAndroidApp(
assistant_client::VoicelessOptions options;
options.obfuscated_gaia_id = interaction.user_id;
assistant_manager_internal_->SendVoicelessInteraction(
assistant_manager_internal()->SendVoicelessInteraction(
interaction_proto, /*description=*/"open_provider_response", options,
[](auto) {});
}
......@@ -846,7 +807,7 @@ void AssistantManagerServiceImpl::OnVerifyAndroidApp(
// created to handle the client OPs in the response of this request.
options.is_user_initiated = true;
assistant_manager_internal_->SendVoicelessInteraction(
assistant_manager_internal()->SendVoicelessInteraction(
interaction_proto, /*description=*/"verify_provider_response", options,
[](auto) {});
}
......@@ -1017,73 +978,28 @@ void AssistantManagerServiceImpl::OnCommunicationError(int error_code) {
observer.OnCommunicationError(type);
}
void AssistantManagerServiceImpl::StartAssistantInternal(
void AssistantManagerServiceImpl::InitAssistant(
const base::Optional<UserInfo>& user,
const std::string& locale) {
DCHECK(background_thread_.task_runner()->BelongsToCurrentThread());
// NOTE: as the above showed, this is running in a different thread, we can
// only access |new_xxx| members here.
base::AutoLock lock(new_assistant_manager_lock_);
// There can only be one |AssistantManager| instance at any given time.
DCHECK(!assistant_manager_);
new_display_connection_ = std::make_unique<CrosDisplayConnection>(
this, /*feedback_ui_enabled=*/true,
assistant::features::IsMediaSessionIntegrationEnabled());
new_assistant_manager_ = delegate_->CreateAssistantManager(
platform_api_.get(), libassistant_config_);
new_assistant_manager_internal_ =
delegate_->UnwrapAssistantManagerInternal(new_assistant_manager_.get());
UpdateInternalOptions(new_assistant_manager_internal_, locale,
spoken_feedback_enabled_);
new_assistant_manager_internal_->SetLocaleOverride(
GetLocaleOrDefault(assistant_state()->locale().value()));
new_assistant_manager_internal_->SetDisplayConnection(
new_display_connection_.get());
new_assistant_manager_internal_->RegisterActionModule(action_module_.get());
new_assistant_manager_internal_->SetAssistantManagerDelegate(this);
new_assistant_manager_internal_->GetFuchsiaApiHelperOrDie()
->SetFuchsiaApiDelegate(&chromium_api_delegate_);
new_assistant_manager_->AddConversationStateListener(this);
new_assistant_manager_->AddDeviceStateListener(this);
std::vector<std::string> server_experiment_ids;
FillServerExperimentIds(&server_experiment_ids);
if (server_experiment_ids.size() > 0) {
new_assistant_manager_internal_->AddExtraExperimentIds(
server_experiment_ids);
}
DCHECK(!IsInitialized());
// When |access_token| does not contain a value, we will start Libassistant
// in signed-out mode by calling SetAuthTokens() with an empty vector.
new_assistant_manager_->SetAuthTokens(ToAuthTokensOrEmpty(user));
new_assistant_manager_->Start();
assistant_manager_controller_ =
std::make_unique<AssistantManagerController>();
assistant_manager_controller_->Initialize(
this, background_thread_.task_runner(), delegate_.get(), platform_api(),
action_module_.get(), &chromium_api_delegate_, libassistant_config_,
locale, GetLocaleOrDefault(assistant_state()->locale().value()),
spoken_feedback_enabled_, ToAuthTokensOrEmpty(user),
base::BindOnce(&AssistantManagerServiceImpl::PostInitAssistant,
weak_factory_.GetWeakPtr()));
}
void AssistantManagerServiceImpl::PostInitAssistant() {
DCHECK(main_task_runner()->RunsTasksInCurrentSequence());
DCHECK_EQ(GetState(), State::STARTING);
{
base::AutoLock lock(new_assistant_manager_lock_);
// It is possible that multiple |StartAssistantInternal| finished on
// background thread, before any of the matching |PostInitAssistant| had
// run. Because we only hold the last created instance in
// |new_assistant_manager_|, it is possible that |new_assistant_manager_| be
// null if we moved it in previous |PostInitAssistant| runs.
if (!new_assistant_manager_) {
return;
}
display_connection_ = std::move(new_display_connection_);
assistant_manager_ = std::move(new_assistant_manager_);
assistant_manager_internal_ = new_assistant_manager_internal_;
new_assistant_manager_internal_ = nullptr;
}
DCHECK(IsInitialized());
const base::TimeDelta time_since_started =
base::TimeTicks::Now() - started_time_;
......@@ -1099,6 +1015,11 @@ void AssistantManagerServiceImpl::PostInitAssistant() {
}
}
bool AssistantManagerServiceImpl::IsInitialized() const {
return assistant_manager_controller_ &&
assistant_manager_controller_->IsInitialized();
}
void AssistantManagerServiceImpl::HandleLaunchMediaIntentResponse(
bool app_opened) {
// TODO(llin): Handle the response.
......@@ -1110,10 +1031,10 @@ void AssistantManagerServiceImpl::HandleLaunchMediaIntentResponse(
void AssistantManagerServiceImpl::OnStartFinished() {
ENSURE_MAIN_THREAD(&AssistantManagerServiceImpl::OnStartFinished);
// It is possible the |assistant_manager_| was destructed before the
// It is possible the |assistant_manager()| was destructed before the
// rescheduled main thread task got a chance to run. We check this and also
// try to avoid double run by checking |GetState()|.
if (!assistant_manager_ || (GetState() == State::RUNNING))
if (!assistant_manager() || (GetState() == State::RUNNING))
return;
SetStateAndInformObservers(State::RUNNING);
......@@ -1135,7 +1056,7 @@ void AssistantManagerServiceImpl::OnStartFinished() {
SetAssistantContextEnabled(assistant_state()->IsScreenContextAllowed());
auto* media_manager = assistant_manager_->GetMediaManager();
auto* media_manager = assistant_manager()->GetMediaManager();
if (media_manager)
media_manager->AddListener(this);
......@@ -1155,7 +1076,7 @@ void AssistantManagerServiceImpl::OnAndroidAppListRefreshed(
filtered_apps_info.emplace_back(app_info);
}
display_connection_->OnAndroidAppListRefreshed(filtered_apps_info);
display_connection()->OnAndroidAppListRefreshed(filtered_apps_info);
}
void AssistantManagerServiceImpl::OnPlaybackStateChange(
......@@ -1185,17 +1106,17 @@ void AssistantManagerServiceImpl::MediaSessionChanged(
void AssistantManagerServiceImpl::OnAlarmTimerStateChanged() {
ENSURE_MAIN_THREAD(&AssistantManagerServiceImpl::OnAlarmTimerStateChanged);
// |assistant_manager_internal_| may not exist if we are receiving this event
// |assistant_manager_internal()| may not exist if we are receiving this event
// as part of a shutdown sequence. When this occurs, we notify our alarm/timer
// controller to clear its cache to remain in sync with LibAssistant.
if (!assistant_manager_internal_) {
if (!assistant_manager_internal()) {
assistant_alarm_timer_controller()->OnTimerStateChanged({});
return;
}
std::vector<ash::AssistantTimerPtr> timers;
auto* manager = assistant_manager_internal_->GetAlarmTimerManager();
auto* manager = assistant_manager_internal()->GetAlarmTimerManager();
for (const auto& event : manager->GetAllEvents()) {
// Note that we currently only handle timers, alarms are unsupported.
if (event.type != assistant_client::AlarmTimerEvent::TIMER)
......@@ -1242,10 +1163,9 @@ void AssistantManagerServiceImpl::OnAccessibilityStatusChanged(
// When |spoken_feedback_enabled_| changes we need to update our internal
// options to turn on/off A11Y features in LibAssistant.
if (assistant_manager_internal_) {
UpdateInternalOptions(assistant_manager_internal_,
assistant_state()->locale().value(),
spoken_feedback_enabled_);
if (assistant_manager_controller()) {
assistant_manager_controller()->UpdateInternalOptions(
assistant_state()->locale().value(), spoken_feedback_enabled_);
}
}
......@@ -1255,33 +1175,33 @@ void AssistantManagerServiceImpl::OnDeviceAppsEnabled(bool enabled) {
if (GetState() != State::RUNNING)
return;
display_connection_->SetDeviceAppsEnabled(enabled);
display_connection()->SetDeviceAppsEnabled(enabled);
action_module_->SetAppSupportEnabled(
assistant::features::IsAppSupportEnabled() && enabled);
}
void AssistantManagerServiceImpl::AddTimeToTimer(const std::string& id,
base::TimeDelta duration) {
if (!assistant_manager_internal_)
if (!assistant_manager_internal())
return;
assistant_manager_internal_->GetAlarmTimerManager()->AddTimeToTimer(
assistant_manager_internal()->GetAlarmTimerManager()->AddTimeToTimer(
id, duration.InSeconds());
}
void AssistantManagerServiceImpl::PauseTimer(const std::string& id) {
if (assistant_manager_internal_)
assistant_manager_internal_->GetAlarmTimerManager()->PauseTimer(id);
if (assistant_manager_internal())
assistant_manager_internal()->GetAlarmTimerManager()->PauseTimer(id);
}
void AssistantManagerServiceImpl::RemoveAlarmOrTimer(const std::string& id) {
if (assistant_manager_internal_)
assistant_manager_internal_->GetAlarmTimerManager()->RemoveEvent(id);
if (assistant_manager_internal())
assistant_manager_internal()->GetAlarmTimerManager()->RemoveEvent(id);
}
void AssistantManagerServiceImpl::ResumeTimer(const std::string& id) {
if (assistant_manager_internal_)
assistant_manager_internal_->GetAlarmTimerManager()->ResumeTimer(id);
if (assistant_manager_internal())
assistant_manager_internal()->GetAlarmTimerManager()->ResumeTimer(id);
}
void AssistantManagerServiceImpl::NotifyEntryIntoAssistantUi(
......@@ -1305,7 +1225,7 @@ void AssistantManagerServiceImpl::SendVoicelessInteraction(
voiceless_options.is_user_initiated = is_user_initiated;
assistant_manager_internal_->SendVoicelessInteraction(
assistant_manager_internal()->SendVoicelessInteraction(
interaction, description, voiceless_options, [](auto) {});
}
......@@ -1313,21 +1233,6 @@ std::string AssistantManagerServiceImpl::GetLastSearchSource() {
return ConsumeLastTriggerSource();
}
void AssistantManagerServiceImpl::FillServerExperimentIds(
std::vector<std::string>* server_experiment_ids) {
if (base::FeatureList::IsEnabled(kChromeOSAssistantDogfood)) {
server_experiment_ids->emplace_back(kServersideDogfoodExperimentId);
}
if (base::FeatureList::IsEnabled(features::kAssistantAppSupport))
server_experiment_ids->emplace_back(kServersideOpenAppExperimentId);
if (features::IsResponseProcessingV2Enabled()) {
server_experiment_ids->emplace_back(
kServersideResponseProcessingV2ExperimentId);
}
}
void AssistantManagerServiceImpl::RecordQueryResponseTypeUMA() {
auto response_type = AssistantQueryResponseType::kUnspecified;
......@@ -1414,13 +1319,13 @@ void AssistantManagerServiceImpl::UpdateMediaState() {
}
}
auto* media_manager = assistant_manager_->GetMediaManager();
auto* media_manager = assistant_manager()->GetMediaManager();
if (media_manager)
media_manager->SetExternalPlaybackState(media_status);
}
void AssistantManagerServiceImpl::ResetMediaState() {
auto* media_manager = assistant_manager_->GetMediaManager();
auto* media_manager = assistant_manager()->GetMediaManager();
if (media_manager) {
MediaStatus media_status;
media_manager->SetExternalPlaybackState(media_status);
......@@ -1466,6 +1371,30 @@ AssistantManagerServiceImpl::main_task_runner() {
return context_->main_task_runner();
}
CrosDisplayConnection* AssistantManagerServiceImpl::display_connection() {
DCHECK(assistant_manager_controller());
return assistant_manager_controller()->display_connection();
}
assistant_client::AssistantManager*
AssistantManagerServiceImpl::assistant_manager() {
if (!assistant_manager_controller_)
return nullptr;
return assistant_manager_controller_->assistant_manager();
}
assistant_client::AssistantManagerInternal*
AssistantManagerServiceImpl::assistant_manager_internal() {
if (!assistant_manager_controller_)
return nullptr;
return assistant_manager_controller_->assistant_manager_internal();
}
AssistantManagerController*
AssistantManagerServiceImpl::assistant_manager_controller() {
return assistant_manager_controller_.get();
}
void AssistantManagerServiceImpl::SetStateAndInformObservers(State new_state) {
state_ = new_state;
......
......@@ -58,10 +58,11 @@ namespace chromeos {
namespace assistant {
class AssistantMediaSession;
class AssistantDeviceSettingsDelegate;
class AssistantManagerController;
class AssistantManagerServiceDelegate;
class CrosPlatformApi;
class ServiceContext;
class AssistantManagerServiceDelegate;
class AssistantDeviceSettingsDelegate;
// Enumeration of Assistant query response type, also recorded in histograms.
// These values are persisted to logs. Entries should not be renumbered and
......@@ -211,12 +212,8 @@ class COMPONENT_EXPORT(ASSISTANT_SERVICE) AssistantManagerServiceImpl
void OnAndroidAppListRefreshed(
const std::vector<AndroidAppInfo>& apps_info) override;
assistant_client::AssistantManager* assistant_manager() {
return assistant_manager_.get();
}
assistant_client::AssistantManagerInternal* assistant_manager_internal() {
return assistant_manager_internal_;
}
assistant_client::AssistantManager* assistant_manager();
assistant_client::AssistantManagerInternal* assistant_manager_internal();
CrosPlatformApi* platform_api() { return platform_api_.get(); }
// assistant_client::MediaManager::Listener overrides:
......@@ -246,9 +243,10 @@ class COMPONENT_EXPORT(ASSISTANT_SERVICE) AssistantManagerServiceImpl
}
private:
void StartAssistantInternal(const base::Optional<UserInfo>& user,
void InitAssistant(const base::Optional<UserInfo>& user,
const std::string& locale);
void PostInitAssistant();
bool IsInitialized() const;
// Update device id, type and locale
void UpdateDeviceSettings();
......@@ -304,6 +302,9 @@ class COMPONENT_EXPORT(ASSISTANT_SERVICE) AssistantManagerServiceImpl
DeviceActions* device_actions();
scoped_refptr<base::SequencedTaskRunner> main_task_runner();
CrosDisplayConnection* display_connection();
AssistantManagerController* assistant_manager_controller();
void SetStateAndInformObservers(State new_state);
State state_ = State::STOPPED;
......@@ -311,25 +312,10 @@ class COMPONENT_EXPORT(ASSISTANT_SERVICE) AssistantManagerServiceImpl
std::unique_ptr<CrosPlatformApi> platform_api_;
std::unique_ptr<action::CrosActionModule> action_module_;
ChromiumApiDelegate chromium_api_delegate_;
// NOTE: |display_connection_| is used by |assistant_manager_| and must be
// declared before so it will be destructed after.
std::unique_ptr<CrosDisplayConnection> display_connection_;
// Similar to |new_asssistant_manager_|, created on |background_thread_| then
// posted to main thread to finish initialization then move to
// |display_connection_|.
std::unique_ptr<CrosDisplayConnection> new_display_connection_;
std::unique_ptr<assistant_client::AssistantManager> assistant_manager_;
std::unique_ptr<AssistantSettingsImpl> assistant_settings_;
// |new_assistant_manager_| is created on |background_thread_| then posted to
// main thread to finish initialization then move to |assistant_manager_|.
std::unique_ptr<assistant_client::AssistantManager> new_assistant_manager_;
// Same ownership as |new_assistant_manager_|.
assistant_client::AssistantManagerInternal* new_assistant_manager_internal_ =
nullptr;
base::Lock new_assistant_manager_lock_;
// same ownership as |assistant_manager_|.
assistant_client::AssistantManagerInternal* assistant_manager_internal_ =
nullptr;
std::unique_ptr<AssistantManagerController> assistant_manager_controller_;
base::ObserverList<AssistantInteractionSubscriber> interaction_subscribers_;
mojo::Remote<media_session::mojom::MediaController> media_controller_;
......
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