/* * Software Name : ATK - UIautomatorViewer Robotium Version * * 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 : UiAutomatorHelper.java * * Created : 05/06/2013 * Author(s) : D'ALMEIDA Joana */ package com.android.uiautomator; import com.android.ddmlib.AdbCommandRejectedException; import com.android.ddmlib.CollectingOutputReceiver; import com.android.ddmlib.IDevice; import com.android.ddmlib.RawImage; import com.android.ddmlib.ShellCommandUnresponsiveException; import com.android.ddmlib.SyncException; import com.android.ddmlib.SyncService; import com.android.ddmlib.TimeoutException; import com.android.uiautomator.actions.ScreenshotAction; import com.android.uiautomator.robotiumTask.RobotiumTaskForViewer; import com.android.uiautomator.tree.BasicTreeNode; import com.android.uiautomator.tree.RootWindowNode; import com.orange.atk.phone.PhoneException; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.imageio.ImageIO; import javax.swing.JOptionPane; import org.apache.log4j.Logger; public class UiAutomatorHelper { private static RobotiumTaskForViewer robotiumTask=null; public static UiAutomatorViewer mViewer=null; public static boolean supportsUiAutomator(IDevice device) { String apiLevelString = device.getProperty("ro.build.version.sdk"); int apiLevel; try { apiLevel = Integer.parseInt(apiLevelString); } catch (NumberFormatException e) { apiLevel = 16; } return apiLevel >= 16; } private static void getUiHierarchyFile(IDevice device, File dst, String cmd ) throws UiAutomatorException { Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.getUiHierarchyFile***/"); if(UiAutomatorViewer.dumpXMLFirstTime){ robotiumTask= new RobotiumTaskForViewer(device); } try { robotiumTask.getViewFromRobotium(cmd); if(RobotiumTaskForViewer.XmlViews==null){ getUiHierarchyFile(device,dst); UiAutomatorViewer.dumpXMLFirstTime = false; return; } if(!RobotiumTaskForViewer.XmlViews.equalsIgnoreCase("KO")) { try { PrintWriter pw = new PrintWriter(new FileWriter(dst.getAbsolutePath(),true)); pw.print(RobotiumTaskForViewer.XmlViews); pw.close(); } catch(IOException e){ String msg = "Exception while getUiHierarchyFile : " + e.getMessage(); Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper. exception while getUiHierarchyFile***/"); throw new UiAutomatorException(msg, e); } } else { dst=null; throw new UiAutomatorException("can't get views", null); } } catch (PhoneException e1) { Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper. exception while getUiHierarchyFile***/"); String msg = "Exception while getUiHierarchyFile from Robotium : " + e1.getMessage(); throw new UiAutomatorException(msg, e1); } } public static UiAutomatorResult takeSnapshot(IDevice device, UiAutomatorViewer mViewer1,String cmd) throws UiAutomatorException { mViewer=mViewer1; File tmpDir = null; File xmlDumpFile = null; File screenshotFile = null; try { tmpDir = File.createTempFile("uiautomatorviewer_", ""); tmpDir.delete(); if (!tmpDir.mkdirs()) throw new IOException("Failed to mkdir"); xmlDumpFile = File.createTempFile("dump_", ".uix", tmpDir); screenshotFile = File.createTempFile("screenshot_", ".png", tmpDir); } catch (Exception e) { String msg = "Error while creating temporary file to save snapshot: " + e.getMessage(); throw new UiAutomatorException(msg, e); } tmpDir.deleteOnExit(); xmlDumpFile.deleteOnExit(); screenshotFile.deleteOnExit(); //get xml dump file try { UiAutomatorHelper.getUiHierarchyFile(device, xmlDumpFile,cmd); } catch (UiAutomatorException e) { String msg = e.getMessage(); Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error while obtaining UI hierarchy XML file:***/"+ e.getMessage()); throw new UiAutomatorException(msg, e); } UiAutomatorModel model; try { Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.load UiAutomatorModel ***/"); model = new UiAutomatorModel(xmlDumpFile); } catch (Exception e) { String msg = "Error while parsing UI hierarchy XML file: \n" + e.getMessage(); Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error while parsing UI hierarchy XML file:***/"+ e.getMessage()); throw new UiAutomatorException(msg, e); } UiAutomatorHelper.mViewer.glassPane.setText("Taking Screenshot"); Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.getScreenshot***/"); RawImage rawImage=null; try { rawImage = device.getScreenshot(); } catch (TimeoutException e) { String msg = "Error taking device screenshot: " + e.getMessage(); Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error taking device screenshot:***/"+ e.getMessage()); throw new UiAutomatorException(msg, e); }catch (IOException e) { String msg = "Error taking device screenshot: " + e.getMessage(); Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error taking device screenshot:***/"+ e.getMessage()); throw new UiAutomatorException(msg, e); }catch (AdbCommandRejectedException e) { String msg = "Error taking device screenshot: " + e.getMessage(); Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error taking device screenshot:***/"+ e.getMessage()); throw new UiAutomatorException(msg, e); } BasicTreeNode root = model.getXmlRootNode(); if ((root instanceof RootWindowNode)) { for (int i = 0; i < ((RootWindowNode)root).getRotation(); i++) { rawImage = rawImage.getRotated(); } } BufferedImage bImage=null; bImage = new BufferedImage(rawImage.width, rawImage.height,BufferedImage.TYPE_INT_ARGB); int index = 0; int increment = rawImage.bpp >> 3; for (int y = 0 ; y < rawImage.height ; y++) { for (int x = 0 ; x < rawImage.width ; x++) { bImage.setRGB(x, y, rawImage.getARGB(index)); index+=increment; } } Image screenshot =null; try { ImageIO.write(bImage, "png", screenshotFile); screenshot = ImageIO.read(screenshotFile); } catch (IOException e) { String msg = "Error while Reading Screenshot File: " + e.getMessage(); Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error while Reading Screenshot File file:***/"+ e.getMessage()); throw new UiAutomatorException(msg, e); } return new UiAutomatorResult(xmlDumpFile, model, screenshot); } /** * call when device api level >= 16 * @throws PhoneException */ private static void getUiHierarchyFile(IDevice device, File dst) throws UiAutomatorException { Logger.getLogger(UiAutomatorHelper.class).debug( "/****views from uiautomator***/ "); String command = "rm /data/local/tmp/uidump.xml"; try { CountDownLatch commandCompleteLatch = new CountDownLatch(1); device.executeShellCommand(command, new CollectingOutputReceiver(commandCompleteLatch)); commandCompleteLatch.await(5L, TimeUnit.SECONDS); } catch (TimeoutException e) { Logger.getLogger(UiAutomatorHelper.class).debug("/****error : "+ e.getMessage()); throw new UiAutomatorException(e.getMessage(),e); } catch (AdbCommandRejectedException e) { Logger.getLogger(UiAutomatorHelper.class).debug("/****error : "+ e.getMessage()); throw new UiAutomatorException(e.getMessage(),e); } catch (ShellCommandUnresponsiveException e) { Logger.getLogger(UiAutomatorHelper.class).debug("/****error : "+ e.getMessage()); throw new UiAutomatorException(e.getMessage(),e); } catch (IOException e) { Logger.getLogger(UiAutomatorHelper.class).debug("/****error : "+ e.getMessage()); throw new UiAutomatorException(e.getMessage(),e); } catch (InterruptedException e) { Logger.getLogger(UiAutomatorHelper.class).debug("/****error : "+ e.getMessage()); throw new UiAutomatorException(e.getMessage(),e); } command = String.format("%s %s %s", new Object[] { "/system/bin/uiautomator", "dump", "/data/local/tmp/uidump.xml" }); CountDownLatch commandCompleteLatch = new CountDownLatch(1); try { device.executeShellCommand(command, new CollectingOutputReceiver(commandCompleteLatch), 40000); commandCompleteLatch.await(40L, TimeUnit.SECONDS); device.getSyncService().pullFile("/data/local/tmp/uidump.xml", dst.getAbsolutePath(), SyncService.getNullProgressMonitor()); }catch (TimeoutException e) { Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error getviews from uiautomator:***/"+ e.getMessage()); throw new UiAutomatorException(e.getMessage(),e); } catch (AdbCommandRejectedException e) { Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error getviews from uiautomator:***/"+ e.getMessage()); throw new UiAutomatorException(e.getMessage(),e); } catch (ShellCommandUnresponsiveException e) { Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error getviews from uiautomator:***/"+ e.getMessage()); throw new UiAutomatorException(e.getMessage(),e); } catch (IOException e) { Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error getviews from uiautomator:***/"+ e.getMessage()); throw new UiAutomatorException(e.getMessage(),e); } catch (InterruptedException e) { Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error getviews from uiautomator:***/"+ e.getMessage()); throw new UiAutomatorException(e.getMessage(),e); } catch (SyncException e) { Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper.Error getviews from uiautomator:***/"+ e.getMessage()); throw new UiAutomatorException(e.getMessage(),e); } } @SuppressWarnings("serial") public static class UiAutomatorException extends Exception { public UiAutomatorException(String msg, Throwable t) { super(msg, t); } } public static class UiAutomatorResult { public final File uiHierarchy; public final UiAutomatorModel model; public final Image screenshot; public UiAutomatorResult(File uiXml, UiAutomatorModel m, Image s) { uiHierarchy = uiXml; model = m; screenshot = s; } } public static void executeRobotiumCommand(String cmd) throws UiAutomatorException{ try { robotiumTask.getViewFromRobotium(cmd); } catch (PhoneException e1) { Logger.getLogger(UiAutomatorHelper.class).debug("/****UiAutomatorHelper. exception while executing command***/ : "+cmd); String msg = "exception while executing command : " +cmd +" exception "+ e1.getMessage(); throw new UiAutomatorException(msg, e1); } } }