File: idle_event_notifier.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (182 lines) | stat: -rw-r--r-- 6,917 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_POWER_ML_IDLE_EVENT_NOTIFIER_H_
#define CHROME_BROWSER_ASH_POWER_ML_IDLE_EVENT_NOTIFIER_H_

#include <memory>
#include <optional>

#include "base/gtest_prod_util.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "chrome/browser/ash/power/ml/boot_clock.h"
#include "chrome/browser/ash/power/ml/user_activity_event.pb.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "services/viz/public/mojom/compositing/video_detector_observer.mojom.h"
#include "ui/base/user_activity/user_activity_detector.h"
#include "ui/base/user_activity/user_activity_observer.h"

namespace ash {
namespace power {
namespace ml {

class RecentEventsCounter;

// This is time since midnight in the local time zone and may move back or
// forward when DST starts or stops.
using TimeOfDay = base::TimeDelta;

// IdleEventNotifier listens to signals and notifies its observers when
// ScreenDimImminent is received from PowerManagerClient. This generates an idle
// event.
class IdleEventNotifier : public chromeos::PowerManagerClient::Observer,
                          public ui::UserActivityObserver,
                          public viz::mojom::VideoDetectorObserver {
 public:
  // If suspend duration is greater than this, we reset timestamps used to calc
  // |ActivityData::recent_time_active|. We also merge video-playing sessions
  // that have a pause shorter than this.
  static constexpr base::TimeDelta kIdleDelay = base::Seconds(30);

  // Count number of key, mouse and touch events in the past hour.
  static constexpr auto kUserInputEventsDuration = base::Hours(1);

  // Granularity of input events is per minute.
  static constexpr int kNumUserInputEventsBuckets =
      kUserInputEventsDuration.InMinutes();

  struct ActivityData {
    ActivityData();

    ActivityData(const ActivityData& input_data);

    UserActivityEvent_Features_DayOfWeek last_activity_day =
        UserActivityEvent_Features_DayOfWeek_SUN;

    // The local time of the last activity before an idle event occurs.
    TimeOfDay last_activity_time_of_day;

    // Last user activity time of the sequence of activities ending in the last
    // activity. It could be different from |last_activity_time_of_day|
    // if the last activity is not a user activity (e.g. video). It is unset if
    // there is no user activity before the idle event is fired.
    std::optional<TimeOfDay> last_user_activity_time_of_day;

    // Duration of activity up to the last activity.
    base::TimeDelta recent_time_active;

    // Duration from the last key/mouse/touch to the time when idle event is
    // generated.  It is unset if there is no key/mouse/touch activity before
    // the idle event.
    std::optional<base::TimeDelta> time_since_last_key;
    std::optional<base::TimeDelta> time_since_last_mouse;
    std::optional<base::TimeDelta> time_since_last_touch;
    // How long recent video has been playing.
    base::TimeDelta video_playing_time;
    // Duration from when video ended. It is unset if video did not play
    // (|video_playing_time| = 0).
    std::optional<base::TimeDelta> time_since_video_ended;
    // True if video is currently playing. False otherwise.
    bool is_video_playing = false;

    int key_events_in_last_hour = 0;
    int mouse_events_in_last_hour = 0;
    int touch_events_in_last_hour = 0;
  };

  IdleEventNotifier(
      chromeos::PowerManagerClient* power_client,
      ui::UserActivityDetector* detector,
      mojo::PendingReceiver<viz::mojom::VideoDetectorObserver> receiver);

  IdleEventNotifier(const IdleEventNotifier&) = delete;
  IdleEventNotifier& operator=(const IdleEventNotifier&) = delete;

  ~IdleEventNotifier() override;

  // chromeos::PowerManagerClient::Observer overrides:
  void LidEventReceived(chromeos::PowerManagerClient::LidState state,
                        base::TimeTicks timestamp) override;
  void PowerChanged(const power_manager::PowerSupplyProperties& proto) override;
  void SuspendDone(base::TimeDelta sleep_duration) override;

  // ui::UserActivityObserver overrides:
  void OnUserActivity(const ui::Event* event) override;

  // viz::mojom::VideoDetectorObserver overrides:
  void OnVideoActivityStarted() override;
  void OnVideoActivityEnded() override;

  // Called in UserActivityController::ShouldDeferScreenDim to prepare activity
  // data for making Smart Dim decision.
  ActivityData GetActivityDataAndReset();

  // Get activity data only, do not mutate the class, may be used by machine
  // learning internal page.
  ActivityData GetActivityData() const;

 private:
  FRIEND_TEST_ALL_PREFIXES(IdleEventNotifierTest, CheckInitialValues);
  friend class IdleEventNotifierTest;

  enum class ActivityType {
    USER_OTHER,  // All other user-related activities.
    KEY,
    MOUSE,
    VIDEO,
    TOUCH
  };

  struct ActivityDataInternal;

  ActivityData ConvertActivityData(
      const ActivityDataInternal& internal_data) const;

  // Updates all activity-related timestamps.
  void UpdateActivityData(ActivityType type);

  // Clears timestamps used to calculate |ActivityData::recent_time_active| so
  // that its duration is recalculated after ScreenDimImminent is received or
  // when suspend duration is longer than kIdleDelay.
  // Also clears timestamps for video playing so that duration of video playing
  // will be recalculated.
  void ResetTimestampsForRecentActivity();

  BootClock boot_clock_;

  base::ScopedObservation<chromeos::PowerManagerClient,
                          chromeos::PowerManagerClient::Observer>
      power_manager_client_observation_{this};
  base::ScopedObservation<ui::UserActivityDetector, ui::UserActivityObserver>
      user_activity_observation_{this};

  // Last-received external power state. Changes are treated as user activity.
  std::optional<power_manager::PowerSupplyProperties_ExternalPower>
      external_power_;

  base::ObserverList<Observer>::Unchecked observers_;

  // Holds activity timestamps while we monitor for idle events. It will be
  // converted to an ActivityData when an idle event is sent out.
  std::unique_ptr<ActivityDataInternal> internal_data_;

  // Whether video is playing.
  bool video_playing_ = false;
  mojo::Receiver<viz::mojom::VideoDetectorObserver> receiver_;

  std::unique_ptr<RecentEventsCounter> key_counter_;
  std::unique_ptr<RecentEventsCounter> mouse_counter_;
  std::unique_ptr<RecentEventsCounter> touch_counter_;
};

}  // namespace ml
}  // namespace power
}  // namespace ash

#endif  // CHROME_BROWSER_ASH_POWER_ML_IDLE_EVENT_NOTIFIER_H_