1 // Copyright 2019 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 "third_party/blink/renderer/platform/widget/input/momentum_scroll_jank_tracker.h"
6 
7 #include "base/metrics/histogram_functions.h"
8 #include "third_party/blink/renderer/platform/widget/input/event_with_callback.h"
9 
10 namespace blink {
11 
12 constexpr base::TimeDelta MomentumScrollJankTracker::kRecentEventCutoff;
13 
~MomentumScrollJankTracker()14 MomentumScrollJankTracker::~MomentumScrollJankTracker() {
15   // Don't log if this scroll had no momentum input (after the first event).
16   if (total_event_count_ == 0)
17     return;
18 
19   // We want to target 0 janks, so round our percentages up so that a single
20   // jank over a large number of frames doesn't get lost.
21   // Don't worry about overflow as we'd need a gesture > 100hrs long to hit,
22   // and the downside is an incorrect metric.
23   uint32_t rounding_factor = total_event_count_ - 1;
24   uint32_t jank_percentage =
25       (jank_count_ * 100 + rounding_factor) / total_event_count_;
26 
27   base::UmaHistogramPercentageObsoleteDoNotUse(
28       "Renderer4.MomentumScrollJankPercentage", jank_percentage);
29 }
30 
OnDispatchedInputEvent(EventWithCallback * event_with_callback,const base::TimeTicks & now)31 void MomentumScrollJankTracker::OnDispatchedInputEvent(
32     EventWithCallback* event_with_callback,
33     const base::TimeTicks& now) {
34   DCHECK_EQ(event_with_callback->event().GetType(),
35             WebGestureEvent::Type::kGestureScrollUpdate);
36 
37   const auto& gesture_event =
38       static_cast<const WebGestureEvent&>(event_with_callback->event());
39 
40   // If the scroll is not in the momentum phase, it's driven by user input,
41   // which happens at a higher frequency. Ignore this.
42   if (gesture_event.data.scroll_update.inertial_phase !=
43       WebGestureEvent::InertialPhaseState::kMomentum) {
44     return;
45   }
46 
47   // Ignore the first momentum input event, as this may happen out-of band
48   // with BeginFrame, and may be coalesced in a non-jank scenario.
49   // TODO(ericrk): Add a metric to track jank in the transition from user
50   // to momentum input.
51   if (!seen_first_momentum_input_) {
52     seen_first_momentum_input_ = true;
53     return;
54   }
55 
56   total_event_count_ += event_with_callback->coalesced_count();
57 
58   jank_count_ +=
59       event_with_callback->coalesced_count() - kExpectedMomentumEventsPerFrame;
60 }
61 
62 }  // namespace blink
63