OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/touch/touch_uma.h" | 5 #include "ash/touch/touch_uma.h" |
6 | 6 |
| 7 #include "ash/shell_delegate.h" |
7 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
8 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
9 #include "ui/aura/event.h" | 10 #include "ui/aura/event.h" |
10 #include "ui/aura/root_window.h" | 11 #include "ui/aura/root_window.h" |
11 #include "ui/aura/window.h" | 12 #include "ui/aura/window.h" |
| 13 #include "ui/aura/window_property.h" |
12 | 14 |
13 namespace { | 15 namespace { |
14 | 16 |
15 enum GestureActionType { | 17 enum GestureActionType { |
16 GESTURE_UNKNOWN, | 18 GESTURE_UNKNOWN, |
17 GESTURE_OMNIBOX_PINCH, | 19 GESTURE_OMNIBOX_PINCH, |
18 GESTURE_OMNIBOX_SCROLL, | 20 GESTURE_OMNIBOX_SCROLL, |
19 GESTURE_TABSTRIP_PINCH, | 21 GESTURE_TABSTRIP_PINCH, |
20 GESTURE_TABSTRIP_SCROLL, | 22 GESTURE_TABSTRIP_SCROLL, |
21 GESTURE_BEZEL_SCROLL, | 23 GESTURE_BEZEL_SCROLL, |
22 GESTURE_DESKTOP_SCROLL, | 24 GESTURE_DESKTOP_SCROLL, |
23 GESTURE_DESKTOP_PINCH, | 25 GESTURE_DESKTOP_PINCH, |
24 GESTURE_WEBPAGE_PINCH, | 26 GESTURE_WEBPAGE_PINCH, |
| 27 GESTURE_WEBPAGE_SCROLL, |
25 // NOTE: Add new action types only immediately above this line. Also, make sure | 28 // NOTE: Add new action types only immediately above this line. Also, make sure |
26 // the enum list in tools/histogram/histograms.xml is updated with any change in | 29 // the enum list in tools/histogram/histograms.xml is updated with any change in |
27 // here. | 30 // here. |
28 GESTURE_ACTION_COUNT | 31 GESTURE_ACTION_COUNT |
29 }; | 32 }; |
30 | 33 |
31 enum UMAEventType { | 34 enum UMAEventType { |
32 UMA_ET_UNKNOWN, | 35 UMA_ET_UNKNOWN, |
33 UMA_ET_TOUCH_RELEASED, | 36 UMA_ET_TOUCH_RELEASED, |
34 UMA_ET_TOUCH_PRESSED, | 37 UMA_ET_TOUCH_PRESSED, |
(...skipping 22 matching lines...) Expand all Loading... |
57 UMA_ET_GESTURE_SCROLL_UPDATE_2, | 60 UMA_ET_GESTURE_SCROLL_UPDATE_2, |
58 UMA_ET_GESTURE_SCROLL_UPDATE_3, | 61 UMA_ET_GESTURE_SCROLL_UPDATE_3, |
59 UMA_ET_GESTURE_SCROLL_UPDATE_4P, | 62 UMA_ET_GESTURE_SCROLL_UPDATE_4P, |
60 UMA_ET_GESTURE_PINCH_UPDATE_3, | 63 UMA_ET_GESTURE_PINCH_UPDATE_3, |
61 UMA_ET_GESTURE_PINCH_UPDATE_4P, | 64 UMA_ET_GESTURE_PINCH_UPDATE_4P, |
62 // NOTE: Add new event types only immediately above this line. Make sure to | 65 // NOTE: Add new event types only immediately above this line. Make sure to |
63 // update the enum list in tools/histogram/histograms.xml accordingly. | 66 // update the enum list in tools/histogram/histograms.xml accordingly. |
64 UMA_ET_COUNT | 67 UMA_ET_COUNT |
65 }; | 68 }; |
66 | 69 |
| 70 struct WindowTouchDetails { |
| 71 // Move and start times of the touch points. The key is the touch-id. |
| 72 std::map<int, base::TimeDelta> last_move_time_; |
| 73 std::map<int, base::TimeDelta> last_start_time_; |
| 74 |
| 75 // The last position of the touch points. |
| 76 std::map<int, gfx::Point> last_touch_position_; |
| 77 |
| 78 // Last time-stamp of the last touch-end event. |
| 79 base::TimeDelta last_release_time_; |
| 80 |
| 81 // Stores the time of the last touch released on this window (if there was a |
| 82 // multi-touch gesture on the window, then this is the release-time of the |
| 83 // last touch on the window). |
| 84 base::TimeDelta last_mt_time_; |
| 85 }; |
| 86 |
| 87 DEFINE_OWNED_WINDOW_PROPERTY_KEY(WindowTouchDetails, |
| 88 kWindowTouchDetails, |
| 89 NULL); |
| 90 |
67 GestureActionType FindGestureActionType(aura::Window* window, | 91 GestureActionType FindGestureActionType(aura::Window* window, |
68 const aura::GestureEvent& event) { | 92 const aura::GestureEvent& event) { |
69 if (!window || window->GetRootWindow() == window) { | 93 if (!window || window->GetRootWindow() == window) { |
70 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) | 94 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) |
71 return GESTURE_BEZEL_SCROLL; | 95 return GESTURE_BEZEL_SCROLL; |
72 return GESTURE_UNKNOWN; | 96 return GESTURE_UNKNOWN; |
73 } | 97 } |
74 | 98 |
75 std::string name = window ? window->name() : std::string(); | 99 std::string name = window ? window->name() : std::string(); |
76 | 100 |
77 const char kDesktopBackgroundView[] = "DesktopBackgroundView"; | 101 const char kDesktopBackgroundView[] = "DesktopBackgroundView"; |
78 if (name == kDesktopBackgroundView) { | 102 if (name == kDesktopBackgroundView) { |
79 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) | 103 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) |
80 return GESTURE_DESKTOP_SCROLL; | 104 return GESTURE_DESKTOP_SCROLL; |
81 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) | 105 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) |
82 return GESTURE_DESKTOP_PINCH; | 106 return GESTURE_DESKTOP_PINCH; |
83 return GESTURE_UNKNOWN; | 107 return GESTURE_UNKNOWN; |
84 } | 108 } |
85 | 109 |
86 const char kWebPage[] = "RenderWidgetHostViewAura"; | 110 const char kWebPage[] = "RenderWidgetHostViewAura"; |
87 if (name == kWebPage) { | 111 if (name == kWebPage) { |
88 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) | 112 if (event.type() == ui::ET_GESTURE_PINCH_BEGIN) |
89 return GESTURE_WEBPAGE_PINCH; | 113 return GESTURE_WEBPAGE_PINCH; |
| 114 if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) |
| 115 return GESTURE_WEBPAGE_SCROLL; |
90 return GESTURE_UNKNOWN; | 116 return GESTURE_UNKNOWN; |
91 } | 117 } |
92 | 118 |
93 views::Widget* widget = views::Widget::GetWidgetForNativeView(window); | 119 views::Widget* widget = views::Widget::GetWidgetForNativeView(window); |
94 if (!widget) | 120 if (!widget) |
95 return GESTURE_UNKNOWN; | 121 return GESTURE_UNKNOWN; |
96 | 122 |
97 views::View* view = widget->GetRootView()-> | 123 views::View* view = widget->GetRootView()-> |
98 GetEventHandlerForPoint(event.location()); | 124 GetEventHandlerForPoint(event.location()); |
99 if (!view) | 125 if (!view) |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 UMA_HISTOGRAM_ENUMERATION("Ash.GestureCreated", | 239 UMA_HISTOGRAM_ENUMERATION("Ash.GestureCreated", |
214 UMAEventTypeFromEvent(event), | 240 UMAEventTypeFromEvent(event), |
215 UMA_ET_COUNT); | 241 UMA_ET_COUNT); |
216 | 242 |
217 GestureActionType action = FindGestureActionType(target, event); | 243 GestureActionType action = FindGestureActionType(target, event); |
218 if (action != GESTURE_UNKNOWN) { | 244 if (action != GESTURE_UNKNOWN) { |
219 UMA_HISTOGRAM_ENUMERATION("Ash.GestureTarget", | 245 UMA_HISTOGRAM_ENUMERATION("Ash.GestureTarget", |
220 action, | 246 action, |
221 GESTURE_ACTION_COUNT); | 247 GESTURE_ACTION_COUNT); |
222 } | 248 } |
| 249 |
| 250 if (event.type() == ui::ET_GESTURE_END && |
| 251 event.details().touch_points() == 2) { |
| 252 WindowTouchDetails* details = target->GetProperty(kWindowTouchDetails); |
| 253 CHECK(details) << "Window received gesture but no touch events?"; |
| 254 details->last_mt_time_ = event.time_stamp(); |
| 255 } |
223 } | 256 } |
224 | 257 |
225 void TouchUMA::RecordTouchEvent(aura::Window* target, | 258 void TouchUMA::RecordTouchEvent(aura::Window* target, |
226 const aura::TouchEvent& event) { | 259 const aura::TouchEvent& event) { |
227 // TODO(sad|rjkroege): Figure out what to do (heat map?). | 260 UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchRadius", |
| 261 static_cast<int>(std::max(event.radius_x(), event.radius_y())), |
| 262 1, 500, 100); |
| 263 |
| 264 WindowTouchDetails* details = target->GetProperty(kWindowTouchDetails); |
| 265 if (!details) { |
| 266 details = new WindowTouchDetails; |
| 267 target->SetProperty(kWindowTouchDetails, details); |
| 268 } |
| 269 |
| 270 if (event.type() == ui::ET_TOUCH_PRESSED) { |
| 271 Shell::GetInstance()->delegate()->RecordUserMetricsAction( |
| 272 UMA_TOUCHSCREEN_TAP_DOWN); |
| 273 |
| 274 details->last_start_time_[event.touch_id()] = event.time_stamp(); |
| 275 details->last_touch_position_[event.touch_id()] = event.location(); |
| 276 |
| 277 if (details->last_release_time_.ToInternalValue()) { |
| 278 // Measuring the interval between a touch-release and the next |
| 279 // touch-start is probably less useful when doing multi-touch (e.g. |
| 280 // gestures, or multi-touch friendly apps). So count this only if the user |
| 281 // hasn't done any multi-touch during the last 30 seconds. |
| 282 base::TimeDelta diff = event.time_stamp() - details->last_mt_time_; |
| 283 if (diff.InSeconds() > 30) { |
| 284 base::TimeDelta gap = event.time_stamp() - details->last_release_time_; |
| 285 UMA_HISTOGRAM_COUNTS_10000("Ash.TouchStartAfterEnd", |
| 286 gap.InMilliseconds()); |
| 287 } |
| 288 } |
| 289 } else if (event.type() == ui::ET_TOUCH_RELEASED) { |
| 290 if (details->last_start_time_.count(event.touch_id())) { |
| 291 base::TimeDelta duration = event.time_stamp() - |
| 292 details->last_start_time_[event.touch_id()]; |
| 293 UMA_HISTOGRAM_COUNTS_100("Ash.TouchDuration", duration.InMilliseconds()); |
| 294 } |
| 295 details->last_start_time_.erase(event.touch_id()); |
| 296 details->last_move_time_.erase(event.touch_id()); |
| 297 details->last_touch_position_.erase(event.touch_id()); |
| 298 details->last_release_time_ = event.time_stamp(); |
| 299 } else if (event.type() == ui::ET_TOUCH_MOVED) { |
| 300 int distance = 0; |
| 301 if (details->last_touch_position_.count(event.touch_id())) { |
| 302 gfx::Point lastpos = details->last_touch_position_[event.touch_id()]; |
| 303 distance = abs(lastpos.x() - event.x()) + abs(lastpos.y() - event.y()); |
| 304 } |
| 305 |
| 306 if (details->last_move_time_.count(event.touch_id())) { |
| 307 base::TimeDelta move_delay = event.time_stamp() - |
| 308 details->last_move_time_[event.touch_id()]; |
| 309 UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchMoveInterval", |
| 310 move_delay.InMilliseconds(), |
| 311 1, 50, 25); |
| 312 } |
| 313 |
| 314 UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchMoveSteps", distance, 1, 1000, 50); |
| 315 |
| 316 details->last_move_time_[event.touch_id()] = event.time_stamp(); |
| 317 details->last_touch_position_[event.touch_id()] = event.location(); |
| 318 } |
228 } | 319 } |
229 | 320 |
230 } // namespace internal | 321 } // namespace internal |
231 } // namespace ash | 322 } // namespace ash |
OLD | NEW |