/* * Copyright (c) 2013 The MITRE Corporation, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this work 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.mitre.svmp.client; import org.mitre.svmp.activities.AppRTCActivity; import org.mitre.svmp.common.Constants; import org.mitre.svmp.performance.PerformanceAdapter; import org.mitre.svmp.protocol.SVMPProtocol; import org.mitre.svmp.protocol.SVMPProtocol.Request.RequestType; import android.graphics.Point; import android.util.Log; import android.view.MotionEvent; /** * @author Dave Keppler, Joe Portner * Captures touch input events to be sent to a remote SVMP instance. */ public class TouchHandler implements Constants { private static final String TAG = TouchHandler.class.getName(); private AppRTCActivity activity; private PerformanceAdapter spi; private Point displaySize; private float xScaleFactor, yScaleFactor = 0; private boolean gotScreenInfo = false; public TouchHandler(AppRTCActivity activity, Point displaySize, PerformanceAdapter spi) { this.activity = activity; this.displaySize = displaySize; this.spi = spi; } public void sendScreenInfoMessage() { SVMPProtocol.Request.Builder msg = SVMPProtocol.Request.newBuilder(); msg.setType(RequestType.SCREENINFO); activity.sendMessage(msg.build()); Log.d(TAG, "Sent screen info request"); } public boolean handleScreenInfoResponse(SVMPProtocol.Response msg) { if (!msg.hasScreenInfo()) return false; final int x = msg.getScreenInfo().getX(); final int y = msg.getScreenInfo().getY(); Log.d(TAG, "Got the ServerInfo: xsize=" + x + " ; ysize=" + y); this.xScaleFactor = (float)x/(float)displaySize.x; this.yScaleFactor = (float)y/(float)displaySize.y; Log.i(TAG, "Scale factor: " + xScaleFactor + " ; " + yScaleFactor); gotScreenInfo = true; return true; } public boolean onTouchEvent(final MotionEvent event) { if (!activity.isConnected() || !gotScreenInfo) return false; // increment the touch update count for performance measurement spi.incrementTouchUpdates(); // Create Protobuf message builders SVMPProtocol.Request.Builder msg = SVMPProtocol.Request.newBuilder(); SVMPProtocol.TouchEvent.Builder eventmsg = SVMPProtocol.TouchEvent.newBuilder(); SVMPProtocol.TouchEvent.PointerCoords.Builder p = SVMPProtocol.TouchEvent.PointerCoords.newBuilder(); SVMPProtocol.TouchEvent.HistoricalEvent.Builder h = SVMPProtocol.TouchEvent.HistoricalEvent.newBuilder(); // Set general touch event information eventmsg.setAction(event.getAction()); eventmsg.setDownTime(event.getDownTime()); eventmsg.setEventTime(event.getEventTime()); eventmsg.setEdgeFlags(event.getEdgeFlags()); // Loop and set pointer/coordinate information final int pointerCount = event.getPointerCount(); for (int i = 0; i < pointerCount; i++) { final float adjX = event.getX(i) * this.xScaleFactor; final float adjY = event.getY(i) * this.yScaleFactor; p.clear(); p.setId(event.getPointerId(i)); p.setX(adjX); p.setY(adjY); eventmsg.addItems(p.build()); } // Loop and set historical pointer/coordinate information final int historicalCount = event.getHistorySize(); for (int i = 0; i < historicalCount; i++) { h.clear(); for (int j = 0; j < pointerCount; j++) { p.clear(); p.setId(event.getPointerId(j)); p.setX(event.getHistoricalX(j,i) * this.xScaleFactor); p.setY(event.getHistoricalY(j,i) * this.yScaleFactor); h.addCoords(p.build()); } h.setEventTime(event.getHistoricalEventTime(i)); eventmsg.addHistorical(h.build()); } // Add Request wrapper around touch event msg.setType(RequestType.TOUCHEVENT); msg.addTouch(eventmsg); // TODO: batch touch events // Send touch event to VM activity.sendMessage(msg.build()); return true; } }