package com.orange.atk.atkUI.coregui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GradientPaint; import java.awt.Paint; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.URL; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.log4j.Logger; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.renderer.category.BarRenderer; import org.jfree.data.category.CategoryDataset; import org.jfree.data.category.DefaultCategoryDataset; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.orange.atk.atkUI.corecli.Configuration; import com.orange.atk.phone.PhoneInterface; import com.orange.atk.phone.detection.AutomaticPhoneDetection; import com.orange.atk.platform.Platform; public class BenchmarkDialog extends JDialog { public static ImageIcon icon = null; private static final String icondescr = "ATK"; private static final String BENCHMARK_PACKAGE_NAME = "com.antutu.ABenchMark"; private static final Pattern patternScore = Pattern.compile("AnTuTuBenchmarkScore\\([ 0-9]+\\):\\s*(\\w+)\\s*:\\s*(\\d+)"); private static final Pattern patternInfo = Pattern.compile("AnTuTuBenchmarkInfo\\([ 0-9]+\\):\\s*(\\d+%)\\s*:\\s*(.+)"); private String outputDir; private String outputFile; private JPanel panel = new JPanel(new BorderLayout()); private JLabel lblStatus = new JLabel(); private String infoText; private JButton btnGo = new JButton("New benchmark"); private JProgressBar progressBar = new JProgressBar(); InfiniteProgressPanel glassPane=null; private DefaultListModel deviceListModel; PhoneInterface currentPhone=null; private JScrollPane scrollableDeviceList; private JList deviceList; private DefaultListModel perfListModel; private JList perfList; private JScrollPane scrollablePerfList; JFreeChart sbchart; DefaultCategoryDataset dataset; List selectedDevices=new ArrayList(); List selectedPerfs=new ArrayList(); HashMap<String, Color> perfColor; public BenchmarkDialog(){ super(CoreGUIPlugin.mainFrame, true); outputDir=Configuration.getProperty("benchmarkDir"); if(outputDir.length()==0){ JOptionPane.showMessageDialog(this, "You have to configure a directory to store benchmark results","Error",JOptionPane.ERROR_MESSAGE); return; } outputFile=outputDir+Platform.FILE_SEPARATOR+"benchmark.csv"; File file = new File(outputFile); if(!file.exists()){ Logger.getLogger(this.getClass() ).info("initializing results database in "+outputFile); try { BufferedWriter os = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file,true))); os.write("date,model,version,memory,integer,float,score2d,score3d,database,sdwrite,sdread,score\n"); os.write("2013-04-26 16:30,GT-I9100,4.0.3,1472,1605,1349,1403,4413,375,1370,0,10754\n"); os.write("2013-05-02 16:51,Nexus 4,4.2.2,2344,3929,1751,1573,6320,535,1500,1900,16792\n"); os.write("2013-05-31 11:02,Galaxy Nexus,4.2,1217,1565,1349,487,2014,410,77,190,7309\n"); os.close(); } catch (IOException e1) { e1.printStackTrace(); } } setPreferredSize(new Dimension(1024, 600)); URL iconURL = CoreGUIPlugin.getMainIcon(); icon = new ImageIcon(iconURL, icondescr); setIconImage(icon.getImage()); setTitle("Benchmark"); deviceListModel = new DefaultListModel(); scrollableDeviceList = new JScrollPane(); scrollablePerfList = new JScrollPane(); deviceList = new JList(deviceListModel); perfListModel = new DefaultListModel(); perfList = new JList(perfListModel); currentPhone = AutomaticPhoneDetection.getInstance().getDevice(); glassPane = new InfiniteProgressPanel( ); glassPane.setOpaque(false); setGlassPane(glassPane); btnGo.setPreferredSize(new Dimension(60, 30)); dataset = new DefaultCategoryDataset(); initializeDataset(null,null); sbchart = createChart(dataset); final ChartPanel pnl = new ChartPanel(sbchart); pnl.setPreferredSize(new java.awt.Dimension(450, 350)); Box deviceListBox = Box.createVerticalBox(); deviceListBox.add(new JLabel("List of devices")); Box perfListBox = Box.createVerticalBox(); perfListBox.add(new JLabel("Performance")); scrollableDeviceList.setViewportView(deviceList); deviceListBox.add(scrollableDeviceList); scrollablePerfList.setViewportView(perfList); perfListBox.add(scrollablePerfList); perfListModel.insertElementAt("cpu", 0); perfListModel.insertElementAt("mem", 1); perfListModel.insertElementAt("3d", 1); ActionListener launchBenchListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { new Thread(new SearchPackage()).start(); new Thread(new ReadLogcat()).start(); glassPane.setVisible(true); glassPane.start( ); } }; deviceList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent evt) { if (evt.getValueIsAdjusting()) { return; } selectedDevices.clear(); Collections.addAll(selectedDevices, deviceList.getSelectedValues()); initializeDataset(selectedDevices,selectedPerfs); sbchart.fireChartChanged(); } }); perfList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent evt) { if (evt.getValueIsAdjusting()) { return; } selectedPerfs.clear(); Collections.addAll(selectedPerfs,perfList.getSelectedValues()); initializeDataset(selectedDevices,selectedPerfs); sbchart.fireChartChanged(); } }); btnGo.addActionListener(launchBenchListener); progressBar.setPreferredSize(new Dimension(150, 18)); progressBar.setStringPainted(true); progressBar.setVisible(false); JPanel rightBar = new JPanel(new BorderLayout(5, 0)); rightBar.setLayout(new BoxLayout(rightBar, BoxLayout.PAGE_AXIS)); rightBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5)); rightBar.add(btnGo); rightBar.add(deviceListBox); rightBar.add(perfListBox); JPanel statusBar = new JPanel(new BorderLayout(5, 0)); statusBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5)); statusBar.add(lblStatus, BorderLayout.CENTER); statusBar.add(progressBar, BorderLayout.EAST); panel.add(rightBar, BorderLayout.EAST); panel.add(pnl, BorderLayout.CENTER); panel.add(statusBar, BorderLayout.SOUTH); getContentPane().add(panel); pack(); setVisible(true); } private class ReadLogcat implements Runnable{ /*I/AnTuTuBenchmarkScore(17928): memory : 710 I/AnTuTuBenchmarkScore(17928): integer : 775 I/AnTuTuBenchmarkScore(17928): float : 657 I/AnTuTuBenchmarkScore(17928): 2d : 481 I/AnTuTuBenchmarkScore(17928): 3d : 1956 I/AnTuTuBenchmarkScore(17928): database : 415 I/AnTuTuBenchmarkScore(17928): sdwrite : 102 I/AnTuTuBenchmarkScore(17928): sdread : 192 I/AnTuTuBenchmarkScore(17928): score : 5288 */ boolean isRunning=false; public void run() { isRunning=true; progressBar.setVisible(true); if(!(new File(outputDir).exists())){ boolean success = new File(outputDir).mkdir(); if (success) { Logger.getLogger(this.getClass() ).info(outputDir+" created"); } } String line = ""; BufferedReader bufferedReader=null; Process process = null; try { //Clear logcat to ensure we log the relevant test results process = Runtime.getRuntime().exec(new String[]{Platform.getInstance().getDefaultADBLocation(), "-s",currentPhone.getUID(),"logcat","-c"}); process.waitFor(); process = Runtime.getRuntime().exec(new String[]{Platform.getInstance().getDefaultADBLocation(), "-s",currentPhone.getUID(),"logcat","-v","time"}); bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); Logger.getLogger(this.getClass() ).info("logcat running"); while(isRunning) { line = bufferedReader.readLine(); if(line!=null){ if(line.contains("AnTuTuBenchmarkScore")){ Logger.getLogger(this.getClass() ).info(line); Matcher match = patternScore.matcher(line); if(match.find()){ infoText+=match.group(1)+": "+match.group(2)+"<br>"; lblStatus.setText("<html>"+infoText+"</html>"); }else{ Logger.getLogger(this.getClass() ).info("line doesn't match"); } }else if(line.contains("AnTuTuBenchmarkInfo")){ Logger.getLogger(this.getClass() ).info(line); Matcher match = patternInfo.matcher(line); if(match.find()){ lblStatus.setText(match.group(1)+" "+match.group(2)); progressBar.setValue(Integer.parseInt(match.group(1).split("%")[0])); } if(match.group(1).equals("100%")){ Logger.getLogger(this.getClass() ).info("stop"); isRunning=false; Thread.sleep(4000); } } }else{ Thread.sleep(200); } } Logger.getLogger(this.getClass() ).info("stop logcat"); process.destroy(); glassPane.stop(); lblStatus.setText("fetching results..."); fetchResultFile(); } catch (IOException e) { Logger.getLogger(this.getClass() ).error("could not read logcat"); } catch (InterruptedException e) { Logger.getLogger(this.getClass() ).error("could not read logcat"); } } } private class SearchPackage implements Runnable { private boolean installing=false; boolean foundBenchApk = false; @Override public void run() { if(currentPhone.getType() != PhoneInterface.TYPE_ANDROID) { infoText="No device found<br>"; lblStatus.setText("<html>"+infoText+"</html>"); glassPane.stop(); return; } infoText="Benchmarking "+currentPhone.getName()+ " ("+currentPhone.getUID()+")"; setTitle(infoText); while(foundBenchApk == false ){ // look for com.antutu.ABenchMark for(String s: currentPhone.getMonitorList()){ if(s.equals(BENCHMARK_PACKAGE_NAME)){ foundBenchApk=true; break; } } if(foundBenchApk){ String[] args = {Platform.getInstance().getDefaultADBLocation(), "-s",currentPhone.getUID(),"shell", "am", "start", "-a","android.intent.action.VIEW","com.antutu.ABenchMark/.ABenchMarkStartBench"}; Process p; Runtime r =Runtime.getRuntime(); BufferedReader in=null; try { p = r.exec(args); } catch (IOException e) { Logger.getLogger(this.getClass() ).error("exception while executing benchmark:"+e.getMessage()); glassPane.stop(); return; } return; }else{ if( installing == false){ int result=JOptionPane.showConfirmDialog(null, "AnTuTu Benchmark application not found. Would you like to install it ?","alert",JOptionPane.OK_CANCEL_OPTION); if(result == JOptionPane.OK_OPTION){ installing=true; String[] args = {Platform.getInstance().getDefaultADBLocation(), "-s",currentPhone.getUID(),"shell", "am", "start", "market://details?id=com.antutu.ABenchMark"}; try { Runtime.getRuntime().exec(args); } catch (IOException e) { Logger.getLogger(this.getClass() ).error("exception while launching Play: "+e.getMessage()); glassPane.stop(); return; } }else{ glassPane.stop(); return; } }else{ try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } } } private void fetchResultFile() { BufferedWriter os = null; try { if(!(new File(outputDir).exists())){ boolean success = new File(outputDir).mkdir(); if (success) { Logger.getLogger(this.getClass() ).info(outputDir+" created"); } } File file = new File(outputFile); os = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file,true))); BufferedReader bufferedReader=null; Process process = null; Logger.getLogger(this.getClass() ).info("adb pull "); process = Runtime.getRuntime().exec(new String[]{Platform.getInstance().getDefaultADBLocation(), "-s",currentPhone.getUID(),"pull","/sdcard/.antutu/benchmark/history_scores/",outputDir}); Logger.getLogger(this.getClass() ).info("waitFor "+process); //process.waitFor(); bufferedReader = new BufferedReader( new InputStreamReader(process.getErrorStream())); String l; while( (l = bufferedReader.readLine()) != null){ Logger.getLogger(this.getClass() ).info(l); } } catch (IOException e) { Logger.getLogger(this.getClass() ).error(e); } Logger.getLogger(this.getClass() ).info("sorting"); File files[]=(new File(outputDir)).listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { String lowercaseName = name.toLowerCase(); if (lowercaseName.endsWith(".xml")) { return true; } else { return false; } } }); Arrays.sort(files, new Comparator<File>(){ public int compare(File f1, File f2) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH_mm_ss"); try { Date d1 = sdf.parse(f1.getName().substring(0,18)); Date d2 = sdf.parse(f2.getName().substring(0,18)); return d2.compareTo(d1); } catch (ParseException e) { Logger.getLogger(this.getClass() ).info("error while sorting "+e); } return 0; } }); File f=files[0]; Logger.getLogger(this.getClass() ).info(f.getAbsolutePath()); DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder; lblStatus.setText("saving results ..."); try { dBuilder = dbFactory.newDocumentBuilder(); Document doc = dBuilder.parse(f); doc.getDocumentElement().normalize(); if(doc.getDocumentElement().getNodeName().equals("scores")){ NodeList nList = doc.getElementsByTagName("item"); for (int temp = 0; temp < nList.getLength(); temp++) { Node nNode = nList.item(temp); if (nNode.getNodeType() == Node.ELEMENT_NODE) { Element eElement = (Element) nNode; os.write( eElement.getElementsByTagName("date").item(0).getTextContent()+","+ eElement.getElementsByTagName("model").item(0).getTextContent()+","+ eElement.getElementsByTagName("version").item(0).getTextContent()+","+ eElement.getElementsByTagName("memory").item(0).getTextContent()+","+ eElement.getElementsByTagName("integer").item(0).getTextContent()+","+ eElement.getElementsByTagName("float").item(0).getTextContent()+","+ eElement.getElementsByTagName("score2d").item(0).getTextContent()+","+ eElement.getElementsByTagName("score3d").item(0).getTextContent()+","+ eElement.getElementsByTagName("database").item(0).getTextContent()+","+ eElement.getElementsByTagName("sdwrite").item(0).getTextContent()+","+ eElement.getElementsByTagName("sdread").item(0).getTextContent()+","+ eElement.getElementsByTagName("score").item(0).getTextContent()+"\n" ); } } } os.close(); lblStatus.setText("results saved"); } catch (ParserConfigurationException e) { Logger.getLogger(this.getClass() ).error(e); } catch (SAXException e) { Logger.getLogger(this.getClass() ).error(e); } catch (IOException e) { Logger.getLogger(this.getClass() ).error(e); } initializeDataset(null,null); sbchart.fireChartChanged(); } /** * Create chart * @param dataset * @return */ private JFreeChart createChart(final CategoryDataset dataset) { JFreeChart stackedChart = ChartFactory.createStackedBarChart("Device performance summary", "Category", "Value", dataset, PlotOrientation.VERTICAL, true, true, false); CategoryPlot plot = (CategoryPlot) stackedChart.getPlot(); BarRenderer renderer = (BarRenderer) plot.getRenderer(); renderer.setDrawBarOutline(false); // set up gradient paints for series... GradientPaint gp0 = new GradientPaint(0.0f, 0.0f, Color.decode("#29A2C6"), 0.0f, 0.0f, Color.decode("#29A2C6").darker()); GradientPaint gp1 = new GradientPaint(0.0f, 0.0f, Color.decode("#73B66B"), 0.0f, 0.0f, Color.decode("#73B66B").darker()); GradientPaint gp2 = new GradientPaint(0.0f, 0.0f, Color.decode("#EE0000"), 0.0f, 0.0f, Color.decode("#EE0000").darker()); renderer.setSeriesPaint(0, gp0); renderer.setSeriesPaint(1, gp1); renderer.setSeriesPaint(2, gp2); renderer.setSeriesVisible(0, true); renderer.setMaximumBarWidth(.20); return stackedChart; } /** * Create dataset for chart in application usually get data from database * with JDBC or collection * * @return */ private void initializeDataset(List<String> devices, List<String> perfs) { try{ dataset.clear(); BufferedReader bReader =new BufferedReader(new FileReader(outputFile)); String s; bReader.readLine(); //skip first line while ((s=bReader.readLine())!=null){ //Logger.getLogger(this.getClass() ).debug(s); String datavalue [] = s.split(","); if(datavalue.length==12){ if(devices==null || (devices!=null && devices.contains(datavalue[1]))){ if(perfs==null || (perfs!=null && perfs.contains("cpu"))){ dataset.addValue(Float.parseFloat(datavalue[4]),"cpu",datavalue[1]); }else{ dataset.addValue(0,"cpu",datavalue[1]); } if(perfs==null || (perfs!=null && perfs.contains("mem"))){ dataset.addValue(Float.parseFloat(datavalue[3]),"mem",datavalue[1]); }else{ dataset.addValue(0,"mem",datavalue[1]); } if(perfs==null || (perfs!=null && perfs.contains("3d"))){ dataset.addValue(Float.parseFloat(datavalue[7]),"3d",datavalue[1]); }else{ dataset.addValue(0,"3d",datavalue[1]); } } if(!deviceListModel.contains(datavalue[1])){ deviceListModel.addElement(datavalue[1]); } } } bReader.close(); }catch(IOException e){ Logger.getLogger(this.getClass() ).error(e); } } }