1 // Copyright 2017 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 "chrome/browser/chromeos/power/ml/user_activity_ukm_logger_impl.h"
6
7 #include <memory>
8 #include <vector>
9
10 #include "chrome/browser/chromeos/power/ml/user_activity_event.pb.h"
11 #include "chrome/browser/chromeos/power/ml/user_activity_manager.h"
12 #include "components/ukm/test_ukm_recorder.h"
13 #include "services/metrics/public/cpp/ukm_builders.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace chromeos {
17 namespace power {
18 namespace ml {
19
20 using ukm::builders::UserActivity;
21 using ukm::builders::UserActivityId;
22
23 class UserActivityUkmLoggerTest : public testing::Test {
24 public:
UserActivityUkmLoggerTest()25 UserActivityUkmLoggerTest() {
26 // These values are arbitrary but must correspond with the values
27 // in CheckUserActivityValues.
28 UserActivityEvent::Event* event = user_activity_event_.mutable_event();
29 event->set_log_duration_sec(395);
30 event->set_reason(UserActivityEvent::Event::USER_ACTIVITY);
31 event->set_type(UserActivityEvent::Event::REACTIVATE);
32 event->set_screen_dim_occurred(true);
33 event->set_screen_off_occurred(true);
34 event->set_screen_lock_occurred(true);
35
36 // In the order of metrics names in ukm.
37 UserActivityEvent::Features* features =
38 user_activity_event_.mutable_features();
39 features->set_battery_percent(96.0);
40 features->set_device_management(UserActivityEvent::Features::UNMANAGED);
41 features->set_device_mode(UserActivityEvent::Features::CLAMSHELL);
42 features->set_device_type(UserActivityEvent::Features::CHROMEBOOK);
43 features->set_last_activity_day(UserActivityEvent::Features::MON);
44 features->set_last_activity_time_sec(7300);
45 features->set_last_user_activity_time_sec(3800);
46 features->set_key_events_in_last_hour(20000);
47 features->set_recent_time_active_sec(10);
48 features->set_previous_negative_actions_count(2);
49 features->set_previous_positive_actions_count(1);
50 features->set_video_playing_time_sec(800);
51 features->set_on_to_dim_sec(100);
52 features->set_dim_to_screen_off_sec(200);
53 features->set_screen_dimmed_initially(false);
54 features->set_screen_locked_initially(false);
55 features->set_screen_off_initially(false);
56 features->set_time_since_last_mouse_sec(100);
57 features->set_time_since_last_touch_sec(311);
58 features->set_time_since_video_ended_sec(400);
59 features->set_mouse_events_in_last_hour(89);
60 features->set_touch_events_in_last_hour(1890);
61
62 UserActivityEvent::ModelPrediction* prediction =
63 user_activity_event_.mutable_model_prediction();
64 prediction->set_decision_threshold(50);
65 prediction->set_inactivity_score(60);
66 prediction->set_model_applied(true);
67 prediction->set_response(UserActivityEvent::ModelPrediction::NO_DIM);
68
69 user_activity_logger_delegate_ukm_.ukm_recorder_ = &recorder_;
70 }
71
72 protected:
LogActivity(const UserActivityEvent & event)73 void LogActivity(const UserActivityEvent& event) {
74 user_activity_logger_delegate_ukm_.LogActivity(event);
75 }
76
CheckUserActivityValues(const ukm::mojom::UkmEntry * entry)77 void CheckUserActivityValues(const ukm::mojom::UkmEntry* entry) {
78 recorder_.ExpectEntryMetric(entry, UserActivity::kEventLogDurationName,
79 395);
80 recorder_.ExpectEntryMetric(entry, UserActivity::kEventReasonName,
81 UserActivityEvent::Event::USER_ACTIVITY);
82 recorder_.ExpectEntryMetric(entry, UserActivity::kEventTypeName,
83 UserActivityEvent::Event::REACTIVATE);
84 recorder_.ExpectEntryMetric(entry, UserActivity::kBatteryPercentName, 95);
85 recorder_.ExpectEntryMetric(entry, UserActivity::kDeviceManagementName,
86 UserActivityEvent::Features::UNMANAGED);
87 recorder_.ExpectEntryMetric(entry, UserActivity::kDeviceModeName,
88 UserActivityEvent::Features::CLAMSHELL);
89 recorder_.ExpectEntryMetric(entry, UserActivity::kDeviceTypeName,
90 UserActivityEvent::Features::CHROMEBOOK);
91 recorder_.ExpectEntryMetric(entry, UserActivity::kLastActivityDayName,
92 UserActivityEvent::Features::MON);
93 recorder_.ExpectEntryMetric(entry, UserActivity::kKeyEventsInLastHourName,
94 10000);
95 recorder_.ExpectEntryMetric(entry, UserActivity::kLastActivityTimeName, 2);
96 recorder_.ExpectEntryMetric(entry, UserActivity::kLastUserActivityTimeName,
97 1);
98 recorder_.ExpectEntryMetric(entry, UserActivity::kModelAppliedName, 1);
99 recorder_.ExpectEntryMetric(entry,
100 UserActivity::kModelDecisionThresholdName, 50);
101 recorder_.ExpectEntryMetric(entry, UserActivity::kModelInactivityScoreName,
102 60);
103 recorder_.ExpectEntryMetric(entry, UserActivity::kModelResponseName, 1);
104 recorder_.ExpectEntryMetric(entry, UserActivity::kMouseEventsInLastHourName,
105 89);
106 EXPECT_FALSE(recorder_.EntryHasMetric(entry, UserActivity::kOnBatteryName));
107 recorder_.ExpectEntryMetric(
108 entry, UserActivity::kPreviousNegativeActionsCountName, 2);
109 recorder_.ExpectEntryMetric(
110 entry, UserActivity::kPreviousPositiveActionsCountName, 1);
111
112 recorder_.ExpectEntryMetric(entry, UserActivity::kRecentTimeActiveName, 10);
113 recorder_.ExpectEntryMetric(entry,
114 UserActivity::kRecentVideoPlayingTimeName, 600);
115 recorder_.ExpectEntryMetric(entry, UserActivity::kScreenDimDelayName, 100);
116 recorder_.ExpectEntryMetric(entry, UserActivity::kScreenDimmedInitiallyName,
117 false);
118 recorder_.ExpectEntryMetric(entry, UserActivity::kScreenDimOccurredName,
119 true);
120 recorder_.ExpectEntryMetric(entry, UserActivity::kScreenDimToOffDelayName,
121 200);
122 recorder_.ExpectEntryMetric(entry, UserActivity::kScreenLockedInitiallyName,
123 false);
124 recorder_.ExpectEntryMetric(entry, UserActivity::kScreenLockOccurredName,
125 true);
126 recorder_.ExpectEntryMetric(entry, UserActivity::kScreenOffInitiallyName,
127 false);
128 recorder_.ExpectEntryMetric(entry, UserActivity::kScreenOffOccurredName,
129 true);
130
131 recorder_.ExpectEntryMetric(entry, UserActivity::kSequenceIdName, 1);
132 EXPECT_FALSE(
133 recorder_.EntryHasMetric(entry, UserActivity::kTimeSinceLastKeyName));
134 recorder_.ExpectEntryMetric(entry, UserActivity::kTimeSinceLastMouseName,
135 100);
136 recorder_.ExpectEntryMetric(entry, UserActivity::kTimeSinceLastTouchName,
137 311);
138 recorder_.ExpectEntryMetric(
139 entry, UserActivity::kTimeSinceLastVideoEndedName, 360);
140 recorder_.ExpectEntryMetric(entry, UserActivity::kTouchEventsInLastHourName,
141 1000);
142 }
143
144 UserActivityEvent user_activity_event_;
145 ukm::TestUkmRecorder recorder_;
146
147 private:
148 UserActivityUkmLoggerImpl user_activity_logger_delegate_ukm_;
149 DISALLOW_COPY_AND_ASSIGN(UserActivityUkmLoggerTest);
150 };
151
TEST_F(UserActivityUkmLoggerTest,BasicLogging)152 TEST_F(UserActivityUkmLoggerTest, BasicLogging) {
153 auto user_activity_event = user_activity_event_;
154 UserActivityEvent::Features* features =
155 user_activity_event.mutable_features();
156 features->set_source_id(recorder_.GetNewSourceID());
157 const GURL kUrl1 = GURL("https://example1.com/");
158 features->set_tab_domain(kUrl1.host());
159 features->set_engagement_score(90);
160 features->set_has_form_entry(false);
161
162 LogActivity(user_activity_event);
163
164 const auto& activity_entries =
165 recorder_.GetEntriesByName(UserActivity::kEntryName);
166 EXPECT_EQ(1u, activity_entries.size());
167 const ukm::mojom::UkmEntry* activity_entry = activity_entries[0];
168 CheckUserActivityValues(activity_entry);
169
170 const ukm::SourceId kSourceId = activity_entry->source_id;
171 const auto& activity_id_entries =
172 recorder_.GetEntriesByName(UserActivityId::kEntryName);
173 EXPECT_EQ(1u, activity_id_entries.size());
174
175 const ukm::mojom::UkmEntry* entry = activity_id_entries[0];
176 recorder_.ExpectEntryMetric(entry, UserActivityId::kActivityIdName,
177 kSourceId);
178 recorder_.ExpectEntryMetric(entry, UserActivityId::kSiteEngagementScoreName,
179 90);
180 recorder_.ExpectEntryMetric(entry, UserActivityId::kHasFormEntryName, 0);
181 }
182
183 // Tests what would be logged in Incognito: when source IDs are not provided.
TEST_F(UserActivityUkmLoggerTest,EmptySources)184 TEST_F(UserActivityUkmLoggerTest, EmptySources) {
185 LogActivity(user_activity_event_);
186
187 const auto& activity_entries =
188 recorder_.GetEntriesByName(UserActivity::kEntryName);
189 EXPECT_EQ(1u, activity_entries.size());
190 const ukm::mojom::UkmEntry* activity_entry = activity_entries[0];
191
192 CheckUserActivityValues(activity_entry);
193
194 EXPECT_EQ(0u, recorder_.GetEntriesByName(UserActivityId::kEntryName).size());
195 }
196
TEST_F(UserActivityUkmLoggerTest,TwoUserActivityEvents)197 TEST_F(UserActivityUkmLoggerTest, TwoUserActivityEvents) {
198 // A second event will be logged. Values correspond with the checks below.
199 UserActivityEvent user_activity_event2;
200 UserActivityEvent::Event* event = user_activity_event2.mutable_event();
201 event->set_log_duration_sec(35);
202 event->set_reason(UserActivityEvent::Event::IDLE_SLEEP);
203 event->set_type(UserActivityEvent::Event::TIMEOUT);
204
205 UserActivityEvent::Features* features =
206 user_activity_event2.mutable_features();
207 features->set_battery_percent(86.0);
208 features->set_device_management(UserActivityEvent::Features::MANAGED);
209 features->set_device_mode(UserActivityEvent::Features::CLAMSHELL);
210 features->set_device_type(UserActivityEvent::Features::CHROMEBOOK);
211 features->set_last_activity_day(UserActivityEvent::Features::TUE);
212 features->set_last_activity_time_sec(7300);
213 features->set_last_user_activity_time_sec(3800);
214 features->set_recent_time_active_sec(20);
215 features->set_on_to_dim_sec(10);
216 features->set_dim_to_screen_off_sec(20);
217 features->set_time_since_last_mouse_sec(200);
218
219 UserActivityEvent::ModelPrediction* prediction =
220 user_activity_event2.mutable_model_prediction();
221 prediction->set_model_applied(false);
222 prediction->set_response(UserActivityEvent::ModelPrediction::MODEL_ERROR);
223
224 LogActivity(user_activity_event_);
225 LogActivity(user_activity_event2);
226
227 const auto& activity_entries =
228 recorder_.GetEntriesByName(UserActivity::kEntryName);
229 EXPECT_EQ(2u, activity_entries.size());
230
231 // Check the first user activity values.
232 CheckUserActivityValues(activity_entries[0]);
233
234 // Check the second user activity values.
235 const ukm::mojom::UkmEntry* entry1 = activity_entries[1];
236 recorder_.ExpectEntryMetric(entry1, UserActivity::kEventLogDurationName, 35);
237 recorder_.ExpectEntryMetric(entry1, UserActivity::kEventReasonName,
238 UserActivityEvent::Event::IDLE_SLEEP);
239 recorder_.ExpectEntryMetric(entry1, UserActivity::kEventTypeName,
240 UserActivityEvent::Event::TIMEOUT);
241 recorder_.ExpectEntryMetric(entry1, UserActivity::kBatteryPercentName, 85);
242 recorder_.ExpectEntryMetric(entry1, UserActivity::kDeviceManagementName,
243 UserActivityEvent::Features::MANAGED);
244 recorder_.ExpectEntryMetric(entry1, UserActivity::kDeviceModeName,
245 UserActivityEvent::Features::CLAMSHELL);
246 recorder_.ExpectEntryMetric(entry1, UserActivity::kDeviceTypeName,
247 UserActivityEvent::Features::CHROMEBOOK);
248 recorder_.ExpectEntryMetric(entry1, UserActivity::kLastActivityDayName,
249 UserActivityEvent::Features::TUE);
250 recorder_.ExpectEntryMetric(entry1, UserActivity::kLastActivityTimeName, 2);
251 recorder_.ExpectEntryMetric(entry1, UserActivity::kLastUserActivityTimeName,
252 1);
253 EXPECT_FALSE(recorder_.EntryHasMetric(entry1, UserActivity::kOnBatteryName));
254 recorder_.ExpectEntryMetric(entry1, UserActivity::kRecentTimeActiveName, 20);
255 recorder_.ExpectEntryMetric(entry1, UserActivity::kScreenDimDelayName, 10);
256 recorder_.ExpectEntryMetric(entry1, UserActivity::kScreenDimToOffDelayName,
257 20);
258 recorder_.ExpectEntryMetric(entry1, UserActivity::kSequenceIdName, 2);
259 EXPECT_FALSE(
260 recorder_.EntryHasMetric(entry1, UserActivity::kTimeSinceLastKeyName));
261 recorder_.ExpectEntryMetric(entry1, UserActivity::kTimeSinceLastMouseName,
262 200);
263 recorder_.ExpectEntryMetric(entry1, UserActivity::kModelResponseName, 2);
264 recorder_.ExpectEntryMetric(entry1, UserActivity::kModelAppliedName, 0);
265 EXPECT_FALSE(recorder_.EntryHasMetric(
266 entry1, UserActivity::kModelDecisionThresholdName));
267 EXPECT_FALSE(recorder_.EntryHasMetric(
268 entry1, UserActivity::kModelInactivityScoreName));
269
270 EXPECT_EQ(0u, recorder_.GetEntriesByName(UserActivityId::kEntryName).size());
271 }
272
273 } // namespace ml
274 } // namespace power
275 } // namespace chromeos
276