| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.chromium.latency.walt; |
| |
| import android.util.Log; |
| import android.view.MotionEvent; |
| |
| import java.lang.reflect.Method; |
| |
| /** |
| * A convenient representation of MotionEvent events |
| * - microsecond accuracy |
| * - no bundling of ACTION_MOVE events |
| */ |
| |
| public class UsMotionEvent { |
| |
| public long physicalTime, kernelTime, createTime; |
| public float x, y; |
| public int slot; |
| public int action; |
| public int num; |
| public String metadata; |
| public long baseTime; |
| |
| public boolean isOk = false; |
| |
| /** |
| * |
| * @param event - MotionEvent as received by the handler. |
| * @param baseTime - base time of the last clock sync. |
| */ |
| public UsMotionEvent(MotionEvent event, long baseTime) { |
| createTime = RemoteClockInfo.microTime() - baseTime; |
| this.baseTime = baseTime; |
| slot = -1; |
| kernelTime = getEventTimeMicro(event) - baseTime; |
| x = event.getX(); |
| y = event.getY(); |
| action = event.getAction(); |
| } |
| |
| public UsMotionEvent(MotionEvent event, long baseTime, int pos) { |
| createTime = RemoteClockInfo.microTime() - baseTime; |
| this.baseTime = baseTime; |
| slot = pos; |
| action = MotionEvent.ACTION_MOVE; // Only MOVE events get bundled with history |
| |
| kernelTime = getHistoricalEventTimeMicro(event, pos) - baseTime; |
| x = event.getHistoricalX(pos); |
| y = event.getHistoricalY(pos); |
| } |
| |
| public String getActionString() { |
| return actionToString(action); |
| } |
| |
| |
| public String toString() { |
| return String.format("%d %f %f", |
| kernelTime, x, y); |
| |
| } |
| |
| public String toStringLong() { |
| return String.format("Event: t=%d x=%.1f y=%.1f slot=%d num=%d %s", |
| kernelTime, x, y, slot, num, actionToString(action)); |
| |
| } |
| |
| // The MotionEvent.actionToString is not present before API 19 |
| public static String actionToString(int action) { |
| switch (action) { |
| case MotionEvent.ACTION_DOWN: |
| return "ACTION_DOWN"; |
| case MotionEvent.ACTION_UP: |
| return "ACTION_UP"; |
| case MotionEvent.ACTION_CANCEL: |
| return "ACTION_CANCEL"; |
| case MotionEvent.ACTION_OUTSIDE: |
| return "ACTION_OUTSIDE"; |
| case MotionEvent.ACTION_MOVE: |
| return "ACTION_MOVE"; |
| case MotionEvent.ACTION_HOVER_MOVE: |
| return "ACTION_HOVER_MOVE"; |
| case MotionEvent.ACTION_SCROLL: |
| return "ACTION_SCROLL"; |
| case MotionEvent.ACTION_HOVER_ENTER: |
| return "ACTION_HOVER_ENTER"; |
| case MotionEvent.ACTION_HOVER_EXIT: |
| return "ACTION_HOVER_EXIT"; |
| } |
| return "UNKNOWN_ACTION"; |
| } |
| |
| /** |
| MotionEvent.getEventTime() function only provides millisecond resolution. |
| There is a MotionEvent.getEventTimeNano() function but for some reason it |
| is hidden by @hide which means it can't be called directly. |
| Calling is via reflection. |
| |
| See: |
| http://stackoverflow.com/questions/17035271/what-does-hide-mean-in-the-android-source-code |
| */ |
| private long getEventTimeMicro(MotionEvent event) { |
| long t_nanos = -1; |
| try { |
| Class cls = Class.forName("android.view.MotionEvent"); |
| Method myTimeGetter = cls.getMethod("getEventTimeNano"); |
| t_nanos = (long) myTimeGetter.invoke(event); |
| } catch (Exception e) { |
| Log.i("WALT.MsMotionEvent", e.getMessage()); |
| } |
| |
| return t_nanos / 1000; |
| } |
| |
| private long getHistoricalEventTimeMicro(MotionEvent event, int pos) { |
| long t_nanos = -1; |
| try { |
| Class cls = Class.forName("android.view.MotionEvent"); |
| Method myTimeGetter = cls.getMethod("getHistoricalEventTimeNano", new Class[] {int.class}); |
| t_nanos = (long) myTimeGetter.invoke(event, new Object[]{pos}); |
| } catch (Exception e) { |
| Log.i("WALT.MsMotionEvent", e.getMessage()); |
| } |
| |
| return t_nanos / 1000; |
| } |
| |
| } |
| |