Commit ed249990 authored by David Black's avatar David Black Committed by Commit Bot

Refactor Assistant alarms/timers.

Previously the AssistantAlarmTimerController/Model only handled fired
timers. Due to new UX requirements, we are going to need to handle
scheduled and paused timers as well.

This CL makes the necessary changes to the AssistantAlarmTimerController
and model to support scheduled, paused, and firing timers. Note that
though this CL contains sufficient code to support them, it stops short
of actually handling them as this will be done in another set of CLs.

That being the case, this CL does not have a functional impact on the
existing experience.

Also note that this CL removes some "alarm" related nomenclature. Alarms
may/may not be implemented in the near future and (if we do) the code
will be friendlier to treat alarms and timers as distinct entities.

Bug: b:149570650
Change-Id: I6025471b80def7610625dcfa3c66ce17ba7e2817
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2095939Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarAlex Gough <ajgo@chromium.org>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Commit-Queue: David Black <dmblack@google.com>
Cr-Commit-Position: refs/heads/master@{#751512}
parent 2c2a9896
......@@ -16,6 +16,7 @@
#include "base/i18n/message_formatter.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chromeos/services/assistant/public/features.h"
#include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
......@@ -41,25 +42,21 @@ constexpr base::TimeDelta kTickInterval = base::TimeDelta::FromSeconds(1);
// Helpers ---------------------------------------------------------------------
// Creates a notification ID for the given |alarm_timer_id|. It is guaranteed
// that this method will always return the same notification ID given the same
// alarm/timer ID.
std::string CreateTimerNotificationId(const std::string& alarm_timer_id) {
return std::string(kTimerNotificationIdPrefix) + alarm_timer_id;
// Creates a notification ID for the given |timer|. It is guaranteed that this
// method will always return the same notification ID given the same timer.
std::string CreateTimerNotificationId(const mojom::AssistantTimer& timer) {
return std::string(kTimerNotificationIdPrefix) + timer.id;
}
// Creates a notification message for the given |alarm_timer| which has the
// specified amount of |time_remaining|. Note that if the alarm/timer is expired
// the amount of time remaining will be negated.
std::string CreateTimerNotificationMessage(const AlarmTimer& alarm_timer,
base::TimeDelta time_remaining) {
// Creates a notification message for the given |timer|.
std::string CreateTimerNotificationMessage(const mojom::AssistantTimer& timer) {
// Method aliases to prevent line-wrapping below.
const auto createHour = icu::MeasureUnit::createHour;
const auto createMinute = icu::MeasureUnit::createMinute;
const auto createSecond = icu::MeasureUnit::createSecond;
// Calculate hours/minutes/seconds remaining.
const int64_t total_seconds = time_remaining.InSeconds();
const int64_t total_seconds = std::abs(timer.remaining_time.InSeconds());
const int32_t hours = total_seconds / 3600;
const int32_t minutes = (total_seconds - hours * 3600) / 60;
const int32_t seconds = total_seconds % 60;
......@@ -93,9 +90,9 @@ std::string CreateTimerNotificationMessage(const AlarmTimer& alarm_timer,
message = base::StringPrintf("%02d:%02d:%02d", hours, minutes, seconds);
}
// If time has elapsed since the |alarm_timer| has expired, we'll need to
// negate the amount of time remaining.
if (total_seconds && alarm_timer.expired()) {
// If time has elapsed since the |timer| has fired, we'll need to negate the
// amount of time remaining.
if (timer.remaining_time.InSeconds() < 0) {
const auto format = l10n_util::GetStringUTF16(
IDS_ASSISTANT_TIMER_NOTIFICATION_MESSAGE_EXPIRED);
return base::UTF16ToUTF8(
......@@ -106,11 +103,9 @@ std::string CreateTimerNotificationMessage(const AlarmTimer& alarm_timer,
return message;
}
// TODO(llin): Migrate to use the AlarmManager API to better support multiple
// timers when the API is available.
// Creates a notification for the given |timer|.
chromeos::assistant::mojom::AssistantNotificationPtr CreateTimerNotification(
const AlarmTimer& alarm_timer,
base::TimeDelta time_remaining) {
const mojom::AssistantTimer& timer) {
using chromeos::assistant::mojom::AssistantNotification;
using chromeos::assistant::mojom::AssistantNotificationButton;
using chromeos::assistant::mojom::AssistantNotificationPtr;
......@@ -118,8 +113,7 @@ chromeos::assistant::mojom::AssistantNotificationPtr CreateTimerNotification(
const std::string title =
l10n_util::GetStringUTF8(IDS_ASSISTANT_TIMER_NOTIFICATION_TITLE);
const std::string message =
CreateTimerNotificationMessage(alarm_timer, time_remaining);
const std::string message = CreateTimerNotificationMessage(timer);
base::Optional<GURL> stop_alarm_timer_action_url =
assistant::util::CreateAlarmTimerDeepLink(
......@@ -129,7 +123,7 @@ chromeos::assistant::mojom::AssistantNotificationPtr CreateTimerNotification(
base::Optional<GURL> add_time_to_timer_action_url =
assistant::util::CreateAlarmTimerDeepLink(
assistant::util::AlarmTimerAction::kAddTimeToTimer, alarm_timer.id,
assistant::util::AlarmTimerAction::kAddTimeToTimer, timer.id,
kOneMin);
AssistantNotificationPtr notification = AssistantNotification::New();
......@@ -144,7 +138,7 @@ chromeos::assistant::mojom::AssistantNotificationPtr CreateTimerNotification(
notification->title = title;
notification->message = message;
notification->client_id = CreateTimerNotificationId(alarm_timer.id);
notification->client_id = CreateTimerNotificationId(timer);
notification->grouping_key = kTimerNotificationGroupingKey;
// This notification should be able to wake up the display if it was off.
......@@ -208,67 +202,70 @@ void AssistantAlarmTimerController::RemoveModelObserver(
model_.RemoveObserver(observer);
}
void AssistantAlarmTimerController::OnAlarmTimerStateChanged(
mojom::AssistantAlarmTimerEventPtr event) {
if (!event) {
// Nothing is ringing. Remove all alarms and timers.
model_.RemoveAllAlarmsTimers();
void AssistantAlarmTimerController::OnTimerStateChanged(
std::vector<mojom::AssistantTimerPtr> timers) {
if (timers.empty()) {
model_.RemoveAllTimers();
return;
}
switch (event->type) {
case mojom::AssistantAlarmTimerEventType::kTimer:
if (event->data->get_timer_data()->state ==
mojom::AssistantTimerState::kFired) {
// Remove all timers/alarms since there will be only one timer/alarm
// firing.
// TODO(llin): Handle multiple timers firing when the API is supported.
model_.RemoveAllAlarmsTimers();
AlarmTimer timer;
timer.id = event->data->get_timer_data()->timer_id;
timer.type = AlarmTimerType::kTimer;
timer.end_time = base::TimeTicks::Now();
model_.AddAlarmTimer(timer);
}
break;
// TODO(llin): Handle alarm event.
// First we remove all old timers that no longer exist.
for (const auto* old_timer : model_.GetAllTimers()) {
if (std::none_of(timers.begin(), timers.end(),
[&old_timer](const auto& new_or_updated_timer) {
return old_timer->id == new_or_updated_timer->id;
})) {
model_.RemoveTimer(old_timer->id);
}
}
// Then we add any new timers and update existing ones.
for (auto& new_or_updated_timer : timers)
model_.AddOrUpdateTimer(std::move(new_or_updated_timer));
}
void AssistantAlarmTimerController::OnAlarmTimerAdded(
const AlarmTimer& alarm_timer,
const base::TimeDelta& time_remaining) {
// Schedule a repeating timer to tick the tracked alarms/timers.
if (!timer_.IsRunning()) {
timer_.Start(FROM_HERE, kTickInterval, &model_,
&AssistantAlarmTimerModel::Tick);
void AssistantAlarmTimerController::OnTimerAdded(
const mojom::AssistantTimer& timer) {
// Schedule a repeating timer to tick the tracked timers.
if (!ticker_.IsRunning()) {
ticker_.Start(FROM_HERE, kTickInterval, &model_,
&AssistantAlarmTimerModel::Tick);
}
// Create a notification for the added alarm/timer.
assistant_controller_->notification_controller()->AddOrUpdateNotification(
CreateTimerNotification(alarm_timer, time_remaining));
CreateTimerNotification(timer));
}
void AssistantAlarmTimerController::OnAlarmsTimersTicked(
const std::map<std::string, base::TimeDelta>& times_remaining) {
// Update any existing notifications associated w/ our alarms/timers.
for (auto& pair : times_remaining) {
auto* notification_controller =
assistant_controller_->notification_controller();
if (notification_controller->model()->HasNotificationForId(
CreateTimerNotificationId(/*alarm_timer_id=*/pair.first))) {
notification_controller->AddOrUpdateNotification(CreateTimerNotification(
*model_.GetAlarmTimerById(pair.first), pair.second));
}
void AssistantAlarmTimerController::OnTimerUpdated(
const mojom::AssistantTimer& timer) {
// When a |timer| is updated we need to update the corresponding notification
// unless it has already been dismissed by the user.
auto* notification_controller =
assistant_controller_->notification_controller();
if (notification_controller->model()->HasNotificationForId(
CreateTimerNotificationId(timer))) {
notification_controller->AddOrUpdateNotification(
CreateTimerNotification(timer));
}
}
void AssistantAlarmTimerController::OnAllAlarmsTimersRemoved() {
// We can stop our timer from ticking when all alarms/timers are removed.
timer_.Stop();
void AssistantAlarmTimerController::OnTimerRemoved(
const mojom::AssistantTimer& timer) {
// If our model is empty, we no longer need tick updates.
if (model_.empty())
ticker_.Stop();
// Remove any notification associated w/ |timer|.
assistant_controller_->notification_controller()->RemoveNotificationById(
CreateTimerNotificationId(timer), /*from_server=*/false);
}
void AssistantAlarmTimerController::OnAllTimersRemoved() {
// We can stop our timer from ticking when all timers are removed.
ticker_.Stop();
// Remove any notifications associated w/ alarms/timers.
// Remove any notifications associated w/ timers.
assistant_controller_->notification_controller()
->RemoveNotificationByGroupingKey(kTimerNotificationGroupingKey,
/*from_server=*/false);
......
......@@ -7,6 +7,7 @@
#include <map>
#include <string>
#include <vector>
#include "ash/assistant/assistant_controller_observer.h"
#include "ash/assistant/model/assistant_alarm_timer_model.h"
......@@ -52,15 +53,14 @@ class AssistantAlarmTimerController
void RemoveModelObserver(AssistantAlarmTimerModelObserver* observer);
// mojom::AssistantAlarmTimerController:
void OnAlarmTimerStateChanged(
mojom::AssistantAlarmTimerEventPtr event) override;
void OnTimerStateChanged(
std::vector<mojom::AssistantTimerPtr> timers) override;
// AssistantAlarmTimerModelObserver:
void OnAlarmTimerAdded(const AlarmTimer& alarm_timer,
const base::TimeDelta& time_remaining) override;
void OnAlarmsTimersTicked(
const std::map<std::string, base::TimeDelta>& times_remaining) override;
void OnAllAlarmsTimersRemoved() override;
void OnTimerAdded(const mojom::AssistantTimer& timer) override;
void OnTimerUpdated(const mojom::AssistantTimer& timer) override;
void OnTimerRemoved(const mojom::AssistantTimer& timer) override;
void OnAllTimersRemoved() override;
// Provides a pointer to the |assistant| owned by AssistantController.
void SetAssistant(chromeos::assistant::mojom::Assistant* assistant);
......@@ -91,7 +91,7 @@ class AssistantAlarmTimerController
AssistantAlarmTimerModel model_;
base::RepeatingTimer timer_;
base::RepeatingTimer ticker_;
// Owned by AssistantController.
chromeos::assistant::mojom::Assistant* assistant_;
......
......@@ -18,6 +18,7 @@
#include "base/macros.h"
#include "base/test/icu_test_util.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "ui/base/l10n/l10n_util.h"
namespace ash {
......@@ -26,22 +27,14 @@ namespace {
// Helpers ---------------------------------------------------------------------
// Creates a timer event with a given |id| and |state|.
mojom::AssistantAlarmTimerEventPtr CreateTimerEvent(
const std::string& id,
mojom::AssistantTimerState state) {
auto timer_data = mojom::AssistantTimer::New();
timer_data->timer_id = id;
timer_data->state = state;
auto alarm_timer_data = mojom::AlarmTimerData::New();
alarm_timer_data->set_timer_data(std::move(timer_data));
auto timer_event = mojom::AssistantAlarmTimerEvent::New();
timer_event->type = mojom::AssistantAlarmTimerEventType::kTimer;
timer_event->data = std::move(alarm_timer_data);
return timer_event;
// Creates a timer with the specified |id| which is firing now.
mojom::AssistantTimerPtr CreateFiringTimer(const std::string& id) {
mojom::AssistantTimerPtr timer = mojom::AssistantTimer::New();
timer->id = id;
timer->state = mojom::AssistantTimerState::kFired;
timer->fire_time = base::Time::Now();
timer->remaining_time = base::TimeDelta();
return timer;
}
// ScopedNotificationModelObserver ---------------------------------------------
......@@ -165,8 +158,9 @@ TEST_F(AssistantAlarmTimerControllerTest, AddsAndUpdatesTimerNotification) {
ScopedNotificationModelObserver notification_model_observer;
// Fire a timer.
controller()->OnAlarmTimerStateChanged(
CreateTimerEvent(/*id=*/"1", mojom::AssistantTimerState::kFired));
std::vector<mojom::AssistantTimerPtr> timers;
timers.push_back(CreateFiringTimer(/*id=*/"1"));
controller()->OnTimerStateChanged(std::move(timers));
// We expect our title to be internationalized.
const std::string expected_title =
......
......@@ -4,6 +4,7 @@ include_rules = [
"+ash/assistant/model",
"+ash/public/cpp/app_list",
"+ash/public/cpp/assistant",
"+ash/public/mojom",
"+chromeos/services/assistant/public" ,
"+services/content/public",
"+ui/gfx/geometry",
......
......@@ -5,7 +5,8 @@
#include "ash/assistant/model/assistant_alarm_timer_model.h"
#include "ash/assistant/model/assistant_alarm_timer_model_observer.h"
#include "base/stl_util.h"
#include "ash/public/mojom/assistant_controller.mojom.h"
#include "base/time/time.h"
namespace ash {
......@@ -23,54 +24,89 @@ void AssistantAlarmTimerModel::RemoveObserver(
observers_.RemoveObserver(observer);
}
void AssistantAlarmTimerModel::AddAlarmTimer(const AlarmTimer& alarm_timer) {
DCHECK(!base::Contains(alarms_timers_, alarm_timer.id));
alarms_timers_[alarm_timer.id] = alarm_timer;
NotifyAlarmTimerAdded(alarm_timer, /*time_remaining=*/base::TimeTicks::Now() -
alarm_timer.end_time);
void AssistantAlarmTimerModel::AddOrUpdateTimer(
mojom::AssistantTimerPtr timer) {
auto* ptr = timer.get();
auto it = timers_.find(timer->id);
if (it == timers_.end()) {
timers_[timer->id] = std::move(timer);
NotifyTimerAdded(*ptr);
return;
}
timers_[timer->id] = std::move(timer);
NotifyTimerUpdated(*ptr);
}
void AssistantAlarmTimerModel::RemoveTimer(const std::string& id) {
auto it = timers_.find(id);
if (it == timers_.end())
return;
mojom::AssistantTimerPtr timer = std::move(it->second);
timers_.erase(it);
NotifyTimerRemoved(*timer);
}
void AssistantAlarmTimerModel::RemoveAllAlarmsTimers() {
if (alarms_timers_.empty())
void AssistantAlarmTimerModel::RemoveAllTimers() {
if (timers_.empty())
return;
alarms_timers_.clear();
NotifyAllAlarmsTimersRemoved();
timers_.clear();
NotifyAllTimersRemoved();
}
std::vector<const mojom::AssistantTimer*>
AssistantAlarmTimerModel::GetAllTimers() const {
std::vector<const mojom::AssistantTimer*> timers;
for (const auto& pair : timers_)
timers.push_back(pair.second.get());
return timers;
}
const AlarmTimer* AssistantAlarmTimerModel::GetAlarmTimerById(
const mojom::AssistantTimer* AssistantAlarmTimerModel::GetTimerById(
const std::string& id) const {
auto it = alarms_timers_.find(id);
return it != alarms_timers_.end() ? &it->second : nullptr;
auto it = timers_.find(id);
return it != timers_.end() ? it->second.get() : nullptr;
}
void AssistantAlarmTimerModel::Tick() {
const base::TimeTicks now = base::TimeTicks::Now();
if (timers_.empty())
return;
// Calculate remaining time for all tracked alarms/timers.
std::map<std::string, base::TimeDelta> times_remaining;
for (auto& alarm_timer : alarms_timers_)
times_remaining[alarm_timer.first] = now - alarm_timer.second.end_time;
for (auto& pair : timers_) {
mojom::AssistantTimer* timer = pair.second.get();
if (timer->state == mojom::AssistantTimerState::kPaused)
continue;
NotifyAlarmsTimersTicked(times_remaining);
timer->remaining_time = timer->fire_time - base::Time::Now();
NotifyTimerUpdated(*timer);
}
}
void AssistantAlarmTimerModel::NotifyTimerAdded(
const mojom::AssistantTimer& timer) {
for (auto& observer : observers_)
observer.OnTimerAdded(timer);
}
void AssistantAlarmTimerModel::NotifyAlarmTimerAdded(
const AlarmTimer& alarm_timer,
const base::TimeDelta& time_remaining) {
void AssistantAlarmTimerModel::NotifyTimerUpdated(
const mojom::AssistantTimer& timer) {
for (auto& observer : observers_)
observer.OnAlarmTimerAdded(alarm_timer, time_remaining);
observer.OnTimerUpdated(timer);
}
void AssistantAlarmTimerModel::NotifyAlarmsTimersTicked(
const std::map<std::string, base::TimeDelta>& times_remaining) {
void AssistantAlarmTimerModel::NotifyTimerRemoved(
const mojom::AssistantTimer& timer) {
for (auto& observer : observers_)
observer.OnAlarmsTimersTicked(times_remaining);
observer.OnTimerRemoved(timer);
}
void AssistantAlarmTimerModel::NotifyAllAlarmsTimersRemoved() {
void AssistantAlarmTimerModel::NotifyAllTimersRemoved() {
for (auto& observer : observers_)
observer.OnAllAlarmsTimersRemoved();
observer.OnAllTimersRemoved();
}
} // namespace ash
......@@ -7,7 +7,9 @@
#include <map>
#include <string>
#include <vector>
#include "ash/public/mojom/assistant_controller.mojom-forward.h"
#include "base/component_export.h"
#include "base/macros.h"
#include "base/observer_list.h"
......@@ -16,20 +18,6 @@ namespace ash {
class AssistantAlarmTimerModelObserver;
enum class AlarmTimerType {
kAlarm,
kTimer,
};
struct COMPONENT_EXPORT(ASSISTANT_MODEL) AlarmTimer {
std::string id;
AlarmTimerType type;
base::TimeTicks end_time;
// Returns true if this alarm/timer has expired.
bool expired() const { return base::TimeTicks::Now() >= end_time; }
};
// The model belonging to AssistantAlarmTimerController which tracks alarm/timer
// state and notifies a pool of observers.
class COMPONENT_EXPORT(ASSISTANT_MODEL) AssistantAlarmTimerModel {
......@@ -41,26 +29,35 @@ class COMPONENT_EXPORT(ASSISTANT_MODEL) AssistantAlarmTimerModel {
void AddObserver(AssistantAlarmTimerModelObserver* observer);
void RemoveObserver(AssistantAlarmTimerModelObserver* observer);
// Adds the specified alarm/timer to the model.
void AddAlarmTimer(const AlarmTimer& alarm_timer);
// Adds or updates the timer specified by |timer.id| in the model.
void AddOrUpdateTimer(mojom::AssistantTimerPtr timer);
// Removes the timer uniquely identified by |id|.
void RemoveTimer(const std::string& id);
// Remove all alarms/timers from the model.
void RemoveAllAlarmsTimers();
// Remove all timers from the model.
void RemoveAllTimers();
// Returns the alarm/timer uniquely identified by |id|.
const AlarmTimer* GetAlarmTimerById(const std::string& id) const;
// Returns all timers from the model.
std::vector<const mojom::AssistantTimer*> GetAllTimers() const;
// Invoke to tick any alarms/timers and to notify observers of time remaining.
// Returns the timer uniquely identified by |id|.
const mojom::AssistantTimer* GetTimerById(const std::string& id) const;
// Invoke to tick any timers. Note that this will update the |remaining_time|
// for all timers in the model and trigger an OnTimerUpdated() event.
void Tick();
// Returns |true| if the model contains no timers, |false| otherwise.
bool empty() const { return timers_.empty(); }
private:
void NotifyAlarmTimerAdded(const AlarmTimer& alarm_timer,
const base::TimeDelta& time_remaining);
void NotifyAlarmsTimersTicked(
const std::map<std::string, base::TimeDelta>& times_remaining);
void NotifyAllAlarmsTimersRemoved();
void NotifyTimerAdded(const mojom::AssistantTimer& timer);
void NotifyTimerUpdated(const mojom::AssistantTimer& timer);
void NotifyTimerRemoved(const mojom::AssistantTimer& timer);
void NotifyAllTimersRemoved();
std::map<std::string, AlarmTimer> alarms_timers_;
std::map<std::string, mojom::AssistantTimerPtr> timers_;
base::ObserverList<AssistantAlarmTimerModelObserver> observers_;
......
......@@ -8,33 +8,28 @@
#include <map>
#include <string>
#include "ash/public/mojom/assistant_controller.mojom-forward.h"
#include "base/component_export.h"
#include "base/observer_list_types.h"
namespace base {
class TimeDelta;
} // namespace base
namespace ash {
struct AlarmTimer;
// A checked observer which receives notification of changes to the Assistant
// alarm/timer model.
class COMPONENT_EXPORT(ASSISTANT_MODEL) AssistantAlarmTimerModelObserver
: public base::CheckedObserver {
public:
// Invoked when the specified alarm/timer has been added.
virtual void OnAlarmTimerAdded(const AlarmTimer& alarm_timer,
const base::TimeDelta& time_remaining) {}
// Invoked when the specified timer has been added.
virtual void OnTimerAdded(const mojom::AssistantTimer& timer) {}
// Invoked when the specified timer has been updated.
virtual void OnTimerUpdated(const mojom::AssistantTimer& timer) {}
// Invoked when the alarms/timers associated with the given ids have ticked
// with the specified time remaining.
virtual void OnAlarmsTimersTicked(
const std::map<std::string, base::TimeDelta>& times_remaining) {}
// Invoked when the specified timer has been removed.
virtual void OnTimerRemoved(const mojom::AssistantTimer& timer) {}
// Invoked when all alarms/timers have been removed.
virtual void OnAllAlarmsTimersRemoved() {}
// Invoked when all timers have been removed.
virtual void OnAllTimersRemoved() {}
protected:
~AssistantAlarmTimerModelObserver() override = default;
......
......@@ -8,54 +8,37 @@ import "chromeos/services/assistant/public/mojom/assistant_notification.mojom";
import "mojo/public/mojom/base/time.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
// Represents the current state of an Assistant timer.
enum AssistantTimerState {
kUnknown,
// The timer is scheduled to fire at some future date.
kScheduled,
// The timer will not fire but is kept in the queue of scheduled events;
// it can be resumed after which it will fire in |remaining_duration_ms|.
// it can be resumed after which it will fire in |remaining_time|.
kPaused,
// The timer has fired. In the simplest case this means the timer has
// begun ringing.
kFired,
};
// Models an Assistant timer.
struct AssistantTimer {
string timer_id;
// The current state of this timer.
string id;
string label;
AssistantTimerState state;
// TODO(llin): Add more timer data.
};
// Assistant alarm/timer event type.
// Currently, the AlarmTimerManager maintains only one firing alarm/timer,
// the previous one will be dismissed if the second one firing.
enum AssistantAlarmTimerEventType {
kTimer
// TODO(llin): Add alarm event type.
};
union AlarmTimerData {
AssistantTimer timer_data;
// TODO(llin): Add alarm data.
};
// A composite struct that will hold exactly one alarm or timer.
struct AssistantAlarmTimerEvent {
AssistantAlarmTimerEventType type;
AlarmTimerData? data;
mojo_base.mojom.Time fire_time;
mojo_base.mojom.TimeDelta remaining_time;
};
// Interface to the AssistantAlarmTimerController which is owned by the
// AssistantController. Currently used by the Assistant service to notify Ash
// of changes to the underlying alarm/timer state in LibAssistant.
interface AssistantAlarmTimerController {
// Invoked when an alarm/timer state changed. No alarm/timer is ringing if
// |event| is nullptr.
OnAlarmTimerStateChanged(AssistantAlarmTimerEvent? event);
// Invoked when timer state has changed. Note that |timers| may be empty.
OnTimerStateChanged(array<AssistantTimer> timers);
};
// Interface to the AssistantNotificationController which is owned by the
......
......@@ -21,6 +21,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "chromeos/assistant/internal/internal_constants.h"
#include "chromeos/assistant/internal/proto/google3/assistant/api/client_input/warmer_welcome_input.pb.h"
......@@ -42,7 +43,6 @@
#include "libassistant/shared/internal_api/assistant_manager_internal.h"
#include "libassistant/shared/public/assistant_manager.h"
#include "libassistant/shared/public/media_manager.h"
#include "mojo/public/mojom/base/time.mojom.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "ui/accessibility/accessibility_switches.h"
......@@ -1356,45 +1356,44 @@ void AssistantManagerServiceImpl::MediaSessionMetadataChanged(
UpdateMediaState();
}
// TODO(dmblack): Handle non-firing (e.g. paused or scheduled) timers.
void AssistantManagerServiceImpl::OnAlarmTimerStateChanged() {
ENSURE_MAIN_THREAD(&AssistantManagerServiceImpl::OnAlarmTimerStateChanged);
// Currently, we only handle ringing events here. After some AlarmTimerManager
// API improvement, we will be handling other alarm/timer events.
auto* alarm_timer_manager =
assistant_manager_internal_->GetAlarmTimerManager();
// TODO(llin): Use GetAllEvents after the AlarmTimerManager API improvement is
// ready (b/128701326).
const assistant_client::AlarmTimerEvent& ringing_event =
alarm_timer_manager->GetRingingEvent();
switch (ringing_event.type) {
case assistant_client::AlarmTimerEvent::NONE:
assistant_alarm_timer_controller()->OnAlarmTimerStateChanged(nullptr);
break;
case assistant_client::AlarmTimerEvent::TIMER: {
ash::mojom::AssistantAlarmTimerEventPtr alarm_timer_event_ptr =
ash::mojom::AssistantAlarmTimerEvent::New();
alarm_timer_event_ptr->type =
ash::mojom::AssistantAlarmTimerEventType::kTimer;
if (ringing_event.type == assistant_client::AlarmTimerEvent::TIMER) {
alarm_timer_event_ptr->data = ash::mojom::AlarmTimerData::New();
ash::mojom::AssistantTimerPtr timer_data_ptr =
ash::mojom::AssistantTimer::New();
timer_data_ptr->state = GetTimerState(ringing_event.timer_data.state);
timer_data_ptr->timer_id = ringing_event.timer_data.timer_id;
alarm_timer_event_ptr->data->set_timer_data(std::move(timer_data_ptr));
}
assistant_alarm_timer_controller()->OnAlarmTimerStateChanged(
std::move(alarm_timer_event_ptr));
break;
std::vector<ash::mojom::AssistantTimerPtr> timers;
auto* manager = assistant_manager_internal_->GetAlarmTimerManager();
for (const auto& event : manager->GetAllEvents()) {
// Note that we currently only handle timers, alarms are unsupported. Also
// note that we only handle timers that are fired. Non-firing (e.g. paused
// or scheduled) timers will be supported in the near future.
if (event.type != assistant_client::AlarmTimerEvent::TIMER ||
event.timer_data.state != assistant_client::Timer::State::FIRED) {
continue;
}
case assistant_client::AlarmTimerEvent::ALARM:
// TODO(llin): Handle alarm.
NOTREACHED();
break;
ash::mojom::AssistantTimerPtr timer = ash::mojom::AssistantTimer::New();
timer->id = event.timer_data.timer_id;
timer->label = event.timer_data.label;
timer->state = GetTimerState(event.timer_data.state);
// LibAssistant provides |fire_time_ms| as an offset from unix epoch.
timer->fire_time =
base::Time::UnixEpoch() +
base::TimeDelta::FromMilliseconds(event.timer_data.fire_time_ms);
// If the |timer| is paused, LibAssistant will specify the amount of time
// remaining. Otherwise we calculate it based on |fire_time|.
timer->remaining_time =
timer->state == ash::mojom::AssistantTimerState::kPaused
? base::TimeDelta::FromMilliseconds(
event.timer_data.remaining_duration_ms)
: timer->fire_time - base::Time::Now();
timers.push_back(std::move(timer));
}
assistant_alarm_timer_controller()->OnTimerStateChanged(std::move(timers));
}
void AssistantManagerServiceImpl::OnAccessibilityStatusChanged(
......
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