1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.traceview; 18 19 import com.android.sdkstats.SdkStatsService; 20 21 import org.eclipse.jface.action.Action; 22 import org.eclipse.jface.action.MenuManager; 23 import org.eclipse.jface.window.ApplicationWindow; 24 import org.eclipse.swt.SWT; 25 import org.eclipse.swt.custom.SashForm; 26 import org.eclipse.swt.graphics.Color; 27 import org.eclipse.swt.graphics.Image; 28 import org.eclipse.swt.layout.GridData; 29 import org.eclipse.swt.layout.GridLayout; 30 import org.eclipse.swt.widgets.Composite; 31 import org.eclipse.swt.widgets.Control; 32 import org.eclipse.swt.widgets.Display; 33 import org.eclipse.swt.widgets.Shell; 34 35 import java.io.File; 36 import java.io.FileInputStream; 37 import java.io.FileNotFoundException; 38 import java.io.FileOutputStream; 39 import java.io.IOException; 40 import java.io.InputStream; 41 import java.nio.channels.FileChannel; 42 import java.util.HashMap; 43 import java.util.Properties; 44 45 public class MainWindow extends ApplicationWindow { 46 47 private final static String PING_NAME = "Traceview"; 48 49 private TraceReader mReader; 50 private String mTraceName; 51 52 // A global cache of string names. 53 public static HashMap<String, String> sStringCache = new HashMap<String, String>(); 54 MainWindow(String traceName, TraceReader reader)55 public MainWindow(String traceName, TraceReader reader) { 56 super(null); 57 mReader = reader; 58 mTraceName = traceName; 59 60 addMenuBar(); 61 } 62 run()63 public void run() { 64 setBlockOnOpen(true); 65 open(); 66 } 67 68 @Override configureShell(Shell shell)69 protected void configureShell(Shell shell) { 70 super.configureShell(shell); 71 shell.setText("Traceview: " + mTraceName); 72 73 InputStream in = getClass().getClassLoader().getResourceAsStream( 74 "icons/traceview-128.png"); 75 if (in != null) { 76 shell.setImage(new Image(shell.getDisplay(), in)); 77 } 78 79 shell.setBounds(100, 10, 1282, 900); 80 } 81 82 @Override createContents(Composite parent)83 protected Control createContents(Composite parent) { 84 ColorController.assignMethodColors(parent.getDisplay(), mReader.getMethods()); 85 SelectionController selectionController = new SelectionController(); 86 87 GridLayout gridLayout = new GridLayout(1, false); 88 gridLayout.marginWidth = 0; 89 gridLayout.marginHeight = 0; 90 gridLayout.horizontalSpacing = 0; 91 gridLayout.verticalSpacing = 0; 92 parent.setLayout(gridLayout); 93 94 Display display = parent.getDisplay(); 95 Color darkGray = display.getSystemColor(SWT.COLOR_DARK_GRAY); 96 97 // Create a sash form to separate the timeline view (on top) 98 // and the profile view (on bottom) 99 SashForm sashForm1 = new SashForm(parent, SWT.VERTICAL); 100 sashForm1.setBackground(darkGray); 101 sashForm1.SASH_WIDTH = 3; 102 GridData data = new GridData(GridData.FILL_BOTH); 103 sashForm1.setLayoutData(data); 104 105 // Create the timeline view 106 new TimeLineView(sashForm1, mReader, selectionController); 107 108 // Create the profile view 109 new ProfileView(sashForm1, mReader, selectionController); 110 return sashForm1; 111 } 112 113 @Override createMenuManager()114 protected MenuManager createMenuManager() { 115 MenuManager manager = super.createMenuManager(); 116 117 MenuManager viewMenu = new MenuManager("View"); 118 manager.add(viewMenu); 119 120 Action showPropertiesAction = new Action("Show Properties...") { 121 @Override 122 public void run() { 123 showProperties(); 124 } 125 }; 126 viewMenu.add(showPropertiesAction); 127 128 return manager; 129 } 130 showProperties()131 private void showProperties() { 132 PropertiesDialog dialog = new PropertiesDialog(getShell()); 133 dialog.setProperties(mReader.getProperties()); 134 dialog.open(); 135 } 136 137 /** 138 * Convert the old two-file format into the current concatenated one. 139 * 140 * @param base Base path of the two files, i.e. base.key and base.data 141 * @return Path to a temporary file that will be deleted on exit. 142 * @throws IOException 143 */ makeTempTraceFile(String base)144 private static String makeTempTraceFile(String base) throws IOException { 145 // Make a temporary file that will go away on exit and prepare to 146 // write into it. 147 File temp = File.createTempFile(base, ".trace"); 148 temp.deleteOnExit(); 149 FileChannel dstChannel = new FileOutputStream(temp).getChannel(); 150 151 // First copy the contents of the key file into our temp file. 152 FileChannel srcChannel = new FileInputStream(base + ".key").getChannel(); 153 long size = dstChannel.transferFrom(srcChannel, 0, srcChannel.size()); 154 srcChannel.close(); 155 156 // Then concatenate the data file. 157 srcChannel = new FileInputStream(base + ".data").getChannel(); 158 dstChannel.transferFrom(srcChannel, size, srcChannel.size()); 159 160 // Clean up. 161 srcChannel.close(); 162 dstChannel.close(); 163 164 // Return the path of the temp file. 165 return temp.getPath(); 166 } 167 168 /** 169 * Returns the tools revision number. 170 */ getRevision()171 private static String getRevision() { 172 Properties p = new Properties(); 173 try{ 174 String toolsdir = System.getProperty("com.android.traceview.toolsdir"); //$NON-NLS-1$ 175 File sourceProp; 176 if (toolsdir == null || toolsdir.length() == 0) { 177 sourceProp = new File("source.properties"); //$NON-NLS-1$ 178 } else { 179 sourceProp = new File(toolsdir, "source.properties"); //$NON-NLS-1$ 180 } 181 182 FileInputStream fis = null; 183 try { 184 fis = new FileInputStream(sourceProp); 185 p.load(fis); 186 } finally { 187 if (fis != null) { 188 try { 189 fis.close(); 190 } catch (IOException ignore) { 191 } 192 } 193 } 194 195 String revision = p.getProperty("Pkg.Revision"); //$NON-NLS-1$ 196 if (revision != null && revision.length() > 0) { 197 return revision; 198 } 199 } catch (FileNotFoundException e) { 200 // couldn't find the file? don't ping. 201 } catch (IOException e) { 202 // couldn't find the file? don't ping. 203 } 204 205 return null; 206 } 207 208 main(String[] args)209 public static void main(String[] args) { 210 TraceReader reader = null; 211 boolean regression = false; 212 213 // ping the usage server 214 215 String revision = getRevision(); 216 if (revision != null) { 217 new SdkStatsService().ping(PING_NAME, revision); 218 } 219 220 // Process command line arguments 221 int argc = 0; 222 int len = args.length; 223 while (argc < len) { 224 String arg = args[argc]; 225 if (arg.charAt(0) != '-') { 226 break; 227 } 228 if (arg.equals("-r")) { 229 regression = true; 230 } else { 231 break; 232 } 233 argc++; 234 } 235 if (argc != len - 1) { 236 System.out.printf("Usage: java %s [-r] trace%n", MainWindow.class.getName()); 237 System.out.printf(" -r regression only%n"); 238 return; 239 } 240 241 String traceName = args[len - 1]; 242 File file = new File(traceName); 243 if (file.exists() && file.isDirectory()) { 244 System.out.printf("Qemu trace files not supported yet.\n"); 245 System.exit(1); 246 // reader = new QtraceReader(traceName); 247 } else { 248 // If the filename as given doesn't exist... 249 if (!file.exists()) { 250 // Try appending .trace. 251 if (new File(traceName + ".trace").exists()) { 252 traceName = traceName + ".trace"; 253 // Next, see if it is the old two-file trace. 254 } else if (new File(traceName + ".data").exists() 255 && new File(traceName + ".key").exists()) { 256 try { 257 traceName = makeTempTraceFile(traceName); 258 } catch (IOException e) { 259 System.err.printf("cannot convert old trace file '%s'\n", traceName); 260 System.exit(1); 261 } 262 // Otherwise, give up. 263 } else { 264 System.err.printf("trace file '%s' not found\n", traceName); 265 System.exit(1); 266 } 267 } 268 269 try { 270 reader = new DmTraceReader(traceName, regression); 271 } catch (IOException e) { 272 System.err.printf("Failed to read the trace file"); 273 e.printStackTrace(); 274 System.exit(1); 275 return; 276 } 277 } 278 279 reader.getTraceUnits().setTimeScale(TraceUnits.TimeScale.MilliSeconds); 280 281 Display.setAppName("Traceview"); 282 new MainWindow(traceName, reader).run(); 283 } 284 } 285