Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / renderer_host / input / motion_event_android.cc
blob6688a3d24dd7c5d23bbac302e1eeb6903511df77
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.
5 #include "content/browser/renderer_host/input/motion_event_android.h"
7 #include "base/android/jni_android.h"
8 #include "jni/MotionEvent_jni.h"
10 using base::android::AttachCurrentThread;
11 using namespace JNI_MotionEvent;
13 namespace content {
14 namespace {
16 int ToAndroidAction(MotionEventAndroid::Action action) {
17 switch (action) {
18 case MotionEventAndroid::ACTION_DOWN:
19 return ACTION_DOWN;
20 case MotionEventAndroid::ACTION_UP:
21 return ACTION_UP;
22 case MotionEventAndroid::ACTION_MOVE:
23 return ACTION_MOVE;
24 case MotionEventAndroid::ACTION_CANCEL:
25 return ACTION_CANCEL;
26 case MotionEventAndroid::ACTION_POINTER_DOWN:
27 return ACTION_POINTER_DOWN;
28 case MotionEventAndroid::ACTION_POINTER_UP:
29 return ACTION_POINTER_UP;
31 NOTREACHED() << "Invalid Android MotionEvent type for gesture detection: "
32 << action;
33 return ACTION_CANCEL;
36 MotionEventAndroid::Action FromAndroidAction(int android_action) {
37 switch (android_action) {
38 case ACTION_DOWN:
39 return MotionEventAndroid::ACTION_DOWN;
40 case ACTION_UP:
41 return MotionEventAndroid::ACTION_UP;
42 case ACTION_MOVE:
43 return MotionEventAndroid::ACTION_MOVE;
44 case ACTION_CANCEL:
45 return MotionEventAndroid::ACTION_CANCEL;
46 case ACTION_POINTER_DOWN:
47 return MotionEventAndroid::ACTION_POINTER_DOWN;
48 case ACTION_POINTER_UP:
49 return MotionEventAndroid::ACTION_POINTER_UP;
50 default:
51 NOTREACHED() << "Invalid Android MotionEvent type for gesture detection: "
52 << android_action;
54 return MotionEventAndroid::ACTION_CANCEL;
57 MotionEventAndroid::ToolType FromAndroidToolType(int android_tool_type) {
58 switch (android_tool_type) {
59 case TOOL_TYPE_UNKNOWN:
60 return MotionEventAndroid::TOOL_TYPE_UNKNOWN;
61 case TOOL_TYPE_FINGER:
62 return MotionEventAndroid::TOOL_TYPE_FINGER;
63 case TOOL_TYPE_STYLUS:
64 return MotionEventAndroid::TOOL_TYPE_STYLUS;
65 case TOOL_TYPE_MOUSE:
66 return MotionEventAndroid::TOOL_TYPE_MOUSE;
67 case TOOL_TYPE_ERASER:
68 return MotionEventAndroid::TOOL_TYPE_ERASER;
69 default:
70 NOTREACHED() << "Invalid Android MotionEvent tool type: "
71 << android_tool_type;
73 return MotionEventAndroid::TOOL_TYPE_UNKNOWN;
76 int FromAndroidButtonState(int button_state) {
77 int result = 0;
78 if ((button_state & BUTTON_BACK) != 0)
79 result |= MotionEventAndroid::BUTTON_BACK;
80 if ((button_state & BUTTON_FORWARD) != 0)
81 result |= MotionEventAndroid::BUTTON_FORWARD;
82 if ((button_state & BUTTON_PRIMARY) != 0)
83 result |= MotionEventAndroid::BUTTON_PRIMARY;
84 if ((button_state & BUTTON_SECONDARY) != 0)
85 result |= MotionEventAndroid::BUTTON_SECONDARY;
86 if ((button_state & BUTTON_TERTIARY) != 0)
87 result |= MotionEventAndroid::BUTTON_TERTIARY;
88 return result;
91 int64 ToAndroidTime(base::TimeTicks time) {
92 return (time - base::TimeTicks()).InMilliseconds();
95 base::TimeTicks FromAndroidTime(int64 time_ms) {
96 return base::TimeTicks() + base::TimeDelta::FromMilliseconds(time_ms);
99 } // namespace
101 MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
102 JNIEnv* env,
103 jobject event,
104 jlong time_ms,
105 jint android_action,
106 jint pointer_count,
107 jint history_size,
108 jint action_index,
109 jfloat pos_x_0_pixels,
110 jfloat pos_y_0_pixels,
111 jfloat pos_x_1_pixels,
112 jfloat pos_y_1_pixels,
113 jint pointer_id_0,
114 jint pointer_id_1,
115 jfloat touch_major_0_pixels,
116 jfloat touch_major_1_pixels,
117 jfloat raw_pos_x_pixels,
118 jfloat raw_pos_y_pixels,
119 jint android_tool_type_0,
120 jint android_tool_type_1,
121 jint android_button_state)
122 : cached_time_(FromAndroidTime(time_ms)),
123 cached_action_(FromAndroidAction(android_action)),
124 cached_pointer_count_(pointer_count),
125 cached_history_size_(history_size),
126 cached_action_index_(action_index),
127 cached_button_state_(FromAndroidButtonState(android_button_state)),
128 pix_to_dip_(pix_to_dip),
129 should_recycle_(false) {
130 DCHECK_GT(pointer_count, 0);
131 DCHECK_GE(history_size, 0);
133 event_.Reset(env, event);
134 DCHECK(event_.obj());
136 cached_positions_[0] = ToDips(gfx::PointF(pos_x_0_pixels, pos_y_0_pixels));
137 cached_positions_[1] = ToDips(gfx::PointF(pos_x_1_pixels, pos_y_1_pixels));
138 cached_pointer_ids_[0] = pointer_id_0;
139 cached_pointer_ids_[1] = pointer_id_1;
140 cached_touch_majors_[0] = ToDips(touch_major_0_pixels);
141 cached_touch_majors_[1] = ToDips(touch_major_1_pixels);
142 cached_raw_position_offset_ =
143 ToDips(gfx::PointF(raw_pos_x_pixels, raw_pos_y_pixels)) -
144 cached_positions_[0];
145 cached_tool_types_[0] = FromAndroidToolType(android_tool_type_0);
146 cached_tool_types_[1] = FromAndroidToolType(android_tool_type_1);
149 MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
150 JNIEnv* env,
151 jobject event)
152 : cached_time_(FromAndroidTime(Java_MotionEvent_getEventTime(env, event))),
153 cached_action_(
154 FromAndroidAction(Java_MotionEvent_getActionMasked(env, event))),
155 cached_pointer_count_(Java_MotionEvent_getPointerCount(env, event)),
156 cached_history_size_(Java_MotionEvent_getHistorySize(env, event)),
157 cached_action_index_(Java_MotionEvent_getActionIndex(env, event)),
158 cached_button_state_(
159 FromAndroidButtonState(Java_MotionEvent_getButtonState(env, event))),
160 pix_to_dip_(pix_to_dip),
161 should_recycle_(true) {
162 event_.Reset(env, event);
163 DCHECK(event_.obj());
165 for (size_t i = 0; i < MAX_POINTERS_TO_CACHE; ++i) {
166 if (i < cached_pointer_count_) {
167 cached_positions_[i] =
168 ToDips(gfx::PointF(Java_MotionEvent_getXF_I(env, event, i),
169 Java_MotionEvent_getYF_I(env, event, i)));
170 cached_pointer_ids_[i] = Java_MotionEvent_getPointerId(env, event, i);
171 cached_touch_majors_[i] =
172 ToDips(Java_MotionEvent_getTouchMajorF_I(env, event, i));
173 cached_tool_types_[i] =
174 FromAndroidToolType(Java_MotionEvent_getToolType(env, event, i));
175 } else {
176 cached_pointer_ids_[i] = 0;
177 cached_touch_majors_[i] = 0.f;
178 cached_tool_types_[i] = MotionEvent::TOOL_TYPE_UNKNOWN;
182 cached_raw_position_offset_ =
183 ToDips(gfx::PointF(Java_MotionEvent_getRawX(env, event),
184 Java_MotionEvent_getRawY(env, event))) -
185 cached_positions_[0];
188 MotionEventAndroid::MotionEventAndroid(const MotionEventAndroid& other)
189 : event_(Obtain(other)),
190 cached_time_(other.cached_time_),
191 cached_action_(other.cached_action_),
192 cached_pointer_count_(other.cached_pointer_count_),
193 cached_history_size_(other.cached_history_size_),
194 cached_action_index_(other.cached_action_index_),
195 cached_raw_position_offset_(other.cached_raw_position_offset_),
196 cached_button_state_(other.cached_button_state_),
197 pix_to_dip_(other.pix_to_dip_),
198 should_recycle_(true) {
199 DCHECK(event_.obj());
200 for (size_t i = 0; i < MAX_POINTERS_TO_CACHE; ++i) {
201 cached_positions_[i] = other.cached_positions_[i];
202 cached_pointer_ids_[i] = other.cached_pointer_ids_[i];
203 cached_touch_majors_[i] = other.cached_touch_majors_[i];
204 cached_tool_types_[i] = other.cached_tool_types_[i];
208 MotionEventAndroid::~MotionEventAndroid() {
209 if (should_recycle_)
210 Java_MotionEvent_recycle(AttachCurrentThread(), event_.obj());
213 int MotionEventAndroid::GetId() const {
214 return 0;
217 MotionEventAndroid::Action MotionEventAndroid::GetAction() const {
218 return cached_action_;
221 int MotionEventAndroid::GetActionIndex() const {
222 return cached_action_index_;
225 size_t MotionEventAndroid::GetPointerCount() const {
226 return cached_pointer_count_;
229 int MotionEventAndroid::GetPointerId(size_t pointer_index) const {
230 DCHECK_LT(pointer_index, cached_pointer_count_);
231 if (pointer_index < MAX_POINTERS_TO_CACHE)
232 return cached_pointer_ids_[pointer_index];
233 return Java_MotionEvent_getPointerId(
234 AttachCurrentThread(), event_.obj(), pointer_index);
237 float MotionEventAndroid::GetX(size_t pointer_index) const {
238 DCHECK_LT(pointer_index, cached_pointer_count_);
239 if (pointer_index < MAX_POINTERS_TO_CACHE)
240 return cached_positions_[pointer_index].x();
241 return ToDips(Java_MotionEvent_getXF_I(
242 AttachCurrentThread(), event_.obj(), pointer_index));
245 float MotionEventAndroid::GetY(size_t pointer_index) const {
246 DCHECK_LT(pointer_index, cached_pointer_count_);
247 if (pointer_index < MAX_POINTERS_TO_CACHE)
248 return cached_positions_[pointer_index].y();
249 return ToDips(Java_MotionEvent_getYF_I(
250 AttachCurrentThread(), event_.obj(), pointer_index));
253 float MotionEventAndroid::GetRawX(size_t pointer_index) const {
254 return GetX(pointer_index) + cached_raw_position_offset_.x();
257 float MotionEventAndroid::GetRawY(size_t pointer_index) const {
258 return GetY(pointer_index) + cached_raw_position_offset_.y();
261 float MotionEventAndroid::GetTouchMajor(size_t pointer_index) const {
262 DCHECK_LT(pointer_index, cached_pointer_count_);
263 if (pointer_index < MAX_POINTERS_TO_CACHE)
264 return cached_touch_majors_[pointer_index];
265 return ToDips(Java_MotionEvent_getTouchMajorF_I(
266 AttachCurrentThread(), event_.obj(), pointer_index));
269 float MotionEventAndroid::GetPressure(size_t pointer_index) const {
270 DCHECK_LT(pointer_index, cached_pointer_count_);
271 return Java_MotionEvent_getPressureF_I(
272 AttachCurrentThread(), event_.obj(), pointer_index);
275 base::TimeTicks MotionEventAndroid::GetEventTime() const {
276 return cached_time_;
279 size_t MotionEventAndroid::GetHistorySize() const {
280 return cached_history_size_;
283 base::TimeTicks MotionEventAndroid::GetHistoricalEventTime(
284 size_t historical_index) const {
285 return FromAndroidTime(Java_MotionEvent_getHistoricalEventTime(
286 AttachCurrentThread(), event_.obj(), historical_index));
289 float MotionEventAndroid::GetHistoricalTouchMajor(
290 size_t pointer_index,
291 size_t historical_index) const {
292 return ToDips(Java_MotionEvent_getHistoricalTouchMajorF_I_I(
293 AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
296 float MotionEventAndroid::GetHistoricalX(size_t pointer_index,
297 size_t historical_index) const {
298 return ToDips(Java_MotionEvent_getHistoricalXF_I_I(
299 AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
302 float MotionEventAndroid::GetHistoricalY(size_t pointer_index,
303 size_t historical_index) const {
304 return ToDips(Java_MotionEvent_getHistoricalYF_I_I(
305 AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
308 ui::MotionEvent::ToolType MotionEventAndroid::GetToolType(
309 size_t pointer_index) const {
310 DCHECK_LT(pointer_index, cached_pointer_count_);
311 if (pointer_index < MAX_POINTERS_TO_CACHE)
312 return cached_tool_types_[pointer_index];
313 return FromAndroidToolType(Java_MotionEvent_getToolType(
314 AttachCurrentThread(), event_.obj(), pointer_index));
317 int MotionEventAndroid::GetButtonState() const {
318 return cached_button_state_;
321 scoped_ptr<ui::MotionEvent> MotionEventAndroid::Clone() const {
322 return scoped_ptr<MotionEvent>(new MotionEventAndroid(*this));
325 scoped_ptr<ui::MotionEvent> MotionEventAndroid::Cancel() const {
326 // The input coordinates to |MotionEventAndroid| are always in device pixels,
327 // but the cached coordinates are in DIPs.
328 const gfx::PointF position_pixels =
329 gfx::ScalePoint(cached_positions_[0], 1.f / pix_to_dip_);
330 return scoped_ptr<MotionEvent>(
331 new MotionEventAndroid(pix_to_dip_,
332 AttachCurrentThread(),
333 Obtain(GetDownTime(),
334 GetEventTime(),
335 MotionEventAndroid::ACTION_CANCEL,
336 position_pixels.x(),
337 position_pixels.y()).obj()));
340 float MotionEventAndroid::GetTouchMinor(size_t pointer_index) const {
341 return ToDips(Java_MotionEvent_getTouchMinorF_I(
342 AttachCurrentThread(), event_.obj(), pointer_index));
345 float MotionEventAndroid::GetOrientation() const {
346 return Java_MotionEvent_getOrientationF(AttachCurrentThread(), event_.obj());
349 base::TimeTicks MotionEventAndroid::GetDownTime() const {
350 return FromAndroidTime(
351 Java_MotionEvent_getDownTime(AttachCurrentThread(), event_.obj()));
354 float MotionEventAndroid::ToDips(float pixels) const {
355 return pixels * pix_to_dip_;
358 gfx::PointF MotionEventAndroid::ToDips(const gfx::PointF& point_pixels) const {
359 return gfx::ScalePoint(point_pixels, pix_to_dip_);
362 // static
363 bool MotionEventAndroid::RegisterMotionEventAndroid(JNIEnv* env) {
364 return JNI_MotionEvent::RegisterNativesImpl(env);
367 // static
368 base::android::ScopedJavaLocalRef<jobject> MotionEventAndroid::Obtain(
369 const MotionEventAndroid& event) {
370 return Java_MotionEvent_obtainAVME_AVME(AttachCurrentThread(),
371 event.event_.obj());
374 // static
375 base::android::ScopedJavaLocalRef<jobject> MotionEventAndroid::Obtain(
376 base::TimeTicks down_time,
377 base::TimeTicks event_time,
378 Action action,
379 float x_pixels,
380 float y_pixels) {
381 return Java_MotionEvent_obtainAVME_J_J_I_F_F_I(AttachCurrentThread(),
382 ToAndroidTime(down_time),
383 ToAndroidTime(event_time),
384 ToAndroidAction(action),
385 x_pixels,
386 y_pixels,
390 } // namespace content