Java tutorial
/* * Software Name : ATK * * Copyright (C) 2007 - 2012 France Tlcom * * 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 : AndroidWizard.java * * Created : 13/08/2010 * Author(s) : HENAFF Mari-Mai */ package com.orange.atk.phone.android.wizard; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Toolkit; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.io.BufferedReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Hashtable; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import org.apache.log4j.Logger; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import com.android.ddmlib.AdbCommandRejectedException; import com.android.ddmlib.IDevice; import com.android.ddmlib.IShellOutputReceiver; import com.android.ddmlib.InstallException; import com.android.ddmlib.ShellCommandUnresponsiveException; import com.android.ddmlib.TimeoutException; import com.orange.atk.error.ErrorManager; import com.orange.atk.internationalization.ResourceManager; import com.orange.atk.phone.PhoneException; import com.orange.atk.phone.android.AndroidDriver; import com.orange.atk.phone.detection.AutomaticPhoneDetection; import com.orange.atk.platform.Platform; import com.orange.atk.util.Position; public class AndroidWizard extends JFrame { private static final String TITLE = "Android Wizard"; protected final static int PORT_ATK_WIZARD = 1358; private String configFileName = ""; private Hashtable<Integer, JPanel> wizardSteps = new Hashtable<Integer, JPanel>(); private Hashtable<Integer, String> wizardStepTitle = new Hashtable<Integer, String>(); private Hashtable<String, String> detectedChannels = new Hashtable<String, String>(); private Hashtable<String, StringBuffer> channelEvents = new Hashtable<String, StringBuffer>(); AndroidDriver phone; IDevice device; int currentStep = -1; // Android Config file parameters private String touchscreen = ""; private String keyboard = ""; private String keyboard2 = ""; private String keyboard3 = ""; private HashMap<String, Position> softKeyMap = new HashMap<String, Position>(); //HashMap<keyName,(X,Y)> private HashMap<String, Integer> keyMap = new HashMap<String, Integer>(); //HashMap<keyName,keyCode> private HashMap<String, String> keyCanal = new HashMap<String, String>(); // HashMap<keyName,keyboard> private HashMap<String, String> softKeyCanal = new HashMap<String, String>(); // HashMap<keyName,keyboard> private boolean ATKWizardInstalled = false; private Socket socket; private int screenWidth = 0; private int screenHeight = 0; private int codeX = -1; private int maxX = 0; private int codeY = -1; private int maxY = 0; private String patternX; private String patternY; private IShellOutputReceiver shellOutputReceiver = new IShellOutputReceiver() { public void addOutput(byte[] data, int offset, int length) { } public void flush() { } public boolean isCancelled() { return false; } }; public AndroidWizard(AndroidDriver phone, IDevice device, String confFileName) throws PhoneException { super(TITLE); configFileName = confFileName; this.device = device; this.phone = phone; try { device.executeShellCommand("getevent -p", new DetectAllChannelsEventFilter(detectedChannels, channelEvents)); } catch (IOException e) { String error = ResourceManager.getInstance().getString("ANDROID_CHANNEL_DETECTION_ERROR"); ErrorManager.getInstance().addWarning(getClass().getName(), error, e); throw new PhoneException(error); } catch (TimeoutException e) { String error = ResourceManager.getInstance().getString("ANDROID_CHANNEL_DETECTION_ERROR"); ErrorManager.getInstance().addWarning(getClass().getName(), error, e); throw new PhoneException(error); } catch (AdbCommandRejectedException e) { String error = ResourceManager.getInstance().getString("ANDROID_CHANNEL_DETECTION_ERROR"); ErrorManager.getInstance().addWarning(getClass().getName(), error, e); throw new PhoneException(error); } catch (ShellCommandUnresponsiveException e) { String error = ResourceManager.getInstance().getString("ANDROID_CHANNEL_DETECTION_ERROR"); ErrorManager.getInstance().addWarning(getClass().getName(), error, e); throw new PhoneException(error); } addStep(new StartWizardPanel(this, phone), "Android Wizard"); addStep(new TouchscreenChannelPanel(this, device, detectedChannels), "Select the channel for the touchscreen"); this.setSize(600, 400); getContentPane().setLayout(new FlowLayout()); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); this.addWindowListener(new WindowListener() { public void windowActivated(WindowEvent arg0) { } public void windowClosed(WindowEvent arg0) { } public void windowClosing(WindowEvent arg0) { exit(false); } public void windowDeactivated(WindowEvent arg0) { } public void windowDeiconified(WindowEvent arg0) { } public void windowIconified(WindowEvent arg0) { } public void windowOpened(WindowEvent arg0) { } }); Dimension sSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension fSize = this.getSize(); this.setLocation((sSize.width - fSize.width) / 2, (sSize.height - fSize.height) / 2); goToStep(0); } public void addStep(JPanel panel, String title) { wizardSteps.put(new Integer(currentStep + 1), panel); wizardStepTitle.put(new Integer(currentStep + 1), title); goToStep(currentStep + 1); } public void exit(boolean force) { if (force) close(); else { int result = JOptionPane.showConfirmDialog(this, "Are you sure you want to exit wizard ? Configuration file won't be generated.", "Confirmation", JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) { close(); } } } private void close() { this.dispose(); try { this.uninstallATKWizard(); } catch (PhoneException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void nextStep() { goToStep(currentStep + 1); } public void prevStep() { goToStep(currentStep - 1); } private void goToStep(int step) { currentStep = step; getContentPane().removeAll(); if (step > 0) this.setTitle(TITLE + ": " + wizardStepTitle.get(new Integer(step)) + " (Step " + step + ")"); if (wizardSteps.get(new Integer(step)) == null) Logger.getLogger(this.getClass()).debug("Step " + step + " is null !!"); getContentPane().add(wizardSteps.get(new Integer(step))); pack(); setVisible(true); } protected void installATKWizard() throws PhoneException { if (!ATKWizardInstalled) { Logger.getLogger(this.getClass()).debug("Installing ATK Wizard on phone"); //push ATKMonitor to the Device try { String result = device.uninstallPackage("com.orange.atk.wizard"); if (result != null) { Logger.getLogger(this.getClass()).debug("Result of the uninstall: " + result); } result = device.installPackage(Platform.getInstance().getJATKPath() + Platform.FILE_SEPARATOR + "AndroidTools" + Platform.FILE_SEPARATOR + "ATKWizard.apk", true); if (result != null) { Logger.getLogger(this.getClass()).debug("Result of the push: " + result); } } catch (InstallException e) { e.printStackTrace(); throw new PhoneException("ATK Wizard - unable to install ATK Wizard"); } //Forward tcp port String adbLocation = Platform.getInstance().getDefaultADBLocation(); Runtime r = Runtime.getRuntime(); String[] args1 = { adbLocation, "forward", "tcp:" + PORT_ATK_WIZARD, "tcp:" + PORT_ATK_WIZARD }; Process p; BufferedReader in_br = null; try { p = r.exec(args1); in_br = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = ""; while ((line = in_br.readLine()) != null) { Logger.getLogger(this.getClass()).debug("adb forward done : " + line); if (line.contains("daemon")) { throw new PhoneException("ATK Wizard - unable to install ATK Wizard"); } } in_br.close(); } catch (Exception e) { e.printStackTrace(); throw new PhoneException("ATK Wizard - unable to install ATK Wizard"); } Logger.getLogger(this.getClass()).debug("adb forward done for port " + PORT_ATK_WIZARD + "\n"); ATKWizardInstalled = true; } } protected void startATKWizard() throws PhoneException { Logger.getLogger(this.getClass()).debug("Starting ATK Wizard"); //run ATKWizard try { device.executeShellCommand("am start -n com.orange.atk.wizard/.ATKWizardClient", shellOutputReceiver); } catch (IOException e) { e.printStackTrace(); throw new PhoneException("ATK Wizard - unable to launch ATK Wizard"); } catch (TimeoutException e) { e.printStackTrace(); throw new PhoneException("ATK Wizard - unable to launch ATK Wizard"); } catch (AdbCommandRejectedException e) { e.printStackTrace(); throw new PhoneException("ATK Wizard - unable to launch ATK Wizard"); } catch (ShellCommandUnresponsiveException e) { e.printStackTrace(); throw new PhoneException("ATK Wizard - unable to launch ATK Wizard"); } try { Thread.sleep(1000); } catch (InterruptedException e2) { } Logger.getLogger(this.getClass()).debug("ATK Wizard is launched on the device ..."); } protected void uninstallATKWizard() throws PhoneException { if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); throw new PhoneException("ATK Wizard - unable to uninstall ATK Wizard"); } } Logger.getLogger(this.getClass()).debug("Uninstalling ATK Wizard from phone"); try { String result = device.uninstallPackage("com.orange.atk.wizard"); if (result != null) { Logger.getLogger(this.getClass()).debug("Result of the uninstall: " + result); } } catch (InstallException e) { e.printStackTrace(); throw new PhoneException("ATK Wizard - unable to uninstall ATK Wizard"); } } protected Socket getWizardSocket() throws UnknownHostException, IOException { if (socket == null) socket = new Socket("127.0.0.1", PORT_ATK_WIZARD); return socket; } public void printReport() { String configXmlFileName = configFileName + ".xml"; Document configxml = DocumentHelper.createDocument(); configxml.addComment(" " + phone.getName() + " configuration file "); configxml.addComment(" Screen resolution " + screenWidth + "x" + screenHeight + " "); Element root = configxml.addElement("Android-config"); Element canalPattern = root.addElement("CanalPattern"); //keyboards if (!keyboard.equals("")) printKeyMapping("keyboard", keyboard, canalPattern, root); if (!keyboard2.equals("")) printKeyMapping("keyboard2", keyboard2, canalPattern, root); if (!keyboard3.equals("")) printKeyMapping("keyboard3", keyboard3, canalPattern, root); Set<String> softKeySet = softKeyMap.keySet(); Element keyMapping = root.addElement("SoftKeyMapping"); for (String key : softKeySet) { keyMapping.addElement("Key").addAttribute("name", key) .addAttribute("avgX", "" + softKeyMap.get(key).getX()) .addAttribute("avgY", "" + softKeyMap.get(key).getY()); } //touchscreen if (!touchscreen.equals("")) { canalPattern.addElement("Pattern").addAttribute("canal", "touchscreen").addAttribute("value", touchscreen.replace("\"", "")); Element Touchscreen = root.addElement("Touchscreen"); Touchscreen.addComment("!!! THIS IS JUST TOUCHSCREEN Elements TEMPLATE !!!"); Touchscreen .addComment("!!! SEE ATK User Guide - Configuration section - and UPDATE following values !!!"); if (codeX != -1 && codeY != -1) { Touchscreen.addComment("!!! Please check following X Y ratioX and ratioY patterns"); Touchscreen.addElement("Pattern").addAttribute("name", "X").addAttribute("value", "3 " + codeX + " "); Touchscreen.addElement("Pattern").addAttribute("name", "Y").addAttribute("value", "3 " + codeY + " "); long ratio = maxX * 100 / screenWidth; Touchscreen.addElement("Pattern").addAttribute("name", "ratioX").addAttribute("value", String.valueOf((double) ratio / 100.0)); ratio = maxY * 100 / screenHeight; Touchscreen.addElement("Pattern").addAttribute("name", "ratioY").addAttribute("value", String.valueOf((double) ratio / 100.0)); Touchscreen.addComment("!!! Please update following patterns"); } else { Touchscreen.addElement("Pattern").addAttribute("name", "X").addAttribute("value", "0 0 "); Touchscreen.addElement("Pattern").addAttribute("name", "Y").addAttribute("value", "0 0 "); Touchscreen.addElement("Pattern").addAttribute("name", "ratioX").addAttribute("value", "1.0"); Touchscreen.addElement("Pattern").addAttribute("name", "ratioY").addAttribute("value", "1.0"); } Touchscreen.addElement("Pattern").addAttribute("name", "down").addAttribute("value", "0 0 0"); Touchscreen.addElement("Pattern").addAttribute("name", "downmax").addAttribute("value", "0 0 0"); Touchscreen.addElement("Pattern").addAttribute("name", "up").addAttribute("value", "0 0 0"); Touchscreen.addElement("Pattern").addAttribute("name", "flush").addAttribute("value", "0 0 0"); Touchscreen.addElement("Pattern").addAttribute("name", "flush2").addAttribute("value", "0 2 0"); Touchscreen.addElement("Threshold").addAttribute("name", "move").addAttribute("value", "15"); Touchscreen.addElement("Option").addAttribute("name", "sendMouseDownForMove").addAttribute("value", "true"); Touchscreen.addElement("Option").addAttribute("name", "sendMouseEventFirst").addAttribute("value", "true"); Touchscreen.addElement("Option").addAttribute("name", "useMonkeyForPress").addAttribute("value", "true"); } //Write the file. OutputFormat format = OutputFormat.createPrettyPrint(); XMLWriter writer = null; try { writer = new XMLWriter(new FileWriter(configXmlFileName), format); writer.write(configxml); writer.close(); } catch (IOException e) { e.printStackTrace(); } //Show a confirm dialog and exit the wizard JOptionPane.showConfirmDialog(this, "A template of the config file has been created under \n" + configXmlFileName + "\n" + "See ATK User guide to configure the Touchscreen section of this template\n", "Success", JOptionPane.CLOSED_OPTION); exit(true); } private void printKeyMapping(String canal, String value, Element canalPattern, Element root) { Set<String> keySet = keyCanal.keySet(); canalPattern.addElement("Pattern").addAttribute("canal", canal).addAttribute("value", value.replace("\"", "")); Element keyMapping = root.addElement("KeyMapping").addAttribute("canal", canal); for (String key : keySet) { if (keyCanal.get(key).equals(canal)) { keyMapping.addElement("Key").addAttribute("name", key).addAttribute("code", "" + keyMap.get(key)); } } } public void setScreenWidth(int screenWidth) { this.screenWidth = screenWidth; } public void setScreenHeight(int screenHeight) { this.screenHeight = screenHeight; } public String getPatternX() { return patternX; } public String getPatternY() { return patternY; } public double getRatioX() { if (screenWidth != 0) return ((double) maxX / (double) screenWidth); return 0; } public double getRatioY() { if (screenHeight != 0) return ((double) maxY / (double) screenHeight); return 0; } /******** Config file parameters *********/ public String getKeyboard(int keyboardNb) { if (keyboardNb == 1) return keyboard; else if (keyboardNb == 2) return keyboard2; else if (keyboardNb == 3) return keyboard3; return keyboard; } public void setKeyboard(int keyboardNb, String keyboard) { if (keyboardNb == 1) this.keyboard = keyboard; else if (keyboardNb == 2) this.keyboard2 = keyboard; else if (keyboardNb == 3) this.keyboard3 = keyboard; } public void registerKey(int keyboard, String keyName, int keyCode) { String keyboardType = "keyboard"; if (keyboard == 2) keyboardType = "keyboard2"; else if (keyboard == 3) keyboardType = "keyboard3"; keyCanal.put(keyName, keyboardType); keyMap.put(keyName, new Integer(keyCode)); } public void registerSoftKey(int keyboard, String keyName, int avgX, int avgY) { // this is soft keyboard == always touchscreen if (keyboard == 1) this.keyboard = ""; else if (keyboard == 2) this.keyboard2 = ""; else if (keyboard == 3) this.keyboard3 = ""; softKeyMap.put(keyName, new Position(avgX, avgY, 0)); } public void setTouchscreen(String touchscreen, StringBuffer traces) { this.touchscreen = touchscreen; // Analyze traces to get X Y event codes String[] tracesEvents = traces.toString().split("\n"); int traceX = -1; int traceY = -1; for (int i = 0; i < tracesEvents.length && i < 20 && traceY == -1; i++) { String traceEvent = tracesEvents[i]; Logger.getLogger(this.getClass()).debug("###" + traceEvent); Matcher mtc = Pattern.compile("\\w*-\\w*:\\s*(\\w*)\\s*(\\w*)\\s*(\\w*)\\s*").matcher(traceEvent); if (mtc.matches()) { int code = Integer.parseInt(mtc.group(2), 16); Logger.getLogger(this.getClass()).debug("TRACE CODE=" + code); if (traceX == -1) { traceX = code; } else { if (code == traceX + 1) { traceY = code; Logger.getLogger(this.getClass()).debug("traceX=" + traceX + " traceY=" + traceY); } else traceX = code; } } } // Analyze touchscreen events to get X Y ratio templates String touchEventsDescription = channelEvents.get(touchscreen).toString(); String[] touchEvents = touchEventsDescription.split("\n"); for (int i = 0; i < touchEvents.length && codeY == -1; i++) { String touchEvent = touchEvents[i]; if (touchEvent.indexOf(":") != -1) touchEvent = touchEvent.substring(touchEvent.indexOf(":") + 1); Logger.getLogger(this.getClass()).debug("***" + touchEvent); Matcher mtc = Pattern.compile( "\\s*(\\d*)\\s*value\\s*(-?\\d+),\\s*min\\s*(-?\\d+),\\s*max\\s*(-?\\d+),\\s*fuzz\\s*(-?\\d+)\\s*flat\\s*(-?\\d+)\\s*") .matcher(touchEvent); if (mtc.matches()) { int code = Integer.parseInt(mtc.group(1), 16); Logger.getLogger(this.getClass()).debug("CODE=" + code); if (code == codeX + 1 && code > 0 && (traceY == -1 || traceY == code)) { codeY = code; patternY = "0003 " + mtc.group(1); Logger.getLogger(this.getClass()).debug("codeX=" + codeX + " codeY=" + codeY); maxY = Integer.parseInt(mtc.group(4)); } else { codeX = code; patternX = "0003 " + mtc.group(1); maxX = Integer.parseInt(mtc.group(4)); } } } if (codeY == -1) codeX = -1; } }