diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/scheduler/renderer/user_model.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/platform/scheduler/renderer/user_model.cc | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/renderer/user_model.cc b/chromium/third_party/blink/renderer/platform/scheduler/renderer/user_model.cc new file mode 100644 index 00000000000..aeb7ba5ce40 --- /dev/null +++ b/chromium/third_party/blink/renderer/platform/scheduler/renderer/user_model.cc @@ -0,0 +1,168 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/scheduler/renderer/user_model.h" + +namespace blink { +namespace scheduler { + +UserModel::UserModel() + : pending_input_event_count_(0), + is_gesture_active_(false), + is_gesture_expected_(false) {} +UserModel::~UserModel() = default; + +void UserModel::DidStartProcessingInputEvent(blink::WebInputEvent::Type type, + const base::TimeTicks now) { + last_input_signal_time_ = now; + if (type == blink::WebInputEvent::kTouchStart || + type == blink::WebInputEvent::kGestureScrollBegin || + type == blink::WebInputEvent::kGesturePinchBegin) { + // Only update stats once per gesture. + if (!is_gesture_active_) + last_gesture_start_time_ = now; + + is_gesture_active_ = true; + } + + // We need to track continuous gestures seperatly for scroll detection + // because taps should not be confused with scrolls. + if (type == blink::WebInputEvent::kGestureScrollBegin || + type == blink::WebInputEvent::kGestureScrollEnd || + type == blink::WebInputEvent::kGestureScrollUpdate || + type == blink::WebInputEvent::kGestureFlingStart || + type == blink::WebInputEvent::kGestureFlingCancel || + type == blink::WebInputEvent::kGesturePinchBegin || + type == blink::WebInputEvent::kGesturePinchEnd || + type == blink::WebInputEvent::kGesturePinchUpdate) { + last_continuous_gesture_time_ = now; + } + + // If the gesture has ended, clear |is_gesture_active_| and record a UMA + // metric that tracks its duration. + if (type == blink::WebInputEvent::kGestureScrollEnd || + type == blink::WebInputEvent::kGesturePinchEnd || + type == blink::WebInputEvent::kGestureFlingStart || + type == blink::WebInputEvent::kTouchEnd) { + is_gesture_active_ = false; + } + + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), + "is_gesture_active", is_gesture_active_); + + pending_input_event_count_++; +} + +void UserModel::DidFinishProcessingInputEvent(const base::TimeTicks now) { + last_input_signal_time_ = now; + if (pending_input_event_count_ > 0) + pending_input_event_count_--; +} + +base::TimeDelta UserModel::TimeLeftInUserGesture(base::TimeTicks now) const { + base::TimeDelta escalated_priority_duration = + base::TimeDelta::FromMilliseconds(kGestureEstimationLimitMillis); + + // If the input event is still pending, go into input prioritized policy and + // check again later. + if (pending_input_event_count_ > 0) + return escalated_priority_duration; + if (last_input_signal_time_.is_null() || + last_input_signal_time_ + escalated_priority_duration < now) { + return base::TimeDelta(); + } + return last_input_signal_time_ + escalated_priority_duration - now; +} + +bool UserModel::IsGestureExpectedSoon( + const base::TimeTicks now, + base::TimeDelta* prediction_valid_duration) { + bool was_gesture_expected = is_gesture_expected_; + is_gesture_expected_ = + IsGestureExpectedSoonImpl(now, prediction_valid_duration); + + // Track when we start expecting a gesture so we can work out later if a + // gesture actually happened. + if (!was_gesture_expected && is_gesture_expected_) + last_gesture_expected_start_time_ = now; + return is_gesture_expected_; +} + +bool UserModel::IsGestureExpectedSoonImpl( + const base::TimeTicks now, + base::TimeDelta* prediction_valid_duration) const { + if (is_gesture_active_) { + if (IsGestureExpectedToContinue(now, prediction_valid_duration)) + return false; + *prediction_valid_duration = + base::TimeDelta::FromMilliseconds(kExpectSubsequentGestureMillis); + return true; + } else { + // If we've have a finished a gesture then a subsequent gesture is deemed + // likely. + base::TimeDelta expect_subsequent_gesture_for = + base::TimeDelta::FromMilliseconds(kExpectSubsequentGestureMillis); + if (last_continuous_gesture_time_.is_null() || + last_continuous_gesture_time_ + expect_subsequent_gesture_for <= now) { + return false; + } + *prediction_valid_duration = + last_continuous_gesture_time_ + expect_subsequent_gesture_for - now; + return true; + } +} + +bool UserModel::IsGestureExpectedToContinue( + const base::TimeTicks now, + base::TimeDelta* prediction_valid_duration) const { + if (!is_gesture_active_) + return false; + + base::TimeDelta median_gesture_duration = + base::TimeDelta::FromMilliseconds(kMedianGestureDurationMillis); + base::TimeTicks expected_gesture_end_time = + last_gesture_start_time_ + median_gesture_duration; + + if (expected_gesture_end_time > now) { + *prediction_valid_duration = expected_gesture_end_time - now; + return true; + } + return false; +} + +void UserModel::Reset(base::TimeTicks now) { + last_input_signal_time_ = base::TimeTicks(); + last_gesture_start_time_ = base::TimeTicks(); + last_continuous_gesture_time_ = base::TimeTicks(); + last_gesture_expected_start_time_ = base::TimeTicks(); + last_reset_time_ = now; + is_gesture_active_ = false; + is_gesture_expected_ = false; + pending_input_event_count_ = 0; +} + +void UserModel::AsValueInto(base::trace_event::TracedValue* state) const { + state->BeginDictionary("user_model"); + state->SetInteger("pending_input_event_count", pending_input_event_count_); + state->SetDouble( + "last_input_signal_time", + (last_input_signal_time_ - base::TimeTicks()).InMillisecondsF()); + state->SetDouble( + "last_gesture_start_time", + (last_gesture_start_time_ - base::TimeTicks()).InMillisecondsF()); + state->SetDouble( + "last_continuous_gesture_time", + (last_continuous_gesture_time_ - base::TimeTicks()).InMillisecondsF()); + state->SetDouble("last_gesture_expected_start_time", + (last_gesture_expected_start_time_ - base::TimeTicks()) + .InMillisecondsF()); + state->SetDouble("last_reset_time", + (last_reset_time_ - base::TimeTicks()).InMillisecondsF()); + state->SetBoolean("is_gesture_expected", is_gesture_expected_); + state->SetBoolean("is_gesture_active", is_gesture_active_); + state->EndDictionary(); +} + +} // namespace scheduler +} // namespace blink |