1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chromeos/services/assistant/service.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <utility>
10
11 #include "ash/public/cpp/ambient/ambient_ui_model.h"
12 #include "ash/public/cpp/assistant/assistant_state.h"
13 #include "ash/public/cpp/assistant/controller/assistant_alarm_timer_controller.h"
14 #include "ash/public/cpp/assistant/controller/assistant_controller.h"
15 #include "ash/public/cpp/assistant/controller/assistant_notification_controller.h"
16 #include "ash/public/cpp/session/session_controller.h"
17 #include "base/bind.h"
18 #include "base/command_line.h"
19 #include "base/logging.h"
20 #include "base/optional.h"
21 #include "base/rand_util.h"
22 #include "base/single_thread_task_runner.h"
23 #include "base/time/time.h"
24 #include "base/timer/timer.h"
25 #include "build/buildflag.h"
26 #include "chromeos/assistant/buildflags.h"
27 #include "chromeos/audio/cras_audio_handler.h"
28 #include "chromeos/constants/chromeos_features.h"
29 #include "chromeos/constants/chromeos_switches.h"
30 #include "chromeos/dbus/dbus_thread_manager.h"
31 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
32 #include "chromeos/services/assistant/assistant_interaction_logger.h"
33 #include "chromeos/services/assistant/assistant_manager_service.h"
34 #include "chromeos/services/assistant/assistant_manager_service_delegate_impl.h"
35 #include "chromeos/services/assistant/fake_assistant_manager_service_impl.h"
36 #include "chromeos/services/assistant/fake_assistant_settings_impl.h"
37 #include "chromeos/services/assistant/public/cpp/assistant_client.h"
38 #include "chromeos/services/assistant/public/cpp/assistant_prefs.h"
39 #include "chromeos/services/assistant/public/cpp/device_actions.h"
40 #include "chromeos/services/assistant/public/cpp/features.h"
41 #include "chromeos/services/assistant/service_context.h"
42 #include "components/signin/public/identity_manager/access_token_fetcher.h"
43 #include "components/signin/public/identity_manager/access_token_info.h"
44 #include "components/signin/public/identity_manager/consent_level.h"
45 #include "components/signin/public/identity_manager/identity_manager.h"
46 #include "components/signin/public/identity_manager/scope_set.h"
47 #include "components/user_manager/known_user.h"
48 #include "google_apis/gaia/google_service_auth_error.h"
49 #include "services/network/public/cpp/shared_url_loader_factory.h"
50
51 #if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
52 #include "chromeos/assistant/internal/internal_constants.h"
53 #include "chromeos/services/assistant/assistant_manager_service_impl.h"
54 #include "chromeos/services/assistant/assistant_settings_impl.h"
55 #include "chromeos/services/assistant/utils.h"
56 #include "services/device/public/mojom/battery_monitor.mojom.h"
57 #endif
58
59 namespace chromeos {
60 namespace assistant {
61
62 namespace {
63
64 using chromeos::assistant::features::IsAmbientAssistantEnabled;
65 using CommunicationErrorType = AssistantManagerService::CommunicationErrorType;
66
67 constexpr char kScopeAuthGcm[] = "https://www.googleapis.com/auth/gcm";
68 constexpr char kScopeAssistant[] =
69 "https://www.googleapis.com/auth/assistant-sdk-prototype";
70 constexpr char kScopeGeller[] = "https://www.googleapis.com/auth/webhistory";
71
72 constexpr base::TimeDelta kMinTokenRefreshDelay =
73 base::TimeDelta::FromMilliseconds(1000);
74 constexpr base::TimeDelta kMaxTokenRefreshDelay =
75 base::TimeDelta::FromMilliseconds(60 * 1000);
76
77 // Testing override for the URI used to contact the s3 server.
78 const char* g_s3_server_uri_override = nullptr;
79 // Testing override for the device-id used by Libassistant to identify this
80 // device.
81 const char* g_device_id_override = nullptr;
82
ToAssistantStatus(AssistantManagerService::State state)83 AssistantStatus ToAssistantStatus(AssistantManagerService::State state) {
84 using State = AssistantManagerService::State;
85
86 switch (state) {
87 case State::STOPPED:
88 case State::STARTING:
89 case State::STARTED:
90 return AssistantStatus::NOT_READY;
91 case State::RUNNING:
92 return AssistantStatus::READY;
93 }
94 }
95
96 #if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
GetS3ServerUriOverride()97 base::Optional<std::string> GetS3ServerUriOverride() {
98 if (g_s3_server_uri_override)
99 return g_s3_server_uri_override;
100 return base::nullopt;
101 }
102
GetDeviceIdOverride()103 base::Optional<std::string> GetDeviceIdOverride() {
104 if (g_device_id_override)
105 return g_device_id_override;
106 return base::nullopt;
107 }
108 #endif
109
110 // Returns true if the system is currently in Ambient Mode (with ambient screen
111 // shown or hidden, but not closed).
InAmbientMode()112 bool InAmbientMode() {
113 DCHECK(chromeos::features::IsAmbientModeEnabled());
114 return ash::AmbientUiModel::Get()->ui_visibility() !=
115 ash::AmbientUiVisibility::kClosed;
116 }
117
118 // In the signed-out mode, we are going to run Assistant service without
119 // using user's signed in account information.
IsSignedOutMode()120 bool IsSignedOutMode() {
121 // We will switch the Libassitsant mode to signed-out/signed-in when user
122 // enters/exits the ambient mode.
123 const bool entered_ambient_mode =
124 IsAmbientAssistantEnabled() && InAmbientMode();
125
126 // Note that we shouldn't toggle the flag to true when exiting ambient
127 // mode if we have been using fake gaia login, e.g. in the Tast test.
128 return entered_ambient_mode ||
129 base::CommandLine::ForCurrentProcess()->HasSwitch(
130 chromeos::switches::kDisableGaiaServices);
131 }
132
133 } // namespace
134
135 // Scoped observer that will subscribe |Service| as an Ash session observer,
136 // and will unsubscribe in its destructor.
137 class ScopedAshSessionObserver {
138 public:
ScopedAshSessionObserver(ash::SessionActivationObserver * observer,const AccountId & account_id)139 ScopedAshSessionObserver(ash::SessionActivationObserver* observer,
140 const AccountId& account_id)
141 : observer_(observer), account_id_(account_id) {
142 DCHECK(account_id_.is_valid());
143 DCHECK(controller());
144 controller()->AddSessionActivationObserverForAccountId(account_id_,
145 observer_);
146 }
147
~ScopedAshSessionObserver()148 ~ScopedAshSessionObserver() {
149 if (controller())
150 controller()->RemoveSessionActivationObserverForAccountId(account_id_,
151 observer_);
152 }
153
154 private:
controller() const155 ash::SessionController* controller() const {
156 return ash::SessionController::Get();
157 }
158
159 ash::SessionActivationObserver* const observer_;
160 const AccountId account_id_;
161 };
162
163 class Service::Context : public ServiceContext {
164 public:
Context(Service * parent)165 explicit Context(Service* parent) : parent_(parent) {}
166 ~Context() override = default;
167
168 // ServiceContext:
assistant_alarm_timer_controller()169 ash::AssistantAlarmTimerController* assistant_alarm_timer_controller()
170 override {
171 return ash::AssistantAlarmTimerController::Get();
172 }
173
assistant_controller()174 ash::AssistantController* assistant_controller() override {
175 return ash::AssistantController::Get();
176 }
177
assistant_notification_controller()178 ash::AssistantNotificationController* assistant_notification_controller()
179 override {
180 return ash::AssistantNotificationController::Get();
181 }
182
assistant_screen_context_controller()183 ash::AssistantScreenContextController* assistant_screen_context_controller()
184 override {
185 return ash::AssistantScreenContextController::Get();
186 }
187
assistant_state()188 ash::AssistantStateBase* assistant_state() override {
189 return ash::AssistantState::Get();
190 }
191
cras_audio_handler()192 CrasAudioHandler* cras_audio_handler() override {
193 return CrasAudioHandler::Get();
194 }
195
device_actions()196 DeviceActions* device_actions() override { return DeviceActions::Get(); }
197
main_task_runner()198 scoped_refptr<base::SequencedTaskRunner> main_task_runner() override {
199 return parent_->main_task_runner_;
200 }
201
power_manager_client()202 PowerManagerClient* power_manager_client() override {
203 return PowerManagerClient::Get();
204 }
205
primary_account_gaia_id()206 std::string primary_account_gaia_id() override {
207 return parent_->RetrievePrimaryAccountInfo().gaia;
208 }
209
210 private:
211 Service* const parent_; // |this| is owned by |parent_|.
212
213 DISALLOW_COPY_AND_ASSIGN(Context);
214 };
215
Service(std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_url_loader_factory,signin::IdentityManager * identity_manager)216 Service::Service(std::unique_ptr<network::PendingSharedURLLoaderFactory>
217 pending_url_loader_factory,
218 signin::IdentityManager* identity_manager)
219 : identity_manager_(identity_manager),
220 token_refresh_timer_(std::make_unique<base::OneShotTimer>()),
221 main_task_runner_(base::SequencedTaskRunnerHandle::Get()),
222 context_(std::make_unique<Context>(this)),
223 pending_url_loader_factory_(std::move(pending_url_loader_factory)) {
224 DCHECK(identity_manager_);
225 chromeos::PowerManagerClient* power_manager_client =
226 context_->power_manager_client();
227 power_manager_observer_.Add(power_manager_client);
228 power_manager_client->RequestStatusUpdate();
229 }
230
~Service()231 Service::~Service() {
232 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
233 ash::AssistantState::Get()->RemoveObserver(this);
234 ash::AssistantController::Get()->SetAssistant(nullptr);
235 }
236
237 // static
OverrideS3ServerUriForTesting(const char * uri)238 void Service::OverrideS3ServerUriForTesting(const char* uri) {
239 g_s3_server_uri_override = uri;
240 }
241
242 // static
OverrideDeviceIdForTesting(const char * device_id)243 void Service::OverrideDeviceIdForTesting(const char* device_id) {
244 g_device_id_override = device_id;
245 }
246
SetAssistantManagerServiceForTesting(std::unique_ptr<AssistantManagerService> assistant_manager_service)247 void Service::SetAssistantManagerServiceForTesting(
248 std::unique_ptr<AssistantManagerService> assistant_manager_service) {
249 DCHECK(assistant_manager_service_ == nullptr);
250 assistant_manager_service_for_testing_ = std::move(assistant_manager_service);
251 }
252
Init()253 void Service::Init() {
254 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
255
256 ash::AssistantState::Get()->AddObserver(this);
257
258 if (IsAmbientAssistantEnabled())
259 ambient_ui_model_observer_.Add(ash::AmbientUiModel::Get());
260
261 DCHECK(!assistant_manager_service_);
262
263 RequestAccessToken();
264 }
265
Shutdown()266 void Service::Shutdown() {
267 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
268
269 if (assistant_manager_service_)
270 StopAssistantManagerService();
271 }
272
GetAssistant()273 Assistant* Service::GetAssistant() {
274 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
275 DCHECK(assistant_manager_service_);
276 return assistant_manager_service_.get();
277 }
278
PowerChanged(const power_manager::PowerSupplyProperties & prop)279 void Service::PowerChanged(const power_manager::PowerSupplyProperties& prop) {
280 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
281 const bool power_source_connected =
282 prop.external_power() == power_manager::PowerSupplyProperties::AC;
283 if (power_source_connected == power_source_connected_)
284 return;
285
286 power_source_connected_ = power_source_connected;
287 UpdateAssistantManagerState();
288 }
289
SuspendDone(const base::TimeDelta & sleep_duration)290 void Service::SuspendDone(const base::TimeDelta& sleep_duration) {
291 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
292 // |token_refresh_timer_| may become stale during sleeping, so we immediately
293 // request a new token to make sure it is fresh.
294 if (token_refresh_timer_->IsRunning()) {
295 token_refresh_timer_->AbandonAndStop();
296 RequestAccessToken();
297 }
298 }
299
OnSessionActivated(bool activated)300 void Service::OnSessionActivated(bool activated) {
301 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
302 session_active_ = activated;
303
304 AssistantClient::Get()->OnAssistantStatusChanged(
305 ToAssistantStatus(assistant_manager_service_->GetState()));
306 UpdateListeningState();
307 }
308
OnLockStateChanged(bool locked)309 void Service::OnLockStateChanged(bool locked) {
310 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
311 locked_ = locked;
312 UpdateListeningState();
313 }
314
OnAssistantConsentStatusChanged(int consent_status)315 void Service::OnAssistantConsentStatusChanged(int consent_status) {
316 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
317
318 // Notify device apps status when user accepts activity control.
319 if (assistant_manager_service_ &&
320 assistant_manager_service_->GetState() ==
321 AssistantManagerService::State::RUNNING) {
322 assistant_manager_service_->SyncDeviceAppsStatus();
323 }
324 }
325
OnAssistantContextEnabled(bool enabled)326 void Service::OnAssistantContextEnabled(bool enabled) {
327 UpdateAssistantManagerState();
328 }
329
OnAssistantHotwordAlwaysOn(bool hotword_always_on)330 void Service::OnAssistantHotwordAlwaysOn(bool hotword_always_on) {
331 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
332 // No need to update hotword status if power source is connected.
333 if (power_source_connected_)
334 return;
335
336 UpdateAssistantManagerState();
337 }
338
OnAssistantSettingsEnabled(bool enabled)339 void Service::OnAssistantSettingsEnabled(bool enabled) {
340 UpdateAssistantManagerState();
341 }
342
OnAssistantHotwordEnabled(bool enabled)343 void Service::OnAssistantHotwordEnabled(bool enabled) {
344 UpdateAssistantManagerState();
345 }
346
OnLocaleChanged(const std::string & locale)347 void Service::OnLocaleChanged(const std::string& locale) {
348 UpdateAssistantManagerState();
349 }
350
OnArcPlayStoreEnabledChanged(bool enabled)351 void Service::OnArcPlayStoreEnabledChanged(bool enabled) {
352 UpdateAssistantManagerState();
353 }
354
OnLockedFullScreenStateChanged(bool enabled)355 void Service::OnLockedFullScreenStateChanged(bool enabled) {
356 UpdateListeningState();
357 }
358
OnCommunicationError(CommunicationErrorType error_type)359 void Service::OnCommunicationError(CommunicationErrorType error_type) {
360 if (error_type == CommunicationErrorType::AuthenticationError)
361 RequestAccessToken();
362 }
363
OnStateChanged(AssistantManagerService::State new_state)364 void Service::OnStateChanged(AssistantManagerService::State new_state) {
365 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
366
367 if (new_state == AssistantManagerService::State::STARTED)
368 FinalizeAssistantManagerService();
369 if (new_state == AssistantManagerService::State::RUNNING)
370 DVLOG(1) << "Assistant is running";
371
372 AssistantClient::Get()->OnAssistantStatusChanged(
373 ToAssistantStatus(new_state));
374 UpdateListeningState();
375 }
376
OnAmbientUiVisibilityChanged(ash::AmbientUiVisibility visibility)377 void Service::OnAmbientUiVisibilityChanged(
378 ash::AmbientUiVisibility visibility) {
379 DCHECK(IsAmbientAssistantEnabled());
380
381 if (IsSignedOutMode()) {
382 UpdateAssistantManagerState();
383 } else {
384 // Refresh the access_token before we switch back to signed-in mode in case
385 // that we don't have any auth_token cached before.
386 RequestAccessToken();
387 }
388 }
389
UpdateAssistantManagerState()390 void Service::UpdateAssistantManagerState() {
391 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
392 auto* assistant_state = ash::AssistantState::Get();
393
394 if (!assistant_state->hotword_enabled().has_value() ||
395 !assistant_state->settings_enabled().has_value() ||
396 !assistant_state->locale().has_value() ||
397 (!access_token_.has_value() && !IsSignedOutMode()) ||
398 !assistant_state->arc_play_store_enabled().has_value()) {
399 // Assistant state has not finished initialization, let's wait.
400 return;
401 }
402
403 if (IsSignedOutMode()) {
404 // Clear |access_token_| in signed-out mode to keep it synced with what we
405 // will pass to the |assistant_manager_service_|.
406 access_token_ = base::nullopt;
407 }
408
409 if (!assistant_manager_service_)
410 CreateAssistantManagerService();
411
412 auto state = assistant_manager_service_->GetState();
413 switch (state) {
414 case AssistantManagerService::State::STOPPED:
415 if (assistant_state->settings_enabled().value()) {
416 assistant_manager_service_->Start(GetUserInfo(), ShouldEnableHotword());
417 DVLOG(1) << "Request Assistant start";
418 }
419 break;
420 case AssistantManagerService::State::STARTING:
421 case AssistantManagerService::State::STARTED:
422 // If the Assistant is disabled by domain policy, the libassistant will
423 // never becomes ready. Stop waiting for the state change and stop the
424 // service.
425 if (assistant_state->allowed_state() ==
426 AssistantAllowedState::DISALLOWED_BY_POLICY) {
427 StopAssistantManagerService();
428 return;
429 }
430 // Wait if |assistant_manager_service_| is not at a stable state.
431 update_assistant_manager_callback_.Cancel();
432 update_assistant_manager_callback_.Reset(
433 base::BindOnce(&Service::UpdateAssistantManagerState,
434 weak_ptr_factory_.GetWeakPtr()));
435 main_task_runner_->PostDelayedTask(
436 FROM_HERE, update_assistant_manager_callback_.callback(),
437 kUpdateAssistantManagerDelay);
438 break;
439 case AssistantManagerService::State::RUNNING:
440 if (assistant_state->settings_enabled().value()) {
441 assistant_manager_service_->SetUser(GetUserInfo());
442 if (IsAmbientAssistantEnabled())
443 assistant_manager_service_->EnableAmbientMode(InAmbientMode());
444 assistant_manager_service_->EnableHotword(ShouldEnableHotword());
445 assistant_manager_service_->SetArcPlayStoreEnabled(
446 assistant_state->arc_play_store_enabled().value());
447 assistant_manager_service_->SetAssistantContextEnabled(
448 assistant_state->IsScreenContextAllowed());
449 } else {
450 StopAssistantManagerService();
451 }
452 break;
453 }
454 }
455
RetrievePrimaryAccountInfo() const456 CoreAccountInfo Service::RetrievePrimaryAccountInfo() const {
457 CoreAccountInfo account_info = identity_manager_->GetPrimaryAccountInfo(
458 signin::ConsentLevel::kNotRequired);
459 CHECK(!account_info.account_id.empty());
460 CHECK(!account_info.gaia.empty());
461 return account_info;
462 }
463
RequestAccessToken()464 void Service::RequestAccessToken() {
465 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
466
467 // Bypass access token fetching when service is running in signed-out mode.
468 if (IsSignedOutMode()) {
469 VLOG(1) << "Signed out mode detected, bypass access token fetching.";
470 return;
471 }
472
473 if (access_token_fetcher_) {
474 LOG(WARNING) << "Access token already requested.";
475 return;
476 }
477
478 VLOG(1) << "Start requesting access token.";
479 CoreAccountInfo account_info = RetrievePrimaryAccountInfo();
480 if (!identity_manager_->HasAccountWithRefreshToken(account_info.account_id)) {
481 LOG(ERROR) << "Failed to retrieve primary account info. Retrying.";
482 RetryRefreshToken();
483 return;
484 }
485
486 signin::ScopeSet scopes;
487 scopes.insert(kScopeAssistant);
488 scopes.insert(kScopeAuthGcm);
489 if (features::IsOnDeviceAssistantEnabled())
490 scopes.insert(kScopeGeller);
491
492 access_token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount(
493 account_info.account_id, "cros_assistant", scopes,
494 base::BindOnce(&Service::GetAccessTokenCallback, base::Unretained(this)),
495 signin::AccessTokenFetcher::Mode::kImmediate);
496 }
497
GetAccessTokenCallback(GoogleServiceAuthError error,signin::AccessTokenInfo access_token_info)498 void Service::GetAccessTokenCallback(
499 GoogleServiceAuthError error,
500 signin::AccessTokenInfo access_token_info) {
501 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
502
503 // It's safe to delete AccessTokenFetcher from inside its own callback.
504 access_token_fetcher_.reset();
505
506 if (error.state() != GoogleServiceAuthError::NONE) {
507 LOG(ERROR) << "Failed to retrieve token, error: " << error.ToString();
508 RetryRefreshToken();
509 return;
510 }
511
512 access_token_ = access_token_info.token;
513 UpdateAssistantManagerState();
514 token_refresh_timer_->Start(
515 FROM_HERE, access_token_info.expiration_time - base::Time::Now(), this,
516 &Service::RequestAccessToken);
517 }
518
RetryRefreshToken()519 void Service::RetryRefreshToken() {
520 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
521
522 base::TimeDelta backoff_delay =
523 std::min(kMinTokenRefreshDelay *
524 (1 << (token_refresh_error_backoff_factor - 1)),
525 kMaxTokenRefreshDelay) +
526 base::RandDouble() * kMinTokenRefreshDelay;
527 if (backoff_delay < kMaxTokenRefreshDelay)
528 ++token_refresh_error_backoff_factor;
529 token_refresh_timer_->Start(FROM_HERE, backoff_delay, this,
530 &Service::RequestAccessToken);
531 }
532
CreateAssistantManagerService()533 void Service::CreateAssistantManagerService() {
534 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
535
536 assistant_manager_service_ = CreateAndReturnAssistantManagerService();
537 assistant_manager_service_->AddCommunicationErrorObserver(this);
538 assistant_manager_service_->AddAndFireStateObserver(this);
539
540 if (AssistantInteractionLogger::IsLoggingEnabled()) {
541 interaction_logger_ = std::make_unique<AssistantInteractionLogger>();
542 assistant_manager_service_->AddAssistantInteractionSubscriber(
543 interaction_logger_.get());
544 }
545 }
546
547 std::unique_ptr<AssistantManagerService>
CreateAndReturnAssistantManagerService()548 Service::CreateAndReturnAssistantManagerService() {
549 if (assistant_manager_service_for_testing_)
550 return std::move(assistant_manager_service_for_testing_);
551
552 #if BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
553 mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor;
554 AssistantClient::Get()->RequestBatteryMonitor(
555 battery_monitor.InitWithNewPipeAndPassReceiver());
556
557 auto delegate = std::make_unique<AssistantManagerServiceDelegateImpl>(
558 std::move(battery_monitor), context());
559
560 // |assistant_manager_service_| is only created once.
561 DCHECK(pending_url_loader_factory_);
562 return std::make_unique<AssistantManagerServiceImpl>(
563 context(), std::move(delegate), std::move(pending_url_loader_factory_),
564 GetS3ServerUriOverride(), GetDeviceIdOverride());
565 #else
566 return std::make_unique<FakeAssistantManagerServiceImpl>();
567 #endif
568 }
569
FinalizeAssistantManagerService()570 void Service::FinalizeAssistantManagerService() {
571 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
572 DCHECK(assistant_manager_service_->GetState() ==
573 AssistantManagerService::STARTED ||
574 assistant_manager_service_->GetState() ==
575 AssistantManagerService::RUNNING);
576
577 // Ensure one-time mojom initialization.
578 if (is_assistant_manager_service_finalized_)
579 return;
580 is_assistant_manager_service_finalized_ = true;
581
582 AddAshSessionObserver();
583
584 ash::AssistantController::Get()->SetAssistant(
585 assistant_manager_service_.get());
586 }
587
StopAssistantManagerService()588 void Service::StopAssistantManagerService() {
589 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
590
591 assistant_manager_service_->Stop();
592 weak_ptr_factory_.InvalidateWeakPtrs();
593 AssistantClient::Get()->OnAssistantStatusChanged(AssistantStatus::NOT_READY);
594 }
595
AddAshSessionObserver()596 void Service::AddAshSessionObserver() {
597 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
598
599 // No session controller in unittest.
600 if (ash::SessionController::Get()) {
601 // Note that this account can either be a regular account using real gaia,
602 // or a fake gaia account.
603 CoreAccountInfo account_info = RetrievePrimaryAccountInfo();
604 AccountId account_id = user_manager::known_user::GetAccountId(
605 account_info.email, account_info.gaia, AccountType::GOOGLE);
606 scoped_ash_session_observer_ =
607 std::make_unique<ScopedAshSessionObserver>(this, account_id);
608 }
609 }
610
UpdateListeningState()611 void Service::UpdateListeningState() {
612 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
613
614 bool should_listen =
615 !locked_ &&
616 !ash::AssistantState::Get()->locked_full_screen_enabled().value_or(
617 false) &&
618 session_active_;
619 DVLOG(1) << "Update assistant listening state: " << should_listen;
620 assistant_manager_service_->EnableListening(should_listen);
621 assistant_manager_service_->EnableHotword(should_listen &&
622 ShouldEnableHotword());
623 }
624
GetUserInfo() const625 base::Optional<AssistantManagerService::UserInfo> Service::GetUserInfo() const {
626 if (access_token_) {
627 return AssistantManagerService::UserInfo(RetrievePrimaryAccountInfo().gaia,
628 access_token_.value());
629 }
630 return base::nullopt;
631 }
632
ShouldEnableHotword()633 bool Service::ShouldEnableHotword() {
634 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
635
636 bool dsp_available = context()->cras_audio_handler()->HasHotwordDevice();
637 auto* assistant_state = ash::AssistantState::Get();
638
639 // Disable hotword if hotword is not set to always on and power source is not
640 // connected.
641 if (!dsp_available && !assistant_state->hotword_always_on().value_or(false) &&
642 !power_source_connected_) {
643 return false;
644 }
645
646 return assistant_state->hotword_enabled().value();
647 }
648
649 } // namespace assistant
650 } // namespace chromeos
651