1 // Copyright 2014 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 "ui/base/user_activity/user_activity_detector.h" 6 7 #include "base/format_macros.h" 8 #include "base/logging.h" 9 #include "base/strings/stringprintf.h" 10 #include "build/build_config.h" 11 #include "ui/base/user_activity/user_activity_observer.h" 12 #include "ui/events/event_utils.h" 13 #include "ui/events/platform/platform_event_source.h" 14 15 namespace ui { 16 17 namespace { 18 19 UserActivityDetector* g_instance = nullptr; 20 21 // Returns a string describing |event|. GetEventDebugString(const ui::Event * event)22std::string GetEventDebugString(const ui::Event* event) { 23 std::string details = base::StringPrintf( 24 "type=%d name=%s flags=%d time=%" PRId64, event->type(), event->GetName(), 25 event->flags(), 26 (event->time_stamp() - base::TimeTicks()).InMilliseconds()); 27 28 if (event->IsKeyEvent()) { 29 details += base::StringPrintf(" key_code=%d", 30 static_cast<const ui::KeyEvent*>(event)->key_code()); 31 } else if (event->IsMouseEvent() || event->IsTouchEvent() || 32 event->IsGestureEvent()) { 33 details += base::StringPrintf(" location=%s", 34 static_cast<const ui::LocatedEvent*>( 35 event)->location().ToString().c_str()); 36 } 37 38 return details; 39 } 40 41 } // namespace 42 43 const int UserActivityDetector::kNotifyIntervalMs = 200; 44 45 // Too low and mouse events generated at the tail end of reconfiguration 46 // will be reported as user activity and turn the screen back on; too high 47 // and we'll ignore legitimate activity. 48 const int UserActivityDetector::kDisplayPowerChangeIgnoreMouseMs = 1000; 49 UserActivityDetector()50UserActivityDetector::UserActivityDetector() { 51 CHECK(!g_instance); 52 g_instance = this; 53 54 PlatformEventSource* platform_event_source = 55 PlatformEventSource::GetInstance(); 56 if (platform_event_source) 57 platform_event_source->AddPlatformEventObserver(this); 58 } 59 ~UserActivityDetector()60UserActivityDetector::~UserActivityDetector() { 61 PlatformEventSource* platform_event_source = 62 PlatformEventSource::GetInstance(); 63 if (platform_event_source) 64 platform_event_source->RemovePlatformEventObserver(this); 65 g_instance = nullptr; 66 } 67 68 // static Get()69UserActivityDetector* UserActivityDetector::Get() { 70 return g_instance; 71 } 72 HasObserver(const UserActivityObserver * observer) const73bool UserActivityDetector::HasObserver( 74 const UserActivityObserver* observer) const { 75 return observers_.HasObserver(observer); 76 } 77 AddObserver(UserActivityObserver * observer)78void UserActivityDetector::AddObserver(UserActivityObserver* observer) { 79 observers_.AddObserver(observer); 80 } 81 RemoveObserver(UserActivityObserver * observer)82void UserActivityDetector::RemoveObserver(UserActivityObserver* observer) { 83 observers_.RemoveObserver(observer); 84 } 85 OnDisplayPowerChanging()86void UserActivityDetector::OnDisplayPowerChanging() { 87 honor_mouse_events_time_ = GetCurrentTime() + 88 base::TimeDelta::FromMilliseconds(kDisplayPowerChangeIgnoreMouseMs); 89 } 90 HandleExternalUserActivity()91void UserActivityDetector::HandleExternalUserActivity() { 92 HandleActivity(nullptr); 93 } 94 DidProcessEvent(const PlatformEvent & platform_event)95void UserActivityDetector::DidProcessEvent( 96 const PlatformEvent& platform_event) { 97 std::unique_ptr<ui::Event> event(ui::EventFromNative(platform_event)); 98 ProcessReceivedEvent(event.get()); 99 } 100 GetCurrentTime() const101base::TimeTicks UserActivityDetector::GetCurrentTime() const { 102 return !now_for_test_.is_null() ? now_for_test_ : base::TimeTicks::Now(); 103 } 104 ProcessReceivedEvent(const ui::Event * event)105void UserActivityDetector::ProcessReceivedEvent(const ui::Event* event) { 106 if (!event) 107 return; 108 109 if (event->IsMouseEvent() || event->IsMouseWheelEvent()) { 110 if (event->flags() & ui::EF_IS_SYNTHESIZED) 111 return; 112 if (!honor_mouse_events_time_.is_null() 113 && GetCurrentTime() < honor_mouse_events_time_) 114 return; 115 } 116 117 HandleActivity(event); 118 } 119 HandleActivity(const ui::Event * event)120void UserActivityDetector::HandleActivity(const ui::Event* event) { 121 base::TimeTicks now = GetCurrentTime(); 122 last_activity_time_ = now; 123 last_activity_name_ = event ? event->GetName() : std::string(); 124 if (last_observer_notification_time_.is_null() || 125 (now - last_observer_notification_time_).InMillisecondsF() >= 126 kNotifyIntervalMs) { 127 if (VLOG_IS_ON(1) && event) 128 VLOG(1) << "Reporting user activity: " << GetEventDebugString(event); 129 for (UserActivityObserver& observer : observers_) 130 observer.OnUserActivity(event); 131 last_observer_notification_time_ = now; 132 } 133 } 134 135 } // namespace ui 136