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/events/gesture_detection/gesture_touch_uma_histogram.h"
6
7#include "base/metrics/histogram.h"
8
9namespace ui {
10
11GestureTouchUMAHistogram::GestureTouchUMAHistogram()
12    : max_distance_from_start_squared_(0), is_single_finger_(true) {
13}
14
15GestureTouchUMAHistogram::~GestureTouchUMAHistogram() {
16}
17
18void GestureTouchUMAHistogram::RecordGestureEvent(
19    const GestureEventData& gesture) {
20  UMA_HISTOGRAM_ENUMERATION(
21      "Event.GestureCreated", UMAEventTypeFromEvent(gesture), UMA_ET_COUNT);
22}
23
24void GestureTouchUMAHistogram::RecordTouchEvent(const MotionEvent& event) {
25  if (event.GetAction() == MotionEvent::ACTION_DOWN) {
26    start_time_ = event.GetEventTime();
27    start_touch_position_ = gfx::Point(event.GetX(), event.GetY());
28    is_single_finger_ = true;
29    max_distance_from_start_squared_ = 0;
30  } else if (event.GetAction() == MotionEvent::ACTION_MOVE &&
31             is_single_finger_) {
32    float cur_dist = (start_touch_position_ -
33                      gfx::Point(event.GetX(), event.GetY())).LengthSquared();
34    if (cur_dist > max_distance_from_start_squared_)
35      max_distance_from_start_squared_ = cur_dist;
36  } else {
37    if (event.GetAction() == MotionEvent::ACTION_UP && is_single_finger_) {
38      UMA_HISTOGRAM_CUSTOM_COUNTS(
39          "Event.TouchMaxDistance",
40          static_cast<int>(sqrt(max_distance_from_start_squared_)),
41          0,
42          1500,
43          50);
44
45      base::TimeDelta duration = event.GetEventTime() - start_time_;
46      UMA_HISTOGRAM_TIMES("Event.TouchDuration", duration);
47    }
48    is_single_finger_ = false;
49  }
50}
51
52UMAEventType GestureTouchUMAHistogram::UMAEventTypeFromEvent(
53    const GestureEventData& gesture) {
54  switch (gesture.type()) {
55    case ET_TOUCH_RELEASED:
56      return UMA_ET_TOUCH_RELEASED;
57    case ET_TOUCH_PRESSED:
58      return UMA_ET_TOUCH_PRESSED;
59    case ET_TOUCH_MOVED:
60      return UMA_ET_TOUCH_MOVED;
61    case ET_TOUCH_CANCELLED:
62      return UMA_ET_TOUCH_CANCELLED;
63    case ET_GESTURE_SCROLL_BEGIN:
64      return UMA_ET_GESTURE_SCROLL_BEGIN;
65    case ET_GESTURE_SCROLL_END:
66      return UMA_ET_GESTURE_SCROLL_END;
67    case ET_GESTURE_SCROLL_UPDATE: {
68      int touch_points = gesture.details.touch_points();
69      if (touch_points == 1)
70        return UMA_ET_GESTURE_SCROLL_UPDATE;
71      else if (touch_points == 2)
72        return UMA_ET_GESTURE_SCROLL_UPDATE_2;
73      else if (touch_points == 3)
74        return UMA_ET_GESTURE_SCROLL_UPDATE_3;
75      return UMA_ET_GESTURE_SCROLL_UPDATE_4P;
76    }
77    case ET_GESTURE_TAP: {
78      int tap_count = gesture.details.tap_count();
79      if (tap_count == 1)
80        return UMA_ET_GESTURE_TAP;
81      if (tap_count == 2)
82        return UMA_ET_GESTURE_DOUBLE_TAP;
83      if (tap_count == 3)
84        return UMA_ET_GESTURE_TRIPLE_TAP;
85      NOTREACHED() << "Received tap with tapcount " << tap_count;
86      return UMA_ET_UNKNOWN;
87    }
88    case ET_GESTURE_TAP_DOWN:
89      return UMA_ET_GESTURE_TAP_DOWN;
90    case ET_GESTURE_BEGIN:
91      return UMA_ET_GESTURE_BEGIN;
92    case ET_GESTURE_END:
93      return UMA_ET_GESTURE_END;
94    case ET_GESTURE_TWO_FINGER_TAP:
95      return UMA_ET_GESTURE_TWO_FINGER_TAP;
96    case ET_GESTURE_PINCH_BEGIN:
97      return UMA_ET_GESTURE_PINCH_BEGIN;
98    case ET_GESTURE_PINCH_END:
99      return UMA_ET_GESTURE_PINCH_END;
100    case ET_GESTURE_PINCH_UPDATE: {
101      int touch_points = gesture.details.touch_points();
102      if (touch_points >= 4)
103        return UMA_ET_GESTURE_PINCH_UPDATE_4P;
104      else if (touch_points == 3)
105        return UMA_ET_GESTURE_PINCH_UPDATE_3;
106      return UMA_ET_GESTURE_PINCH_UPDATE;
107    }
108    case ET_GESTURE_LONG_PRESS:
109      return UMA_ET_GESTURE_LONG_PRESS;
110    case ET_GESTURE_LONG_TAP:
111      return UMA_ET_GESTURE_LONG_TAP;
112    case ET_GESTURE_SWIPE: {
113      int touch_points = gesture.details.touch_points();
114      if (touch_points == 1)
115        return UMA_ET_GESTURE_SWIPE_1;
116      else if (touch_points == 2)
117        return UMA_ET_GESTURE_SWIPE_2;
118      else if (touch_points == 3)
119        return UMA_ET_GESTURE_SWIPE_3;
120      return UMA_ET_GESTURE_SWIPE_4P;
121    }
122    case ET_GESTURE_WIN8_EDGE_SWIPE:
123      return UMA_ET_GESTURE_WIN8_EDGE_SWIPE;
124    case ET_GESTURE_TAP_CANCEL:
125      return UMA_ET_GESTURE_TAP_CANCEL;
126    case ET_GESTURE_SHOW_PRESS:
127      return UMA_ET_GESTURE_SHOW_PRESS;
128    case ET_SCROLL:
129      return UMA_ET_SCROLL;
130    case ET_SCROLL_FLING_START:
131      return UMA_ET_SCROLL_FLING_START;
132    case ET_SCROLL_FLING_CANCEL:
133      return UMA_ET_SCROLL_FLING_CANCEL;
134    case ET_GESTURE_TAP_UNCONFIRMED:
135      return UMA_ET_GESTURE_TAP_UNCONFIRMED;
136    case ET_GESTURE_DOUBLE_TAP:
137      return UMA_ET_GESTURE_DOUBLE_TAP;
138    default:
139      NOTREACHED();
140      return UMA_ET_UNKNOWN;
141  }
142}
143
144}  //  namespace ui
145