Java tutorial
/** * AlphaMale for web Copyright (C) 2016 NHN Technology Services This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package com.nts.alphamale.monitor; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.LineIterator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.nts.alphamale.controller.LeaderController; import com.nts.alphamale.data.DataQueue; import com.nts.alphamale.data.EventLog; import com.nts.alphamale.data.Point; import com.nts.alphamale.data.PositionInfo; import com.nts.alphamale.data.Settings; import com.nts.alphamale.event.Event; import com.nts.alphamale.event.EventFactory; import com.nts.alphamale.type.EventType; /*** * ? ? ? class * @author NAVER * */ public class EventMonitor implements Runnable { EventMonitoringListener listener; public interface EventMonitoringListener { public void onCatchEvent(Event event); } Logger log = LogManager.getLogger(this.getClass()); String serial; final String regex = "^\\[(.*)\\]\\s{1,}(\\S+)\\s{1,}(EV_ABS|EV_KEY)\\s{1,}(\\S+)\\s{1,}(\\S+)"; final Pattern p = Pattern.compile(regex); public EventMonitor(String serial, LeaderController leaderController) { this.serial = serial; this.listener = leaderController; } public void run() { try { if (DataQueue.IS_CONTROLED) { log.info("log monitoring"); eventLogAnalysis((LineIterator) DataQueue.EVENT_EXECUTOR.peek().get("stdOut")); } } catch (Exception t) { log.error("Caught exception in EventMonitor. StackTrace:\n" + t.getStackTrace()); this.run(); } } /** * "adb [-s serial] shell getevent -lt" ? ? ? ?. * @see <a href="https://source.android.com/devices/input/getevent.html">Getevent</a> * @param li * @throws InterruptedException */ public void eventLogAnalysis(LineIterator li) throws Exception { boolean tracking = false; int multiCount = 0; List<EventLog> evtLogList = new ArrayList<EventLog>(); Map<Integer, List<Point>> multiSlot = new HashMap<Integer, List<Point>>(); while (li.hasNext()) { String readLine = li.nextLine().trim(); Matcher m = p.matcher(readLine); if (m.find()) { EventLog event = new EventLog(m); if (readLine.contains("EV_KEY")) { makeKeyEvent(event); evtLogList.clear(); } if (event.getAbsLabel().equals("ABS_MT_TRACKING_ID") && event.getAbsValue() != Integer.MAX_VALUE) { if (!multiSlot.containsKey(multiCount)) multiSlot.put(multiCount, new ArrayList<Point>()); multiCount++; tracking = true; } if (event.getAbsLabel().equals("ABS_MT_TRACKING_ID") && event.getAbsValue() == Integer.MAX_VALUE) { multiCount--; if (multiCount == 0) { tracking = false; if (!evtLogList.isEmpty()) { makeMultiTrackingEvent(multiSlot, evtLogList); } } } if (tracking == true) { if (event.getAbsLabel().contains("ABS_MT_POSITION") || event.getAbsLabel().contains("ABS_MT_SLOT")) evtLogList.add(event); } } } } private EventType guessingEventType(PositionInfo position, double elapsedTime) { if (position.getTrackPoint().size() > 0) { Point startXY = position.getStartPoint(); Point endXY = position.getEndPoint(); int width = startXY.x - endXY.x; int height = startXY.y - endXY.y; int absWidth = Math.abs(width); int absHeight = Math.abs(height); //int swipe_distance = absWidth * absHeight; Double swipe_distance = Math.sqrt(Math.pow(absWidth, 2) + Math.pow(absHeight, 2)); log.error("swipe distance : " + swipe_distance); log.error("swipe SWIPE_AREA_THRESHOLD : " + Settings.SWIPE_AREA_THRESHOLD); log.error("elapsedTime : " + elapsedTime); log.error("LONG_TAP_THRESHOLD : " + Settings.LONG_TAP_THRESHOLD); if ((swipe_distance / elapsedTime) > 100) { if (elapsedTime > Settings.LONG_TAP_THRESHOLD) { return EventType.DRAG; } if (swipe_distance > 100) { return EventType.SWIPE; } } if (swipe_distance > Settings.SWIPE_AREA_THRESHOLD) { if (elapsedTime > Settings.LONG_TAP_THRESHOLD) { return EventType.DRAG; } } } if (elapsedTime > Settings.LONG_TAP_THRESHOLD) { return EventType.LONG_TAP; } return EventType.TAP; } private void makeMultiTrackingEvent(Map<Integer, List<Point>> multiSlot, List<EventLog> evtLogList) { //EventInfo event = new EventInfo(); PositionInfo pos = new PositionInfo(); //event start time (timestamp) long evtStartTime = evtLogList.get(0).getCurTimeStamp(); //event end time (timestamp) long evtEndTime = evtLogList.get(evtLogList.size() - 1).getCurTimeStamp(); //event elaspese time (cpu time not ms) double elaspedTime = evtLogList.get(evtLogList.size() - 1).getCpuTimestamp() - evtLogList.get(0).getCpuTimestamp(); double sElaspedTime = evtLogList.get(evtLogList.size() - 1).getCurTimeStamp() - evtLogList.get(0).getCurTimeStamp(); int mt_slot = 0; for (EventLog log : evtLogList) { int x = 0, y = 0; if (log.getAbsLabel().equals("ABS_MT_SLOT")) { mt_slot = log.getAbsValue(); } if (log.getAbsLabel().contains("ABS_MT_POSITION_X")) x = Integer.valueOf(log.getAbsValue()); if (log.getAbsLabel().contains("ABS_MT_POSITION_Y")) y = Integer.valueOf(log.getAbsValue()); multiSlot.get(mt_slot).add(new Point(x, y)); } Integer[] slots = new Integer[multiSlot.size()]; slots = multiSlot.keySet().toArray(slots); Map<Integer, List<Point>> multiTrackInfo = new HashMap<Integer, List<Point>>(); for (int slot : slots) { List<Point> points = multiSlot.get(slot); List<Point> xyPairs = new ArrayList<Point>(); int x = 0, y = 0; for (Point p : points) { x = p.x > 0 ? p.x : x; y = p.y > 0 ? p.y : y; if (x > 0 && y > 0) { xyPairs.add(new Point(x, y)); x = 0; y = 0; } } multiTrackInfo.put(slot, xyPairs); } Event event = null; if (multiSlot.size() == 1) { pos.setTrackPoint(multiTrackInfo.get(0)); if (!evtLogList.isEmpty()) { EventType evtType = guessingEventType(pos, elaspedTime); event = EventFactory.createEvent(evtType); } } else if (multiSlot.size() > 1) { pos.setMultiPoint(multiTrackInfo); if (!evtLogList.isEmpty()) { event = EventFactory.createEvent(EventType.GESTURE); } } if (event != null) { HierarchyMonitor.getInstance(serial).suspend(); event.setEventStartTime(evtStartTime); event.setEventEndTime(evtEndTime); event.setElapsedTime(elaspedTime); event.setSElapsedTime(sElaspedTime); event.setPosition(pos); listener.onCatchEvent(event); HierarchyMonitor.getInstance(serial).resume(); } multiSlot.clear(); evtLogList.clear(); } private void makeKeyEvent(EventLog evtLog) { if (evtLog.getAbsLabel().equals("BTN_TOUCH")) { return; } if (evtLog.getAbsLabel().equals("BTN_TOOL_FINGER")) { return; } if (evtLog.getAbsLabel().equals("MT_TOOL_PEN")) { return; } //TODO long press ? abs_value max(EV_KEY UP ?) ? timestamp ? . long evtTime = evtLog.getCurTimeStamp(); if (evtLog.getAbsValue() == Integer.MIN_VALUE) { Event event = EventFactory.createEvent(EventType.PRESS_KEY); Map<String, Object> value = new HashMap<String, Object>(); value.put("keyValue", "recent"); if (evtLog.getAbsLabel().contains("HOME")) { value.put("keyValue", "home"); } if (evtLog.getAbsLabel().contains("BACK")) { value.put("keyValue", "back"); } if (evtLog.getAbsLabel().contains("VOLUMEUP")) { value.put("keyValue", "volume up"); } if (evtLog.getAbsLabel().contains("VOLUMEDOWN")) { value.put("keyValue", "volume down"); } if (evtLog.getAbsLabel().contains("POWER")) { value.put("keyValue", "power"); } event.setEventStartTime(evtTime); event.setEventEndTime(evtTime); event.setElapsedTime(0); event.setEventMonitoringData(value); listener.onCatchEvent(event); } } }