/*
* Software Name : ATK
*
* Copyright (C) 2007 - 2012 France Télécom
*
* 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.
*
* ------------------------------------------------------------------
* File Name : SmartTouchScreenEventfilter.java
*
* Created : 05/08/2011
* Author(s) : HENAFF Mari-Mai
*/
package com.orange.atk.phone.android;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import com.orange.atk.phone.PhoneInterface;
import com.orange.atk.phone.android.wizard.EventTimerThread;
import com.orange.atk.phone.android.wizard.TimeOutListener;
import com.orange.atk.util.Position;
/**
* Class used to filter output of very common touch screen,
* He is found on HTC G1, Samsung SPICA , MOtorola Morisson...
* @author Moreau Fabien - GFI - FMOREAU@gfi.fr
*
*/
class SmartTouchScreenEventfilter extends EventFilter implements TimeOutListener {
EventTimerThread eventTimerThread;
boolean up = true;
protected int ALLOW_PIXEL_MOVE = 10;
protected int ALLOW_SOFTKEY_MOVE = 20;
//code to detect movement
protected static String X_POSITION="xxx";
protected static String Y_POSITION="xxx";
protected static String XY_POSITION="xxx";
protected static String MOUSE_UP;
//List of Position
private List<Position> tempmoveposition;
//Discriminate if the action is a Drag or a Slide
private boolean isDragAndDrop=false;
private boolean hasMoved=false;
//time of last action such as move Mouse Down or First move
private long refTime=0;
AndroidDriver driver;
protected int newX=-1;
protected int newY=-1;
protected int x=0;
protected int y=0;
protected int moy_x=0;
protected int moy_y=0;
protected int counter = 0;
private Position oldPosition;
private Position initialPosition;
private HashMap<String, Position> softkeyMap;
private Long time;
private boolean mouseUpReceived = false;
public SmartTouchScreenEventfilter(AndroidDriver aphone, AndroidConfHandler ges, HashMap<String, Position> softkeyMap) {
driver = aphone;
tempmoveposition = new ArrayList<Position>();
this.softkeyMap = softkeyMap;
//réecriture en hexa
if (ges.getXpattern()!=null) {
X_POSITION = convertToHexa(ges.getXpattern() );
Y_POSITION = convertToHexa(ges.getYpattern() );
} else {
XY_POSITION = convertToHexa(ges.getXYpattern() );
}
ALLOW_PIXEL_MOVE = ges.getMoveThreshold();
MOUSE_UP = convertToHexa(ges.getUppattern() );
eventTimerThread = new EventTimerThread(this, 500);
eventTimerThread.start();
Logger.getLogger(this.getClass() ).debug("DefaultTouchScreenEventfilter");
}
public enum Action {
MOUSE_DOWN, MOUSE_UP, MOUSE_MOVE, UNKNOWN_ACTION
}
String convertToHexa(String dec) {
if (dec == null) return null;
String result="";
String[] X_POSITIONs = dec.split(" ");
int position=0;
for(String element : X_POSITIONs){
try{
position++;
long x = Integer.parseInt(element);
String hexel = Long.toHexString(x);
if(position==3) {
for(int i=hexel.length() ; i<8 ;i++)
hexel = "0"+hexel;
} else {
for(int i=hexel.length() ; i<4 ;i++)
hexel = "0"+hexel;
}
//don't start with space.
if(position!=1)
result+=" ";
result+=hexel;
}catch (Exception e) {
Logger.getLogger(this.getClass()).warn("error during conversion command in hexa", e);
}
}
Logger.getLogger(this.getClass()).debug(dec+"-->"+result);
return result;
}
@Override
public void processline( String line) {
Logger.getLogger(this.getClass() ).debug("processline : "+line);
eventTimerThread.newEventTime(System.currentTimeMillis());
String commands[] = line.split(": ");
String command = commands[1];
String timeTable[] = commands[0].split("-");
//timeTable[0]: time in s - timeTable[1]: time in microsecond
//time in ms:
time = Long.parseLong(timeTable[0])*1000+Long.parseLong(timeTable[1])/1000;
if(command.startsWith(X_POSITION)) {
//Logger.getLogger(this.getClass() ).debug("Command X="+command);
newX= (((int) ((float)Long.parseLong(command.substring(10),16)/driver.SCREEN_RATIO_X)));
}else if(command.startsWith(Y_POSITION)) {
//Logger.getLogger(this.getClass() ).debug("Command Y="+command);
newY= (int) ((float)Long.parseLong(command.substring(10),16)/driver.SCREEN_RATIO_Y);
}else if(command.startsWith(XY_POSITION)) {
newX= (int) ((float)(Long.parseLong(command.substring(10,14),16) - Long.parseLong("8000",16))/driver.SCREEN_RATIO_X);
newY= (int) ((float)Long.parseLong(command.substring(14),16)/driver.SCREEN_RATIO_Y);
}else if (MOUSE_UP != null && command.startsWith(MOUSE_UP)) {
mouseUpReceived = true;
}
if (newX!=-1 && newY!=-1) {
if (newX!=0 && newX !=0) {
x = newX;
y = newY;
}
newX = -1;
newY = -1;
if (up) {
Logger.getLogger(this.getClass() ).debug("is down");
switchaction( x, y, Action.MOUSE_DOWN, time);
up = false;
} else {
Logger.getLogger(this.getClass() ).debug("is moving");
switchaction( x, y, Action.MOUSE_MOVE, time);
}
}
}
private void perform_average() {
if (moy_x == 0) moy_x = x;
else moy_x = ((moy_x * counter) + x )/ (counter+1);
counter++;
if (moy_y == 0) moy_y = y;
else moy_y = ((moy_y * counter) + y )/ (counter+1);
counter++;
}
private void switchaction(int x,int y, Action action, Long time)
{
switch(action) {
case MOUSE_UP:
Logger.getLogger(this.getClass() ).debug("MOUSE UP x="+x+" - y="+y+" - time="+time);
if(hasMoved) {
tempmoveposition.add(new Position(x,y,(time-refTime)));
if(isDragAndDrop){
driver.phoneTouchScreenDragndrop(tempmoveposition);
} else {
driver.phoneTouchScreenSlide(tempmoveposition);
}
} else {
perform_average();
boolean isSoftKeyPress = false;
Iterator<String> keys = softkeyMap.keySet().iterator();
while (keys.hasNext() && !isSoftKeyPress) {
String key = keys.next();
Position pos = softkeyMap.get(key);
int key_x = pos.getX();
int key_y = pos.getY();
if ((key_x-ALLOW_SOFTKEY_MOVE < moy_x ) && (moy_x < key_x+ALLOW_SOFTKEY_MOVE) && (key_y-ALLOW_SOFTKEY_MOVE < moy_y ) && (moy_y < key_y+ALLOW_SOFTKEY_MOVE)) {
driver.phoneKey(key, (int) (time - refTime), 0);
isSoftKeyPress = true;
}
}
if (!isSoftKeyPress) driver.phoneTouchScreenPressed(moy_x, moy_y,time - refTime);
}
//FLUSH temp
tempmoveposition = new ArrayList<Position>();
isDragAndDrop = false;
hasMoved=false;
initialPosition=null;
oldPosition=null;
moy_x = 0;
moy_y = 0;
counter = 0;
break;
case MOUSE_DOWN:
//Start Timer
Logger.getLogger(this.getClass() ).debug("MOUSE DOWN x="+x+" - y="+y+" - time="+time);
perform_average();
oldPosition =new Position(x,y,0);
tempmoveposition.add(oldPosition);
initialPosition = oldPosition;
refTime = time;
break;
case MOUSE_MOVE:
Logger.getLogger(this.getClass() ).debug("MOUSE MOVE x="+x+" - y="+y+" - time="+time);
perform_average();
if (initialPosition==null) {
oldPosition =new Position(x,y,0);
tempmoveposition.add(oldPosition);
initialPosition = oldPosition;
refTime = time;
} else {
if(((Math.abs(initialPosition.getX()-x) >ALLOW_PIXEL_MOVE ||
Math.abs(initialPosition.getY()-y) >ALLOW_PIXEL_MOVE ))){
if (!hasMoved && (time-refTime)>PhoneInterface.TOUCHSCREEN_LONG_EVENT_MIN_TIME )
isDragAndDrop = true;
hasMoved=true;
}
if(oldPosition!=null&&
((Math.abs(oldPosition.getX()-x) >ALLOW_PIXEL_MOVE ||
Math.abs(oldPosition.getY()-y) >ALLOW_PIXEL_MOVE ))){
oldPosition =new Position(x,y,(time-refTime));
tempmoveposition.add(oldPosition);
}
}
break;
}
}
public void notifyTimeOut() {
Logger.getLogger(this.getClass() ).debug("notify timeout");
if (MOUSE_UP==null || mouseUpReceived) {
switchaction( x, y, Action.MOUSE_UP, time);
up = true;
mouseUpReceived = false;
}
}
public void stopDetection() {
eventTimerThread.stopRunning();
}
}