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