diff options
Diffstat (limited to 'traceview')
29 files changed, 0 insertions, 5190 deletions
diff --git a/traceview/.classpath b/traceview/.classpath deleted file mode 100644 index e71cb61..0000000 --- a/traceview/.classpath +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<classpath> - <classpathentry kind="src" path="src"/> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> - <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANDROID_SWT"/> - <classpathentry combineaccessrules="false" kind="src" path="/SdkStatsService"/> - <classpathentry kind="output" path="bin"/> -</classpath> diff --git a/traceview/.project b/traceview/.project deleted file mode 100644 index 692297f..0000000 --- a/traceview/.project +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>traceview</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>org.eclipse.jdt.core.javabuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>org.eclipse.jdt.core.javanature</nature> - </natures> -</projectDescription> diff --git a/traceview/Android.mk b/traceview/Android.mk deleted file mode 100644 index 2ce7b80..0000000 --- a/traceview/Android.mk +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2007 The Android Open Source Project -# -TRACEVIEW_LOCAL_DIR := $(call my-dir) -include $(TRACEVIEW_LOCAL_DIR)/etc/Android.mk -include $(TRACEVIEW_LOCAL_DIR)/src/Android.mk diff --git a/traceview/README b/traceview/README deleted file mode 100644 index 6f4576a..0000000 --- a/traceview/README +++ /dev/null @@ -1,11 +0,0 @@ -Using the Eclipse projects for traceview. - -traceview requires SWT to compile. - -SWT is available in the depot under //device/prebuild/<platform>/swt - -Because the build path cannot contain relative path that are not inside the project directory, -the .classpath file references a user library called ANDROID_SWT. - -In order to compile the project, make a user library called ANDROID_SWT containing the jar -available at //device/prebuild/<platform>/swt. diff --git a/traceview/etc/Android.mk b/traceview/etc/Android.mk deleted file mode 100644 index f26b19e..0000000 --- a/traceview/etc/Android.mk +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2007 The Android Open Source Project -# -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_PREBUILT_EXECUTABLES := traceview -include $(BUILD_HOST_PREBUILT) - diff --git a/traceview/etc/manifest.txt b/traceview/etc/manifest.txt deleted file mode 100644 index 6cdbc7e..0000000 --- a/traceview/etc/manifest.txt +++ /dev/null @@ -1,2 +0,0 @@ -Main-Class: com.android.traceview.MainWindow -Class-Path: swt.jar org.eclipse.equinox.common_3.2.0.v20060603.jar org.eclipse.jface_3.2.0.I20060605-1400.jar org.eclipse.core.commands_3.2.0.I20060605-1400.jar diff --git a/traceview/etc/traceview b/traceview/etc/traceview deleted file mode 100755 index 1cc913d..0000000 --- a/traceview/etc/traceview +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/bash -# -# Copyright 2005-2006, The Android Open Source Project -# -# 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. - -# This script assumes that the path to this script is something like: -# -# /somepath/outdir/archdir/hostdir/bindir/traceview -# -# where "somepath" is some pathname (like "/work/android/device/") -# "outdir" is a subdirectory (like "out") -# "archdir" is a subdirectory (like "linux-x86-release") -# "hostdir" is a subdirectory (like "host") -# "bindir" is a subdirectory (like "bin") -# -# e.g. /work/android/device/out/linux-x86-release/host/bin/traceview -# -# and that the following directories also exist: -# -# /somepath/outdir/archdir/hostdir/lib/ -# /somepath/outdir/archdir/hostdir/framework/ -# -# where: -# "lib", and "framework" are at the same level as "bindir", -# and are the literal names. - -# Set up prog to be the path of this script, including following symlinks, -# and set up progdir to be the fully-qualified pathname of its directory. -prog="$0" -while [ -h "${prog}" ]; do - newProg=`/bin/ls -ld "${prog}"` - newProg=`expr "${newProg}" : ".* -> \(.*\)$"` - if expr "x${newProg}" : 'x/' >/dev/null; then - prog="${newProg}" - else - progdir=`dirname "${prog}"` - prog="${progdir}/${newProg}" - fi -done -oldwd=`pwd` -progdir=`dirname "${prog}"` -progname=`basename "${prog}"` -cd "${progdir}" -progdir=`pwd` -prog="${progdir}"/"${progname}" -cd "${oldwd}" - -jarfile=traceview.jar -frameworkdir="$progdir" -libdir="$progdir" -if [ ! -r "$frameworkdir/$jarfile" ] -then - frameworkdir=`dirname "$progdir"`/tools/lib - libdir=`dirname "$progdir"`/tools/lib -fi -if [ ! -r "$frameworkdir/$jarfile" ] -then - frameworkdir=`dirname "$progdir"`/framework - libdir=`dirname "$progdir"`/lib -fi -if [ ! -r "$frameworkdir/$jarfile" ] -then - echo "${progname}: can't find $jarfile" - exit 1 -fi - -os=`uname` -if [ $os == 'Darwin' ]; then - javaOpts="-Xmx1600M -XstartOnFirstThread" - javaCmd="/System/Library/Frameworks/JavaVM.framework/Versions/1.5/Commands/java" -else - javaOpts="-Xmx1600M" - javaCmd="java" -fi - -while expr "x$1" : 'x-J' >/dev/null; do - opt=`expr "$1" : '-J\(.*\)'` - javaOpts="${javaOpts} -${opt}" - shift -done - -if [ "$OSTYPE" = "cygwin" ] ; then - jarpath=`cygpath -w "$frameworkdir/$jarfile"` - progdir=`cygpath -w "$progdir"` -else - jarpath="$frameworkdir/$jarfile" -fi - - -exec "$javaCmd" $javaOpts -Djava.ext.dirs="$frameworkdir" -Djava.library.path="$libdir" -jar "$jarpath" "$@" diff --git a/traceview/etc/traceview.bat b/traceview/etc/traceview.bat deleted file mode 100755 index d074f42..0000000 --- a/traceview/etc/traceview.bat +++ /dev/null @@ -1,43 +0,0 @@ -@echo off -rem Copyright (C) 2007 The Android Open Source Project -rem -rem Licensed under the Apache License, Version 2.0 (the "License"); -rem you may not use this file except in compliance with the License. -rem You may obtain a copy of the License at -rem -rem http://www.apache.org/licenses/LICENSE-2.0 -rem -rem Unless required by applicable law or agreed to in writing, software -rem distributed under the License is distributed on an "AS IS" BASIS, -rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -rem See the License for the specific language governing permissions and -rem limitations under the License. - -rem don't modify the caller's environment -setlocal - -rem Set up prog to be the path of this script, including following symlinks, -rem and set up progdir to be the fully-qualified pathname of its directory. -set prog=%~f0 - -rem Change current directory to where traceview is, to avoid issues with directories -rem containing whitespaces. -cd %~dp0 - -set jarfile=traceview.jar -set frameworkdir= -set libdir= - -if exist %frameworkdir%%jarfile% goto JarFileOk - set frameworkdir=lib\ - set libdir=lib\ - -if exist %frameworkdir%%jarfile% goto JarFileOk - set frameworkdir=..\framework\ - set libdir=..\lib\ - -:JarFileOk - -set jarpath=%frameworkdir%%jarfile% - -java -Djava.ext.dirs=%frameworkdir% -Djava.library.path=%libdir% -jar %jarpath% %* diff --git a/traceview/src/Android.mk b/traceview/src/Android.mk deleted file mode 100644 index 7a006de..0000000 --- a/traceview/src/Android.mk +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2007 The Android Open Source Project -# -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_JAVA_RESOURCE_DIRS := resources - -LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_JAR_MANIFEST := ../etc/manifest.txt -LOCAL_JAVA_LIBRARIES := \ - androidprefs \ - sdkstats \ - swt \ - org.eclipse.jface_3.2.0.I20060605-1400 \ - org.eclipse.equinox.common_3.2.0.v20060603 \ - org.eclipse.core.commands_3.2.0.I20060605-1400 -LOCAL_MODULE := traceview - -include $(BUILD_HOST_JAVA_LIBRARY) diff --git a/traceview/src/com/android/traceview/Call.java b/traceview/src/com/android/traceview/Call.java deleted file mode 100644 index 40ac244..0000000 --- a/traceview/src/com/android/traceview/Call.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import org.eclipse.swt.graphics.Color; - -class Call implements TimeLineView.Block { - - // Values for bits within the mFlags field. - private static final int METHOD_ACTION_MASK = 0x3; - private static final int IS_RECURSIVE = 0x10; - - private int mThreadId; - private int mFlags; - MethodData mMethodData; - - /** 0-based thread-local start time */ - long mThreadStartTime; - - /** global start time */ - long mGlobalStartTime; - - /** global end time */ - long mGlobalEndTime; - - private String mName; - - /** - * This constructor is used for the root of a Call tree. The name is - * the name of the corresponding thread. - */ - Call(String name, MethodData methodData) { - mName = name; - mMethodData = methodData; - } - - Call() { - } - - Call(int threadId, MethodData methodData, long time, int methodAction) { - mThreadId = threadId; - mMethodData = methodData; - mThreadStartTime = time; - mFlags = methodAction & METHOD_ACTION_MASK; - mName = methodData.getProfileName(); - } - - public void set(int threadId, MethodData methodData, long time, int methodAction) { - mThreadId = threadId; - mMethodData = methodData; - mThreadStartTime = time; - mFlags = methodAction & METHOD_ACTION_MASK; - mName = methodData.getProfileName(); - } - - public void updateName() { - mName = mMethodData.getProfileName(); - } - - public double addWeight(int x, int y, double weight) { - return mMethodData.addWeight(x, y, weight); - } - - public void clearWeight() { - mMethodData.clearWeight(); - } - - public long getStartTime() { - return mGlobalStartTime; - } - - public long getEndTime() { - return mGlobalEndTime; - } - - public Color getColor() { - return mMethodData.getColor(); - } - - public void addExclusiveTime(long elapsed) { - mMethodData.addElapsedExclusive(elapsed); - if ((mFlags & IS_RECURSIVE) == 0) { - mMethodData.addTopExclusive(elapsed); - } - } - - public void addInclusiveTime(long elapsed, Call parent) { - boolean isRecursive = (mFlags & IS_RECURSIVE) != 0; - mMethodData.addElapsedInclusive(elapsed, isRecursive, parent); - } - - public String getName() { - return mName; - } - - public void setName(String name) { - mName = name; - } - - int getThreadId() { - return mThreadId; - } - - public MethodData getMethodData() { - return mMethodData; - } - - int getMethodAction() { - return mFlags & METHOD_ACTION_MASK; - } - - public void dump() { - System.out.printf("%s [%d, %d]\n", mName, mGlobalStartTime, mGlobalEndTime); - } - - public void setRecursive(boolean isRecursive) { - if (isRecursive) { - mFlags |= IS_RECURSIVE; - } else { - mFlags &= ~IS_RECURSIVE; - } - } - - public boolean isRecursive() { - return (mFlags & IS_RECURSIVE) != 0; - } -} diff --git a/traceview/src/com/android/traceview/ColorController.java b/traceview/src/com/android/traceview/ColorController.java deleted file mode 100644 index f5e4c0d..0000000 --- a/traceview/src/com/android/traceview/ColorController.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import java.util.HashMap; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.widgets.Display; - -public class ColorController { - private static final int[] systemColors = { SWT.COLOR_BLUE, SWT.COLOR_RED, - SWT.COLOR_GREEN, SWT.COLOR_CYAN, SWT.COLOR_MAGENTA, SWT.COLOR_DARK_BLUE, - SWT.COLOR_DARK_RED, SWT.COLOR_DARK_GREEN, SWT.COLOR_DARK_YELLOW, - SWT.COLOR_DARK_CYAN, SWT.COLOR_DARK_MAGENTA, SWT.COLOR_BLACK }; - - private static RGB[] rgbColors = { new RGB(90, 90, 255), // blue - new RGB(0, 240, 0), // green - new RGB(255, 0, 0), // red - new RGB(0, 255, 255), // cyan - new RGB(255, 80, 255), // magenta - new RGB(200, 200, 0), // yellow - new RGB(40, 0, 200), // dark blue - new RGB(150, 255, 150), // light green - new RGB(150, 0, 0), // dark red - new RGB(30, 150, 150), // dark cyan - new RGB(200, 200, 255), // light blue - new RGB(0, 120, 0), // dark green - new RGB(255, 150, 150), // light red - new RGB(140, 80, 140), // dark magenta - new RGB(150, 100, 50), // brown - new RGB(70, 70, 70), // dark grey - }; - - private static HashMap<Integer, Color> colorCache = new HashMap<Integer, Color>(); - private static HashMap<Integer, Image> imageCache = new HashMap<Integer, Image>(); - - public ColorController() { - } - - public static Color requestColor(Display display, RGB rgb) { - return requestColor(display, rgb.red, rgb.green, rgb.blue); - } - - public static Image requestColorSquare(Display display, RGB rgb) { - return requestColorSquare(display, rgb.red, rgb.green, rgb.blue); - } - - public static Color requestColor(Display display, int red, int green, int blue) { - int key = (red << 16) | (green << 8) | blue; - Color color = colorCache.get(key); - if (color == null) { - color = new Color(display, red, green, blue); - colorCache.put(key, color); - } - return color; - } - - public static Image requestColorSquare(Display display, int red, int green, int blue) { - int key = (red << 16) | (green << 8) | blue; - Image image = imageCache.get(key); - if (image == null) { - image = new Image(display, 8, 14); - GC gc = new GC(image); - Color color = requestColor(display, red, green, blue); - gc.setBackground(color); - gc.fillRectangle(image.getBounds()); - gc.dispose(); - imageCache.put(key, image); - } - return image; - } - - public static void assignMethodColors(Display display, MethodData[] methods) { - int nextColorIndex = 0; - for (MethodData md : methods) { - RGB rgb = rgbColors[nextColorIndex]; - if (++nextColorIndex == rgbColors.length) - nextColorIndex = 0; - Color color = requestColor(display, rgb); - Image image = requestColorSquare(display, rgb); - md.setColor(color); - md.setImage(image); - - // Compute and set a faded color - int fadedRed = 150 + rgb.red / 4; - int fadedGreen = 150 + rgb.green / 4; - int fadedBlue = 150 + rgb.blue / 4; - RGB faded = new RGB(fadedRed, fadedGreen, fadedBlue); - color = requestColor(display, faded); - image = requestColorSquare(display, faded); - md.setFadedColor(color); - md.setFadedImage(image); - } - } -} diff --git a/traceview/src/com/android/traceview/DmTraceReader.java b/traceview/src/com/android/traceview/DmTraceReader.java deleted file mode 100644 index 5a19c19..0000000 --- a/traceview/src/com/android/traceview/DmTraceReader.java +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.nio.BufferUnderflowException; -import java.nio.ByteOrder; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class DmTraceReader extends TraceReader { - - private int mVersionNumber = 0; - private boolean mDebug = false; - private static final int TRACE_MAGIC = 0x574f4c53; - private boolean mRegression; - private ProfileProvider mProfileProvider; - private String mTraceFileName; - private MethodData mTopLevel; - private ArrayList<Call> mCallList; - private ArrayList<Call> mSwitchList; - private HashMap<Integer, MethodData> mMethodMap; - private HashMap<Integer, ThreadData> mThreadMap; - private ThreadData[] mSortedThreads; - private MethodData[] mSortedMethods; - private long mGlobalEndTime; - private MethodData mContextSwitch; - private int mOffsetToData; - private byte[] mBytes = new byte[8]; - - // A regex for matching the thread "id name" lines in the .key file - private static final Pattern mIdNamePattern = Pattern.compile("(\\d+)\t(.*)"); // $NON-NLS-1$ - - DmTraceReader(String traceFileName, boolean regression) { - mTraceFileName = traceFileName; - mRegression = regression; - mMethodMap = new HashMap<Integer, MethodData>(); - mThreadMap = new HashMap<Integer, ThreadData>(); - - // Create a single top-level MethodData object to hold the profile data - // for time spent in the unknown caller. - mTopLevel = new MethodData(0, "(toplevel)"); - mContextSwitch = new MethodData(-1, "(context switch)"); - mMethodMap.put(0, mTopLevel); - generateTrees(); - // dumpTrees(); - } - - void generateTrees() { - try { - long offset = parseKeys(); - parseData(offset); - analyzeData(); - } catch (IOException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - - @Override - public ProfileProvider getProfileProvider() { - if (mProfileProvider == null) - mProfileProvider = new ProfileProvider(this); - return mProfileProvider; - } - - Call readCall(MappedByteBuffer buffer, Call call) { - int threadId; - int methodId; - long time; - - try { - if (mVersionNumber == 1) - threadId = buffer.get(); - else - threadId = buffer.getShort(); - methodId = buffer.getInt(); - time = buffer.getInt(); - } catch (BufferUnderflowException ex) { - return null; - } - - int methodAction = methodId & 0x03; - methodId = methodId & ~0x03; - MethodData methodData = mMethodMap.get(methodId); - if (methodData == null) { - String name = String.format("(0x%1$x)", methodId); // $NON-NLS-1$ - methodData = new MethodData(methodId, name); - } - - if (call != null) { - call.set(threadId, methodData, time, methodAction); - } else { - call = new Call(threadId, methodData, time, methodAction); - } - return call; - } - - private MappedByteBuffer mapFile(String filename, long offset) { - MappedByteBuffer buffer = null; - try { - FileInputStream dataFile = new FileInputStream(filename); - File file = new File(filename); - FileChannel fc = dataFile.getChannel(); - buffer = fc.map(FileChannel.MapMode.READ_ONLY, offset, file.length() - offset); - buffer.order(ByteOrder.LITTLE_ENDIAN); - } catch (FileNotFoundException ex) { - System.err.println(ex.getMessage()); - System.exit(1); - } catch (IOException ex) { - System.err.println(ex.getMessage()); - System.exit(1); - } - - return buffer; - } - - private void readDataFileHeader(MappedByteBuffer buffer) { - int magic = buffer.getInt(); - if (magic != TRACE_MAGIC) { - System.err.printf( - "Error: magic number mismatch; got 0x%x, expected 0x%x\n", - magic, TRACE_MAGIC); - throw new RuntimeException(); - } - // read version - int version = buffer.getShort(); - - // read offset - mOffsetToData = buffer.getShort() - 16; - - // read startWhen - buffer.getLong(); - - // Skip over "mOffsetToData" bytes - for (int ii = 0; ii < mOffsetToData; ii++) { - buffer.get(); - } - - // Save this position so that we can re-read the data later - buffer.mark(); - } - - private void parseData(long offset) { - MappedByteBuffer buffer = mapFile(mTraceFileName, offset); - readDataFileHeader(buffer); - parseDataPass1(buffer); - - buffer.reset(); - parseDataPass2(buffer); - } - - private void parseDataPass1(MappedByteBuffer buffer) { - mSwitchList = new ArrayList<Call>(); - - // Read the first call so that we can set "prevThreadData" - Call call = new Call(); - call = readCall(buffer, call); - if (call == null) - return; - long callTime = call.mThreadStartTime; - long prevCallTime = 0; - ThreadData threadData = mThreadMap.get(call.getThreadId()); - if (threadData == null) { - String name = String.format("[%1$d]", call.getThreadId()); // $NON-NLS-1$ - threadData = new ThreadData(call.getThreadId(), name, mTopLevel); - mThreadMap.put(call.getThreadId(), threadData); - } - ThreadData prevThreadData = threadData; - while (true) { - // If a context switch occurred, then insert a placeholder "call" - // record so that we can do something reasonable with the global - // timestamps. - if (prevThreadData != threadData) { - Call switchEnter = new Call(prevThreadData.getId(), - mContextSwitch, prevCallTime, 0); - prevThreadData.setLastContextSwitch(switchEnter); - mSwitchList.add(switchEnter); - Call contextSwitch = threadData.getLastContextSwitch(); - if (contextSwitch != null) { - long prevStartTime = contextSwitch.mThreadStartTime; - long elapsed = callTime - prevStartTime; - long beforeSwitch = elapsed / 2; - long afterSwitch = elapsed - beforeSwitch; - long exitTime = callTime - afterSwitch; - contextSwitch.mThreadStartTime = prevStartTime + beforeSwitch; - Call switchExit = new Call(threadData.getId(), - mContextSwitch, exitTime, 1); - - mSwitchList.add(switchExit); - } - prevThreadData = threadData; - } - - // Read the next call - call = readCall(buffer, call); - if (call == null) { - break; - } - prevCallTime = callTime; - callTime = call.mThreadStartTime; - - threadData = mThreadMap.get(call.getThreadId()); - if (threadData == null) { - String name = String.format("[%d]", call.getThreadId()); - threadData = new ThreadData(call.getThreadId(), name, mTopLevel); - mThreadMap.put(call.getThreadId(), threadData); - } - } - } - - void parseDataPass2(MappedByteBuffer buffer) { - mCallList = new ArrayList<Call>(); - - // Read the first call so that we can set "prevThreadData" - Call call = readCall(buffer, null); - long callTime = call.mThreadStartTime; - long prevCallTime = callTime; - ThreadData threadData = mThreadMap.get(call.getThreadId()); - ThreadData prevThreadData = threadData; - threadData.setGlobalStartTime(0); - - int nthContextSwitch = 0; - - // Assign a global timestamp to each event. - long globalTime = 0; - while (true) { - long elapsed = callTime - prevCallTime; - if (threadData != prevThreadData) { - // Get the next context switch. This one is entered - // by the previous thread. - Call contextSwitch = mSwitchList.get(nthContextSwitch++); - mCallList.add(contextSwitch); - elapsed = contextSwitch.mThreadStartTime - prevCallTime; - globalTime += elapsed; - elapsed = 0; - contextSwitch.mGlobalStartTime = globalTime; - prevThreadData.handleCall(contextSwitch, globalTime); - - if (!threadData.isEmpty()) { - // This context switch is exited by the current thread. - contextSwitch = mSwitchList.get(nthContextSwitch++); - mCallList.add(contextSwitch); - contextSwitch.mGlobalStartTime = globalTime; - elapsed = callTime - contextSwitch.mThreadStartTime; - threadData.handleCall(contextSwitch, globalTime); - } - - // If the thread's global start time has not been set yet, - // then set it. - if (threadData.getGlobalStartTime() == -1) - threadData.setGlobalStartTime(globalTime); - prevThreadData = threadData; - } - - globalTime += elapsed; - call.mGlobalStartTime = globalTime; - - threadData.handleCall(call, globalTime); - mCallList.add(call); - - // Read the next call - call = readCall(buffer, null); - if (call == null) { - break; - } - prevCallTime = callTime; - callTime = call.mThreadStartTime; - threadData = mThreadMap.get(call.getThreadId()); - } - - // Allow each thread to do any cleanup of the call stack. - // Also add the elapsed time for each thread to the toplevel - // method's inclusive time. - for (int id : mThreadMap.keySet()) { - threadData = mThreadMap.get(id); - long endTime = threadData.endTrace(); - if (endTime > 0) - mTopLevel.addElapsedInclusive(endTime, false, null); - } - - mGlobalEndTime = globalTime; - - if (mRegression) { - dumpCallTimes(); - } - } - - static final int PARSE_VERSION = 0; - static final int PARSE_THREADS = 1; - static final int PARSE_METHODS = 2; - static final int PARSE_OPTIONS = 4; - - long parseKeys() throws IOException { - BufferedReader in = null; - try { - in = new BufferedReader(new FileReader(mTraceFileName)); - } catch (FileNotFoundException ex) { - System.err.println(ex.getMessage()); - } - - long offset = 0; - int mode = PARSE_VERSION; - String line = null; - while (true) { - line = in.readLine(); - if (line == null) { - throw new IOException("Key section does not have an *end marker"); - } - - // Calculate how much we have read from the file so far. The - // extra byte is for the line ending not included by readLine(). - offset += line.length() + 1; - if (line.startsWith("*")) { - if (line.equals("*version")) { - mode = PARSE_VERSION; - continue; - } - if (line.equals("*threads")) { - mode = PARSE_THREADS; - continue; - } - if (line.equals("*methods")) { - mode = PARSE_METHODS; - continue; - } - if (line.equals("*end")) { - return offset; - } - } - switch (mode) { - case PARSE_VERSION: - mVersionNumber = Integer.decode(line); - mode = PARSE_OPTIONS; - break; - case PARSE_THREADS: - parseThread(line); - break; - case PARSE_METHODS: - parseMethod(line); - break; - case PARSE_OPTIONS: - break; - } - } - } - - void parseThread(String line) { - String idStr = null; - String name = null; - Matcher matcher = mIdNamePattern.matcher(line); - if (matcher.find()) { - idStr = matcher.group(1); - name = matcher.group(2); - } - if (idStr == null) return; - if (name == null) name = "(unknown)"; - - int id = Integer.decode(idStr); - mThreadMap.put(id, new ThreadData(id, name, mTopLevel)); - } - - void parseMethod(String line) { - String[] tokens = line.split("\t"); - int id = Long.decode(tokens[0]).intValue(); - String className = tokens[1]; - String methodName = null; - String signature = null; - String pathname = null; - int lineNumber = -1; - if (tokens.length == 6) { - methodName = tokens[2]; - signature = tokens[3]; - pathname = tokens[4]; - lineNumber = Integer.decode(tokens[5]); - pathname = constructPathname(className, pathname); - } else if (tokens.length > 2) { - if (tokens[3].startsWith("(")) { - methodName = tokens[2]; - signature = tokens[3]; - } else { - pathname = tokens[2]; - lineNumber = Integer.decode(tokens[3]); - } - } - - mMethodMap.put(id, new MethodData(id, className, methodName, signature, - pathname, lineNumber)); - } - - private String constructPathname(String className, String pathname) { - int index = className.lastIndexOf('/'); - if (index > 0 && index < className.length() - 1 - && pathname.endsWith(".java")) - pathname = className.substring(0, index + 1) + pathname; - return pathname; - } - - private void analyzeData() { - // Sort the threads into decreasing cpu time - Collection<ThreadData> tv = mThreadMap.values(); - mSortedThreads = tv.toArray(new ThreadData[tv.size()]); - Arrays.sort(mSortedThreads, new Comparator<ThreadData>() { - public int compare(ThreadData td1, ThreadData td2) { - if (td2.getCpuTime() > td1.getCpuTime()) - return 1; - if (td2.getCpuTime() < td1.getCpuTime()) - return -1; - return td2.getName().compareTo(td1.getName()); - } - }); - - // Analyze the call tree so that we can label the "worst" children. - // Also set all the root pointers in each node in the call tree. - long sum = 0; - for (ThreadData t : mSortedThreads) { - if (t.isEmpty() == false) { - Call root = t.getCalltreeRoot(); - root.mGlobalStartTime = t.getGlobalStartTime(); - } - } - - // Sort the methods into decreasing inclusive time - Collection<MethodData> mv = mMethodMap.values(); - MethodData[] methods; - methods = mv.toArray(new MethodData[mv.size()]); - Arrays.sort(methods, new Comparator<MethodData>() { - public int compare(MethodData md1, MethodData md2) { - if (md2.getElapsedInclusive() > md1.getElapsedInclusive()) - return 1; - if (md2.getElapsedInclusive() < md1.getElapsedInclusive()) - return -1; - return md1.getName().compareTo(md2.getName()); - } - }); - - // Count the number of methods with non-zero inclusive time - int nonZero = 0; - for (MethodData md : methods) { - if (md.getElapsedInclusive() == 0) - break; - nonZero += 1; - } - - // Copy the methods with non-zero time - mSortedMethods = new MethodData[nonZero]; - int ii = 0; - for (MethodData md : methods) { - if (md.getElapsedInclusive() == 0) - break; - md.setRank(ii); - mSortedMethods[ii++] = md; - } - - // Let each method analyze its profile data - for (MethodData md : mSortedMethods) { - md.analyzeData(); - } - - // Update all the calls to include the method rank in - // their name. - for (Call call : mCallList) { - call.updateName(); - } - - if (mRegression) { - dumpMethodStats(); - } - } - - /* - * This method computes a list of records that describe the the execution - * timeline for each thread. Each record is a pair: (row, block) where: row: - * is the ThreadData object block: is the call (containing the start and end - * times) - */ - @Override - public ArrayList<TimeLineView.Record> getThreadTimeRecords() { - TimeLineView.Record record; - ArrayList<TimeLineView.Record> timeRecs; - timeRecs = new ArrayList<TimeLineView.Record>(); - - // For each thread, push a "toplevel" call that encompasses the - // entire execution of the thread. - for (ThreadData threadData : mSortedThreads) { - if (!threadData.isEmpty() && threadData.getId() != 0) { - Call call = new Call(threadData.getId(), mTopLevel, - threadData.getGlobalStartTime(), 0); - call.mGlobalStartTime = threadData.getGlobalStartTime(); - call.mGlobalEndTime = threadData.getGlobalEndTime(); - record = new TimeLineView.Record(threadData, call); - timeRecs.add(record); - } - } - - for (Call call : mCallList) { - if (call.getMethodAction() != 0 || call.getThreadId() == 0) - continue; - ThreadData threadData = mThreadMap.get(call.getThreadId()); - record = new TimeLineView.Record(threadData, call); - timeRecs.add(record); - } - - if (mRegression) { - dumpTimeRecs(timeRecs); - System.exit(0); - } - return timeRecs; - } - - private void dumpCallTimes() { - String action; - - System.out.format("id thread global start,end method\n"); - for (Call call : mCallList) { - if (call.getMethodAction() == 0) { - action = "+"; - } else { - action = " "; - } - long callTime = call.mThreadStartTime; - System.out.format("%2d %6d %8d %8d %s %s\n", - call.getThreadId(), callTime, call.mGlobalStartTime, - call.mGlobalEndTime, action, call.getMethodData().getName()); -// if (call.getMethodAction() == 0 && call.getGlobalEndTime() < call.getGlobalStartTime()) { -// System.out.printf("endtime %d < startTime %d\n", -// call.getGlobalEndTime(), call.getGlobalStartTime()); -// } - } - } - - private void dumpMethodStats() { - System.out.format("\nExclusive Inclusive Calls Method\n"); - for (MethodData md : mSortedMethods) { - System.out.format("%9d %9d %9s %s\n", - md.getElapsedExclusive(), md.getElapsedInclusive(), - md.getCalls(), md.getProfileName()); - } - } - - private void dumpTimeRecs(ArrayList<TimeLineView.Record> timeRecs) { - System.out.format("\nid thread global start,end method\n"); - for (TimeLineView.Record record : timeRecs) { - Call call = (Call) record.block; - long callTime = call.mThreadStartTime; - System.out.format("%2d %6d %8d %8d %s\n", - call.getThreadId(), callTime, - call.mGlobalStartTime, call.mGlobalEndTime, - call.getMethodData().getName()); - } - } - - @Override - public HashMap<Integer, String> getThreadLabels() { - HashMap<Integer, String> labels = new HashMap<Integer, String>(); - for (ThreadData t : mThreadMap.values()) { - labels.put(t.getId(), t.getName()); - } - return labels; - } - - @Override - public MethodData[] getMethods() { - return mSortedMethods; - } - - @Override - public ThreadData[] getThreads() { - return mSortedThreads; - } - - @Override - public long getEndTime() { - return mGlobalEndTime; - } -} diff --git a/traceview/src/com/android/traceview/MainWindow.java b/traceview/src/com/android/traceview/MainWindow.java deleted file mode 100644 index b0c24e9..0000000 --- a/traceview/src/com/android/traceview/MainWindow.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import com.android.sdkstats.SdkStatsService; - -import org.eclipse.jface.window.ApplicationWindow; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -import java.io.File; -import java.io.IOException; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.nio.channels.FileChannel; -import java.util.HashMap; - -public class MainWindow extends ApplicationWindow { - - private final static String PING_NAME = "Traceview"; - private final static String PING_VERSION = "1.0"; - - private TraceReader mReader; - private String mTraceName; - - // A global cache of string names. - public static HashMap<String, String> sStringCache = new HashMap<String, String>(); - - public MainWindow(String traceName, TraceReader reader) { - super(null); - mReader = reader; - mTraceName = traceName; - } - - public void run() { - setBlockOnOpen(true); - open(); - Display.getCurrent().dispose(); - } - - @Override - protected void configureShell(Shell shell) { - super.configureShell(shell); - shell.setText("Traceview: " + mTraceName); - shell.setBounds(100, 10, 1282, 900); - } - - @Override - protected Control createContents(Composite parent) { - ColorController.assignMethodColors(parent.getDisplay(), mReader.getMethods()); - SelectionController selectionController = new SelectionController(); - - GridLayout gridLayout = new GridLayout(1, false); - gridLayout.marginWidth = 0; - gridLayout.marginHeight = 0; - gridLayout.horizontalSpacing = 0; - gridLayout.verticalSpacing = 0; - parent.setLayout(gridLayout); - - Display display = parent.getDisplay(); - Color darkGray = display.getSystemColor(SWT.COLOR_DARK_GRAY); - - // Create a sash form to separate the timeline view (on top) - // and the profile view (on bottom) - SashForm sashForm1 = new SashForm(parent, SWT.VERTICAL); - sashForm1.setBackground(darkGray); - sashForm1.SASH_WIDTH = 3; - GridData data = new GridData(GridData.FILL_BOTH); - sashForm1.setLayoutData(data); - - // Create the timeline view - new TimeLineView(sashForm1, mReader, selectionController); - - // Create the profile view - new ProfileView(sashForm1, mReader, selectionController); - return sashForm1; - } - - /** - * Convert the old two-file format into the current concatenated one. - * - * @param base Base path of the two files, i.e. base.key and base.data - * @return Path to a temporary file that will be deleted on exit. - * @throws IOException - */ - private static String makeTempTraceFile(String base) throws IOException { - // Make a temporary file that will go away on exit and prepare to - // write into it. - File temp = File.createTempFile(base, ".trace"); - temp.deleteOnExit(); - FileChannel dstChannel = new FileOutputStream(temp).getChannel(); - - // First copy the contents of the key file into our temp file. - FileChannel srcChannel = new FileInputStream(base + ".key").getChannel(); - long size = dstChannel.transferFrom(srcChannel, 0, srcChannel.size()); - srcChannel.close(); - - // Then concatenate the data file. - srcChannel = new FileInputStream(base + ".data").getChannel(); - dstChannel.transferFrom(srcChannel, size, srcChannel.size()); - - // Clean up. - srcChannel.close(); - dstChannel.close(); - - // Return the path of the temp file. - return temp.getPath(); - } - - public static void main(String[] args) { - TraceReader reader = null; - boolean regression = false; - - // ping the usage server - SdkStatsService.ping(PING_NAME, PING_VERSION); - - // Process command line arguments - int argc = 0; - int len = args.length; - while (argc < len) { - String arg = args[argc]; - if (arg.charAt(0) != '-') { - break; - } - if (arg.equals("-r")) { - regression = true; - } else { - break; - } - argc++; - } - if (argc != len - 1) { - System.out.printf("Usage: java %s [-r] trace%n", MainWindow.class.getName()); - System.out.printf(" -r regression only%n"); - return; - } - - String traceName = args[len - 1]; - File file = new File(traceName); - if (file.exists() && file.isDirectory()) { - System.out.printf("Qemu trace files not supported yet.\n"); - System.exit(1); - // reader = new QtraceReader(traceName); - } else { - // If the filename as given doesn't exist... - if (!file.exists()) { - // Try appending .trace. - if (new File(traceName + ".trace").exists()) { - traceName = traceName + ".trace"; - // Next, see if it is the old two-file trace. - } else if (new File(traceName + ".data").exists() - && new File(traceName + ".key").exists()) { - try { - traceName = makeTempTraceFile(traceName); - } catch (IOException e) { - System.err.printf("cannot convert old trace file '%s'\n", traceName); - System.exit(1); - } - // Otherwise, give up. - } else { - System.err.printf("trace file '%s' not found\n", traceName); - System.exit(1); - } - } - - reader = new DmTraceReader(traceName, regression); - } - reader.getTraceUnits().setTimeScale(TraceUnits.TimeScale.MilliSeconds); - new MainWindow(traceName, reader).run(); - } -} diff --git a/traceview/src/com/android/traceview/MethodData.java b/traceview/src/com/android/traceview/MethodData.java deleted file mode 100644 index 0bc9853..0000000 --- a/traceview/src/com/android/traceview/MethodData.java +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Image; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; - -public class MethodData { - - private int mId; - private int mRank = -1; - private String mClassName; - private String mMethodName; - private String mSignature; - private String mName; - private String mProfileName; - private String mPathname; - private int mLineNumber; - private long mElapsedExclusive; - private long mElapsedInclusive; - private long mTopExclusive; - private int[] mNumCalls = new int[2]; // index 0=normal, 1=recursive - private Color mColor; - private Color mFadedColor; - private Image mImage; - private Image mFadedImage; - private HashMap<Integer, ProfileData> mParents; - private HashMap<Integer, ProfileData> mChildren; - - // The parents of this method when this method was in a recursive call - private HashMap<Integer, ProfileData> mRecursiveParents; - - // The children of this method when this method was in a recursive call - private HashMap<Integer, ProfileData> mRecursiveChildren; - - private ProfileNode[] mProfileNodes; - private int mX; - private int mY; - private double mWeight; - - public MethodData(int id, String className) { - mId = id; - mClassName = className; - mMethodName = null; - mSignature = null; - mPathname = null; - mLineNumber = -1; - computeName(); - computeProfileName(); - } - - public MethodData(int id, String className, String methodName, - String signature, String pathname, int lineNumber) { - mId = id; - mClassName = className; - mMethodName = methodName; - mSignature = signature; - mPathname = pathname; - mLineNumber = lineNumber; - computeName(); - computeProfileName(); - } - - private Comparator<ProfileData> mByElapsedInclusive = new Comparator<ProfileData>() { - public int compare(ProfileData pd1, ProfileData pd2) { - if (pd2.getElapsedInclusive() > pd1.getElapsedInclusive()) - return 1; - if (pd2.getElapsedInclusive() < pd1.getElapsedInclusive()) - return -1; - return 0; - } - }; - - public double addWeight(int x, int y, double weight) { - if (mX == x && mY == y) - mWeight += weight; - else { - mX = x; - mY = y; - mWeight = weight; - } - return mWeight; - } - - public void clearWeight() { - mWeight = 0; - } - - public int getRank() { - return mRank; - } - - public void setRank(int rank) { - mRank = rank; - computeProfileName(); - } - - public void addElapsedExclusive(long time) { - mElapsedExclusive += time; - } - - public void addElapsedInclusive(long time, boolean isRecursive, Call parent) { - if (isRecursive == false) { - mElapsedInclusive += time; - mNumCalls[0] += 1; - } else { - mNumCalls[1] += 1; - } - - if (parent == null) - return; - - // Find the child method in the parent - MethodData parentMethod = parent.mMethodData; - if (parent.isRecursive()) { - parentMethod.mRecursiveChildren = updateInclusive(time, - parentMethod, this, false, - parentMethod.mRecursiveChildren); - } else { - parentMethod.mChildren = updateInclusive(time, - parentMethod, this, false, parentMethod.mChildren); - } - - // Find the parent method in the child - if (isRecursive) { - mRecursiveParents = updateInclusive(time, this, parentMethod, true, - mRecursiveParents); - } else { - mParents = updateInclusive(time, this, parentMethod, true, - mParents); - } - } - - private HashMap<Integer, ProfileData> updateInclusive(long time, - MethodData contextMethod, MethodData elementMethod, - boolean elementIsParent, HashMap<Integer, ProfileData> map) { - if (map == null) { - map = new HashMap<Integer, ProfileData>(4); - } else { - ProfileData profileData = map.get(elementMethod.mId); - if (profileData != null) { - profileData.addElapsedInclusive(time); - return map; - } - } - - ProfileData elementData = new ProfileData(contextMethod, - elementMethod, elementIsParent); - elementData.setElapsedInclusive(time); - elementData.setNumCalls(1); - map.put(elementMethod.mId, elementData); - return map; - } - - public void analyzeData() { - // Sort the parents and children into decreasing inclusive time - ProfileData[] sortedParents; - ProfileData[] sortedChildren; - ProfileData[] sortedRecursiveParents; - ProfileData[] sortedRecursiveChildren; - - sortedParents = sortProfileData(mParents); - sortedChildren = sortProfileData(mChildren); - sortedRecursiveParents = sortProfileData(mRecursiveParents); - sortedRecursiveChildren = sortProfileData(mRecursiveChildren); - - // Add "self" time to the top of the sorted children - sortedChildren = addSelf(sortedChildren); - - // Create the ProfileNode objects that we need - ArrayList<ProfileNode> nodes = new ArrayList<ProfileNode>(); - ProfileNode profileNode; - if (mParents != null) { - profileNode = new ProfileNode("Parents", this, sortedParents, - true, false); - nodes.add(profileNode); - } - if (mChildren != null) { - profileNode = new ProfileNode("Children", this, sortedChildren, - false, false); - nodes.add(profileNode); - } - if (mRecursiveParents!= null) { - profileNode = new ProfileNode("Parents while recursive", this, - sortedRecursiveParents, true, true); - nodes.add(profileNode); - } - if (mRecursiveChildren != null) { - profileNode = new ProfileNode("Children while recursive", this, - sortedRecursiveChildren, false, true); - nodes.add(profileNode); - } - mProfileNodes = nodes.toArray(new ProfileNode[nodes.size()]); - } - - // Create and return a ProfileData[] array that is a sorted copy - // of the given HashMap values. - private ProfileData[] sortProfileData(HashMap<Integer, ProfileData> map) { - if (map == null) - return null; - - // Convert the hash values to an array of ProfileData - Collection<ProfileData> values = map.values(); - ProfileData[] sorted = values.toArray(new ProfileData[values.size()]); - - // Sort the array by elapsed inclusive time - Arrays.sort(sorted, mByElapsedInclusive); - return sorted; - } - - private ProfileData[] addSelf(ProfileData[] children) { - ProfileData[] pdata; - if (children == null) { - pdata = new ProfileData[1]; - } else { - pdata = new ProfileData[children.length + 1]; - System.arraycopy(children, 0, pdata, 1, children.length); - } - pdata[0] = new ProfileSelf(this); - return pdata; - } - - public void addTopExclusive(long time) { - mTopExclusive += time; - } - - public long getTopExclusive() { - return mTopExclusive; - } - - public int getId() { - return mId; - } - - private void computeName() { - if (mMethodName == null) { - mName = mClassName; - return; - } - - StringBuilder sb = new StringBuilder(); - sb.append(mClassName); - sb.append("."); //$NON-NLS-1$ - sb.append(mMethodName); - sb.append(" "); //$NON-NLS-1$ - sb.append(mSignature); - mName = sb.toString(); - } - - public String getName() { - return mName; - } - - public String getClassName() { - return mClassName; - } - - public String getMethodName() { - return mMethodName; - } - - public String getProfileName() { - return mProfileName; - } - - public void computeProfileName() { - if (mRank == -1) { - mProfileName = mName; - return; - } - - StringBuilder sb = new StringBuilder(); - sb.append(mRank); - sb.append(" "); //$NON-NLS-1$ - sb.append(getName()); - mProfileName = sb.toString(); - } - - public String getCalls() { - return String.format("%d+%d", mNumCalls[0], mNumCalls[1]); - } - - public int getTotalCalls() { - return mNumCalls[0] + mNumCalls[1]; - } - - public Color getColor() { - return mColor; - } - - public void setColor(Color color) { - mColor = color; - } - - public void setImage(Image image) { - mImage = image; - } - - public Image getImage() { - return mImage; - } - - @Override - public String toString() { - return getName(); - } - - public long getElapsedExclusive() { - return mElapsedExclusive; - } - - public long getElapsedInclusive() { - return mElapsedInclusive; - } - - public void setFadedColor(Color fadedColor) { - mFadedColor = fadedColor; - } - - public Color getFadedColor() { - return mFadedColor; - } - - public void setFadedImage(Image fadedImage) { - mFadedImage = fadedImage; - } - - public Image getFadedImage() { - return mFadedImage; - } - - public void setPathname(String pathname) { - mPathname = pathname; - } - - public String getPathname() { - return mPathname; - } - - public void setLineNumber(int lineNumber) { - mLineNumber = lineNumber; - } - - public int getLineNumber() { - return mLineNumber; - } - - public ProfileNode[] getProfileNodes() { - return mProfileNodes; - } - - public static class Sorter implements Comparator<MethodData> { - public int compare(MethodData md1, MethodData md2) { - if (mColumn == Column.BY_NAME) { - int result = md1.getName().compareTo(md2.getName()); - return (mDirection == Direction.INCREASING) ? result : -result; - } - if (mColumn == Column.BY_INCLUSIVE) { - if (md2.getElapsedInclusive() > md1.getElapsedInclusive()) - return (mDirection == Direction.INCREASING) ? -1 : 1; - if (md2.getElapsedInclusive() < md1.getElapsedInclusive()) - return (mDirection == Direction.INCREASING) ? 1 : -1; - return md1.getName().compareTo(md2.getName()); - } - if (mColumn == Column.BY_EXCLUSIVE) { - if (md2.getElapsedExclusive() > md1.getElapsedExclusive()) - return (mDirection == Direction.INCREASING) ? -1 : 1; - if (md2.getElapsedExclusive() < md1.getElapsedExclusive()) - return (mDirection == Direction.INCREASING) ? 1 : -1; - return md1.getName().compareTo(md2.getName()); - } - if (mColumn == Column.BY_CALLS) { - int result = md1.getTotalCalls() - md2.getTotalCalls(); - if (result == 0) - return md1.getName().compareTo(md2.getName()); - return (mDirection == Direction.INCREASING) ? result : -result; - } - if (mColumn == Column.BY_TIME_PER_CALL) { - double time1 = md1.getElapsedInclusive(); - time1 = time1 / md1.getTotalCalls(); - double time2 = md2.getElapsedInclusive(); - time2 = time2 / md2.getTotalCalls(); - double diff = time1 - time2; - int result = 0; - if (diff < 0) - result = -1; - else if (diff > 0) - result = 1; - if (result == 0) - return md1.getName().compareTo(md2.getName()); - return (mDirection == Direction.INCREASING) ? result : -result; - } - return 0; - } - - public void setColumn(Column column) { - // If the sort column specified is the same as last time, - // then reverse the sort order. - if (mColumn == column) { - // Reverse the sort order - if (mDirection == Direction.INCREASING) - mDirection = Direction.DECREASING; - else - mDirection = Direction.INCREASING; - } else { - // Sort names into increasing order, data into decreasing order. - if (column == Column.BY_NAME) - mDirection = Direction.INCREASING; - else - mDirection = Direction.DECREASING; - } - mColumn = column; - } - - public Column getColumn() { - return mColumn; - } - - public void setDirection(Direction direction) { - mDirection = direction; - } - - public Direction getDirection() { - return mDirection; - } - - public static enum Column { - BY_NAME, BY_EXCLUSIVE, BY_INCLUSIVE, BY_CALLS, BY_TIME_PER_CALL - }; - - public static enum Direction { - INCREASING, DECREASING - }; - - private Column mColumn; - private Direction mDirection; - } -} diff --git a/traceview/src/com/android/traceview/ProfileData.java b/traceview/src/com/android/traceview/ProfileData.java deleted file mode 100644 index f0c1d61..0000000 --- a/traceview/src/com/android/traceview/ProfileData.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - - -public class ProfileData { - - protected MethodData mElement; - - /** mContext is either the parent or child of mElement */ - protected MethodData mContext; - protected boolean mElementIsParent; - protected long mElapsedInclusive; - protected int mNumCalls; - - public ProfileData() { - } - - public ProfileData(MethodData context, MethodData element, - boolean elementIsParent) { - mContext = context; - mElement = element; - mElementIsParent = elementIsParent; - } - - public String getProfileName() { - return mElement.getProfileName(); - } - - public MethodData getMethodData() { - return mElement; - } - - public void addElapsedInclusive(long elapsedInclusive) { - mElapsedInclusive += elapsedInclusive; - mNumCalls += 1; - } - - public void setElapsedInclusive(long elapsedInclusive) { - mElapsedInclusive = elapsedInclusive; - } - - public long getElapsedInclusive() { - return mElapsedInclusive; - } - - public void setNumCalls(int numCalls) { - mNumCalls = numCalls; - } - - public String getNumCalls() { - int totalCalls; - if (mElementIsParent) - totalCalls = mContext.getTotalCalls(); - else - totalCalls = mElement.getTotalCalls(); - return String.format("%d/%d", mNumCalls, totalCalls); - } - - public boolean isParent() { - return mElementIsParent; - } - - public MethodData getContext() { - return mContext; - } -} diff --git a/traceview/src/com/android/traceview/ProfileNode.java b/traceview/src/com/android/traceview/ProfileNode.java deleted file mode 100644 index 7cb0b5d..0000000 --- a/traceview/src/com/android/traceview/ProfileNode.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -public class ProfileNode { - - private String mLabel; - private MethodData mMethodData; - private ProfileData[] mChildren; - private boolean mIsParent; - private boolean mIsRecursive; - - public ProfileNode(String label, MethodData methodData, - ProfileData[] children, boolean isParent, boolean isRecursive) { - mLabel = label; - mMethodData = methodData; - mChildren = children; - mIsParent = isParent; - mIsRecursive = isRecursive; - } - - public String getLabel() { - return mLabel; - } - - public ProfileData[] getChildren() { - return mChildren; - } - - public boolean isParent() { - return mIsParent; - } - - public boolean isRecursive() { - return mIsRecursive; - } -} diff --git a/traceview/src/com/android/traceview/ProfileProvider.java b/traceview/src/com/android/traceview/ProfileProvider.java deleted file mode 100644 index fe5c832..0000000 --- a/traceview/src/com/android/traceview/ProfileProvider.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import java.io.InputStream; -import java.util.Arrays; -import java.util.regex.Pattern; - -import org.eclipse.jface.viewers.IColorProvider; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; -import org.eclipse.swt.widgets.TreeItem; - -class ProfileProvider implements ITreeContentProvider { - - private MethodData[] mRoots; - private SelectionAdapter mListener; - private TreeViewer mTreeViewer; - private TraceReader mReader; - private Image mSortUp; - private Image mSortDown; - private String mColumnNames[] = { "Name", "Incl %", "Inclusive", "Excl %", - "Exclusive", "Calls+Recur\nCalls/Total", "Time/Call" }; - private int mColumnWidths[] = { 370, 70, 70, 70, 70, 90, 70 }; - private int mColumnAlignments[] = { SWT.LEFT, SWT.RIGHT, SWT.RIGHT, - SWT.RIGHT, SWT.RIGHT, SWT.CENTER, SWT.RIGHT }; - private static final int COL_NAME = 0; - private static final int COL_INCLUSIVE_PER = 1; - private static final int COL_INCLUSIVE = 2; - private static final int COL_EXCLUSIVE_PER = 3; - private static final int COL_EXCLUSIVE = 4; - private static final int COL_CALLS = 5; - private static final int COL_TIME_PER_CALL = 6; - private long mTotalTime; - private Pattern mUppercase; - private int mPrevMatchIndex = -1; - - public ProfileProvider(TraceReader reader) { - mRoots = reader.getMethods(); - mReader = reader; - mTotalTime = reader.getEndTime(); - Display display = Display.getCurrent(); - InputStream in = getClass().getClassLoader().getResourceAsStream( - "icons/sort_up.png"); - mSortUp = new Image(display, in); - in = getClass().getClassLoader().getResourceAsStream( - "icons/sort_down.png"); - mSortDown = new Image(display, in); - mUppercase = Pattern.compile("[A-Z]"); - } - - private MethodData doMatchName(String name, int startIndex) { - // Check if the given "name" has any uppercase letters - boolean hasUpper = mUppercase.matcher(name).matches(); - for (int ii = startIndex; ii < mRoots.length; ++ii) { - MethodData md = mRoots[ii]; - String fullName = md.getName(); - // If there were no upper case letters in the given name, - // then ignore case when matching. - if (!hasUpper) - fullName = fullName.toLowerCase(); - if (fullName.indexOf(name) != -1) { - mPrevMatchIndex = ii; - return md; - } - } - mPrevMatchIndex = -1; - return null; - } - - public MethodData findMatchingName(String name) { - return doMatchName(name, 0); - } - - public MethodData findNextMatchingName(String name) { - return doMatchName(name, mPrevMatchIndex + 1); - } - - public MethodData findMatchingTreeItem(TreeItem item) { - if (item == null) - return null; - String text = item.getText(); - if (Character.isDigit(text.charAt(0)) == false) - return null; - int spaceIndex = text.indexOf(' '); - String numstr = text.substring(0, spaceIndex); - int rank = Integer.valueOf(numstr); - for (MethodData md : mRoots) { - if (md.getRank() == rank) - return md; - } - return null; - } - - public void setTreeViewer(TreeViewer treeViewer) { - mTreeViewer = treeViewer; - } - - public String[] getColumnNames() { - return mColumnNames; - } - - public int[] getColumnWidths() { - return mColumnWidths; - } - - public int[] getColumnAlignments() { - return mColumnAlignments; - } - - public Object[] getChildren(Object element) { - if (element instanceof MethodData) { - MethodData md = (MethodData) element; - return md.getProfileNodes(); - } - if (element instanceof ProfileNode) { - ProfileNode pn = (ProfileNode) element; - return pn.getChildren(); - } - return new Object[0]; - } - - public Object getParent(Object element) { - return null; - } - - public boolean hasChildren(Object element) { - if (element instanceof MethodData) - return true; - if (element instanceof ProfileNode) - return true; - return false; - } - - public Object[] getElements(Object element) { - return mRoots; - } - - public void dispose() { - } - - public void inputChanged(Viewer arg0, Object arg1, Object arg2) { - } - - public Object getRoot() { - return "root"; - } - - public SelectionAdapter getColumnListener() { - if (mListener == null) - mListener = new ColumnListener(); - return mListener; - } - - public LabelProvider getLabelProvider() { - return new ProfileLabelProvider(); - } - - class ProfileLabelProvider extends LabelProvider implements - ITableLabelProvider, IColorProvider { - Color colorRed; - Color colorParentsBack; - Color colorChildrenBack; - TraceUnits traceUnits; - - public ProfileLabelProvider() { - Display display = Display.getCurrent(); - colorRed = display.getSystemColor(SWT.COLOR_RED); - colorParentsBack = new Color(display, 230, 230, 255); // blue - colorChildrenBack = new Color(display, 255, 255, 210); // yellow - traceUnits = mReader.getTraceUnits(); - } - - public String getColumnText(Object element, int col) { - if (element instanceof MethodData) { - MethodData md = (MethodData) element; - if (col == COL_NAME) - return md.getProfileName(); - if (col == COL_EXCLUSIVE) { - double val = md.getElapsedExclusive(); - val = traceUnits.getScaledValue(val); - return String.format("%.3f", val); - } - if (col == COL_EXCLUSIVE_PER) { - double val = md.getElapsedExclusive(); - double per = val * 100.0 / mTotalTime; - return String.format("%.1f%%", per); - } - if (col == COL_INCLUSIVE) { - double val = md.getElapsedInclusive(); - val = traceUnits.getScaledValue(val); - return String.format("%.3f", val); - } - if (col == COL_INCLUSIVE_PER) { - double val = md.getElapsedInclusive(); - double per = val * 100.0 / mTotalTime; - return String.format("%.1f%%", per); - } - if (col == COL_CALLS) - return md.getCalls(); - if (col == COL_TIME_PER_CALL) { - int numCalls = md.getTotalCalls(); - double val = md.getElapsedInclusive(); - val = val / numCalls; - val = traceUnits.getScaledValue(val); - return String.format("%.3f", val); - } - } else if (element instanceof ProfileSelf) { - ProfileSelf ps = (ProfileSelf) element; - if (col == COL_NAME) - return ps.getProfileName(); - if (col == COL_INCLUSIVE) { - double val = ps.getElapsedInclusive(); - val = traceUnits.getScaledValue(val); - return String.format("%.3f", val); - } - if (col == COL_INCLUSIVE_PER) { - double total; - double val = ps.getElapsedInclusive(); - MethodData context = ps.getContext(); - total = context.getElapsedInclusive(); - double per = val * 100.0 / total; - return String.format("%.1f%%", per); - } - return ""; - } else if (element instanceof ProfileData) { - ProfileData pd = (ProfileData) element; - if (col == COL_NAME) - return pd.getProfileName(); - if (col == COL_INCLUSIVE) { - double val = pd.getElapsedInclusive(); - val = traceUnits.getScaledValue(val); - return String.format("%.3f", val); - } - if (col == COL_INCLUSIVE_PER) { - double total; - double val = pd.getElapsedInclusive(); - MethodData context = pd.getContext(); - total = context.getElapsedInclusive(); - double per = val * 100.0 / total; - return String.format("%.1f%%", per); - } - if (col == COL_CALLS) - return pd.getNumCalls(); - return ""; - } else if (element instanceof ProfileNode) { - ProfileNode pn = (ProfileNode) element; - if (col == COL_NAME) - return pn.getLabel(); - return ""; - } - return "col" + col; - } - - public Image getColumnImage(Object element, int col) { - if (col != COL_NAME) - return null; - if (element instanceof MethodData) { - MethodData md = (MethodData) element; - return md.getImage(); - } - if (element instanceof ProfileData) { - ProfileData pd = (ProfileData) element; - MethodData md = pd.getMethodData(); - return md.getImage(); - } - return null; - } - - public Color getForeground(Object element) { - return null; - } - - public Color getBackground(Object element) { - if (element instanceof ProfileData) { - ProfileData pd = (ProfileData) element; - if (pd.isParent()) - return colorParentsBack; - return colorChildrenBack; - } - if (element instanceof ProfileNode) { - ProfileNode pn = (ProfileNode) element; - if (pn.isParent()) - return colorParentsBack; - return colorChildrenBack; - } - return null; - } - } - - class ColumnListener extends SelectionAdapter { - MethodData.Sorter sorter = new MethodData.Sorter(); - - @Override - public void widgetSelected(SelectionEvent event) { - TreeColumn column = (TreeColumn) event.widget; - String name = column.getText(); - Tree tree = column.getParent(); - tree.setRedraw(false); - TreeColumn[] columns = tree.getColumns(); - for (TreeColumn col : columns) { - col.setImage(null); - } - if (name == mColumnNames[COL_NAME]) { - // Sort names alphabetically - sorter.setColumn(MethodData.Sorter.Column.BY_NAME); - Arrays.sort(mRoots, sorter); - } else if (name == mColumnNames[COL_EXCLUSIVE]) { - sorter.setColumn(MethodData.Sorter.Column.BY_EXCLUSIVE); - Arrays.sort(mRoots, sorter); - } else if (name == mColumnNames[COL_EXCLUSIVE_PER]) { - sorter.setColumn(MethodData.Sorter.Column.BY_EXCLUSIVE); - Arrays.sort(mRoots, sorter); - } else if (name == mColumnNames[COL_INCLUSIVE]) { - sorter.setColumn(MethodData.Sorter.Column.BY_INCLUSIVE); - Arrays.sort(mRoots, sorter); - } else if (name == mColumnNames[COL_INCLUSIVE_PER]) { - sorter.setColumn(MethodData.Sorter.Column.BY_INCLUSIVE); - Arrays.sort(mRoots, sorter); - } else if (name == mColumnNames[COL_CALLS]) { - sorter.setColumn(MethodData.Sorter.Column.BY_CALLS); - Arrays.sort(mRoots, sorter); - } else if (name == mColumnNames[COL_TIME_PER_CALL]) { - sorter.setColumn(MethodData.Sorter.Column.BY_TIME_PER_CALL); - Arrays.sort(mRoots, sorter); - } - MethodData.Sorter.Direction direction = sorter.getDirection(); - if (direction == MethodData.Sorter.Direction.INCREASING) - column.setImage(mSortDown); - else - column.setImage(mSortUp); - tree.setRedraw(true); - mTreeViewer.refresh(); - } - } -} diff --git a/traceview/src/com/android/traceview/ProfileSelf.java b/traceview/src/com/android/traceview/ProfileSelf.java deleted file mode 100644 index 3a4f3d9..0000000 --- a/traceview/src/com/android/traceview/ProfileSelf.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -public class ProfileSelf extends ProfileData { - public ProfileSelf(MethodData methodData) { - mElement = methodData; - mContext = methodData; - } - - @Override - public String getProfileName() { - return "self"; - } - - @Override - public long getElapsedInclusive() { - return mElement.getTopExclusive(); - } -} diff --git a/traceview/src/com/android/traceview/ProfileView.java b/traceview/src/com/android/traceview/ProfileView.java deleted file mode 100644 index e48cb56..0000000 --- a/traceview/src/com/android/traceview/ProfileView.java +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import java.util.ArrayList; -import java.util.Observable; -import java.util.Observer; - -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.ITreeViewerListener; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TreeExpansionEvent; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.KeyAdapter; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; -import org.eclipse.swt.widgets.TreeItem; - -public class ProfileView extends Composite implements Observer { - - private TreeViewer mTreeViewer; - private Text mSearchBox; - private SelectionController mSelectionController; - private ProfileProvider mProfileProvider; - private Color mColorNoMatch; - private Color mColorMatch; - private MethodData mCurrentHighlightedMethod; - - public ProfileView(Composite parent, TraceReader reader, - SelectionController selectController) { - super(parent, SWT.NONE); - setLayout(new GridLayout(1, false)); - this.mSelectionController = selectController; - mSelectionController.addObserver(this); - - // Add a tree viewer at the top - mTreeViewer = new TreeViewer(this, SWT.MULTI | SWT.NONE); - mTreeViewer.setUseHashlookup(true); - mProfileProvider = reader.getProfileProvider(); - mProfileProvider.setTreeViewer(mTreeViewer); - SelectionAdapter listener = mProfileProvider.getColumnListener(); - final Tree tree = mTreeViewer.getTree(); - tree.setHeaderVisible(true); - tree.setLayoutData(new GridData(GridData.FILL_BOTH)); - - // Get the column names from the ProfileProvider - String[] columnNames = mProfileProvider.getColumnNames(); - int[] columnWidths = mProfileProvider.getColumnWidths(); - int[] columnAlignments = mProfileProvider.getColumnAlignments(); - for (int ii = 0; ii < columnWidths.length; ++ii) { - TreeColumn column = new TreeColumn(tree, SWT.LEFT); - column.setText(columnNames[ii]); - column.setWidth(columnWidths[ii]); - column.setMoveable(true); - column.addSelectionListener(listener); - column.setAlignment(columnAlignments[ii]); - } - - // Add a listener to the tree so that we can make the row - // height smaller. - tree.addListener(SWT.MeasureItem, new Listener() { - public void handleEvent(Event event) { - int fontHeight = event.gc.getFontMetrics().getHeight(); - event.height = fontHeight; - } - }); - - mTreeViewer.setContentProvider(mProfileProvider); - mTreeViewer.setLabelProvider(mProfileProvider.getLabelProvider()); - mTreeViewer.setInput(mProfileProvider.getRoot()); - - // Create another composite to hold the label and text box - Composite composite = new Composite(this, SWT.NONE); - composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - // Add a label for the search box - Label label = new Label(composite, SWT.NONE); - label.setText("Find:"); - - // Add a text box for searching for method names - mSearchBox = new Text(composite, SWT.BORDER); - mSearchBox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - Display display = getDisplay(); - mColorNoMatch = new Color(display, 255, 200, 200); - mColorMatch = mSearchBox.getBackground(); - - mSearchBox.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent ev) { - String query = mSearchBox.getText(); - if (query.length() == 0) - return; - findName(query); - } - }); - - // Add a key listener to the text box so that we can clear - // the text box if the user presses <ESC>. - mSearchBox.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent event) { - if (event.keyCode == SWT.ESC) { - mSearchBox.setText(""); - } else if (event.keyCode == SWT.CR) { - String query = mSearchBox.getText(); - if (query.length() == 0) - return; - findNextName(query); - } - } - }); - - // Also add a key listener to the tree viewer so that the - // user can just start typing anywhere in the tree view. - tree.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent event) { - if (event.keyCode == SWT.ESC) { - mSearchBox.setText(""); - } else if (event.keyCode == SWT.BS) { - // Erase the last character from the search box - String text = mSearchBox.getText(); - int len = text.length(); - String chopped; - if (len <= 1) - chopped = ""; - else - chopped = text.substring(0, len - 1); - mSearchBox.setText(chopped); - } else if (event.keyCode == SWT.CR) { - String query = mSearchBox.getText(); - if (query.length() == 0) - return; - findNextName(query); - } else { - // Append the given character to the search box - String str = String.valueOf(event.character); - mSearchBox.append(str); - } - event.doit = false; - } - }); - - // Add a selection listener to the tree so that the user can click - // on a method that is a child or parent and jump to that method. - mTreeViewer - .addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent ev) { - ISelection sel = ev.getSelection(); - if (sel.isEmpty()) - return; - if (sel instanceof IStructuredSelection) { - IStructuredSelection selection = (IStructuredSelection) sel; - Object element = selection.getFirstElement(); - if (element == null) - return; - if (element instanceof MethodData) { - MethodData md = (MethodData) element; - highlightMethod(md, true); - } - if (element instanceof ProfileData) { - MethodData md = ((ProfileData) element) - .getMethodData(); - highlightMethod(md, true); - } - } - } - }); - - // Add a tree listener so that we can expand the parents and children - // of a method when a method is expanded. - mTreeViewer.addTreeListener(new ITreeViewerListener() { - public void treeExpanded(TreeExpansionEvent event) { - Object element = event.getElement(); - if (element instanceof MethodData) { - MethodData md = (MethodData) element; - expandNode(md); - } - } - public void treeCollapsed(TreeExpansionEvent event) { - } - }); - - tree.addListener(SWT.MouseDown, new Listener() { - public void handleEvent(Event event) { - Point point = new Point(event.x, event.y); - TreeItem treeItem = tree.getItem(point); - MethodData md = mProfileProvider.findMatchingTreeItem(treeItem); - if (md == null) - return; - ArrayList<Selection> selections = new ArrayList<Selection>(); - selections.add(Selection.highlight("MethodData", md)); - mSelectionController.change(selections, "ProfileView"); - } - }); - } - - private void findName(String query) { - MethodData md = mProfileProvider.findMatchingName(query); - selectMethod(md); - } - - private void findNextName(String query) { - MethodData md = mProfileProvider.findNextMatchingName(query); - selectMethod(md); - } - - private void selectMethod(MethodData md) { - if (md == null) { - mSearchBox.setBackground(mColorNoMatch); - return; - } - mSearchBox.setBackground(mColorMatch); - highlightMethod(md, false); - } - - public void update(Observable objservable, Object arg) { - // Ignore updates from myself - if (arg == "ProfileView") - return; - // System.out.printf("profileview update from %s\n", arg); - ArrayList<Selection> selections; - selections = mSelectionController.getSelections(); - for (Selection selection : selections) { - Selection.Action action = selection.getAction(); - if (action != Selection.Action.Highlight) - continue; - String name = selection.getName(); - if (name == "MethodData") { - MethodData md = (MethodData) selection.getValue(); - highlightMethod(md, true); - return; - } - if (name == "Call") { - Call call = (Call) selection.getValue(); - MethodData md = call.mMethodData; - highlightMethod(md, true); - return; - } - } - } - - private void highlightMethod(MethodData md, boolean clearSearch) { - if (md == null) - return; - // Avoid an infinite recursion - if (md == mCurrentHighlightedMethod) - return; - if (clearSearch) { - mSearchBox.setText(""); - mSearchBox.setBackground(mColorMatch); - } - mCurrentHighlightedMethod = md; - mTreeViewer.collapseAll(); - // Expand this node and its children - expandNode(md); - StructuredSelection sel = new StructuredSelection(md); - mTreeViewer.setSelection(sel, true); - Tree tree = mTreeViewer.getTree(); - TreeItem[] items = tree.getSelection(); - tree.setTopItem(items[0]); - // workaround a Mac bug by adding showItem(). - tree.showItem(items[0]); - } - - private void expandNode(MethodData md) { - ProfileNode[] nodes = md.getProfileNodes(); - mTreeViewer.setExpandedState(md, true); - // Also expand the "Parents" and "Children" nodes. - for (ProfileNode node : nodes) { - if (node.isRecursive() == false) - mTreeViewer.setExpandedState(node, true); - } - } -} diff --git a/traceview/src/com/android/traceview/QtraceReader.java b/traceview/src/com/android/traceview/QtraceReader.java deleted file mode 100644 index c4db4a2..0000000 --- a/traceview/src/com/android/traceview/QtraceReader.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import java.util.ArrayList; -import java.util.HashMap; - -public class QtraceReader extends TraceReader { - QtraceReader(String traceName) { - } - - @Override - public MethodData[] getMethods() { - return null; - } - - @Override - public HashMap<Integer, String> getThreadLabels() { - return null; - } - - @Override - public ArrayList<TimeLineView.Record> getThreadTimeRecords() { - return null; - } - - @Override - public ProfileProvider getProfileProvider() { - return null; - } -} diff --git a/traceview/src/com/android/traceview/Selection.java b/traceview/src/com/android/traceview/Selection.java deleted file mode 100644 index 3764619..0000000 --- a/traceview/src/com/android/traceview/Selection.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -public class Selection { - - private Action mAction; - private String mName; - private Object mValue; - - public Selection(Action action, String name, Object value) { - mAction = action; - mName = name; - mValue = value; - } - - public static Selection highlight(String name, Object value) { - return new Selection(Action.Highlight, name, value); - } - - public static Selection include(String name, Object value) { - return new Selection(Action.Include, name, value); - } - - public static Selection exclude(String name, Object value) { - return new Selection(Action.Exclude, name, value); - } - - public void setName(String name) { - mName = name; - } - - public String getName() { - return mName; - } - - public void setValue(Object value) { - mValue = value; - } - - public Object getValue() { - return mValue; - } - - public void setAction(Action action) { - mAction = action; - } - - public Action getAction() { - return mAction; - } - - public static enum Action { - Highlight, Include, Exclude, Aggregate - }; -} diff --git a/traceview/src/com/android/traceview/SelectionController.java b/traceview/src/com/android/traceview/SelectionController.java deleted file mode 100644 index 4c930ea..0000000 --- a/traceview/src/com/android/traceview/SelectionController.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import java.util.ArrayList; -import java.util.Observable; - -public class SelectionController extends Observable { - - private ArrayList<Selection> mSelections; - - public void change(ArrayList<Selection> selections, Object arg) { - this.mSelections = selections; - setChanged(); - notifyObservers(arg); - } - - public ArrayList<Selection> getSelections() { - return mSelections; - } -} diff --git a/traceview/src/com/android/traceview/ThreadData.java b/traceview/src/com/android/traceview/ThreadData.java deleted file mode 100644 index 54ea891..0000000 --- a/traceview/src/com/android/traceview/ThreadData.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import java.util.ArrayList; -import java.util.HashMap; - -class ThreadData implements TimeLineView.Row { - - private int mId; - private String mName; - private long mGlobalStartTime = -1; - private long mGlobalEndTime = -1; - private long mLastEventTime; - private long mCpuTime; - private Call mRoot; - private Call mCurrent; - private Call mLastContextSwitch; - private ArrayList<Call> mStack = new ArrayList<Call>(); - - // This is a hash of all the methods that are currently on the stack. - private HashMap<MethodData, Integer> mStackMethods = new HashMap<MethodData, Integer>(); - - // True if no calls have ever been added to this thread - private boolean mIsEmpty; - - ThreadData(int id, String name, MethodData topLevel) { - mId = id; - mName = String.format("[%d] %s", id, name); - mRoot = new Call(mName, topLevel); - mCurrent = mRoot; - mIsEmpty = true; - } - - public boolean isEmpty() { - return mIsEmpty; - } - - public String getName() { - return mName; - } - - public Call getCalltreeRoot() { - return mRoot; - } - - void handleCall(Call call, long globalTime) { - mIsEmpty = false; - long currentTime = call.mThreadStartTime; - if (currentTime < mLastEventTime) { - System.err - .printf( - "ThreadData: '%1$s' call time (%2$d) is less than previous time (%3$d) for thread '%4$s'\n", - call.getName(), currentTime, mLastEventTime, mName); - System.exit(1); - } - long elapsed = currentTime - mLastEventTime; - mCpuTime += elapsed; - if (call.getMethodAction() == 0) { - // This is a method entry. - enter(call, elapsed); - } else { - // This is a method exit. - exit(call, elapsed, globalTime); - } - mLastEventTime = currentTime; - mGlobalEndTime = globalTime; - } - - private void enter(Call c, long elapsed) { - Call caller = mCurrent; - push(c); - - // Check the stack for a matching method to determine if this call - // is recursive. - MethodData md = c.mMethodData; - Integer num = mStackMethods.get(md); - if (num == null) { - num = 0; - } else if (num > 0) { - c.setRecursive(true); - } - num += 1; - mStackMethods.put(md, num); - mCurrent = c; - - // Add the elapsed time to the caller's exclusive time - caller.addExclusiveTime(elapsed); - } - - private void exit(Call c, long elapsed, long globalTime) { - mCurrent.mGlobalEndTime = globalTime; - Call top = pop(); - if (top == null) { - return; - } - - if (mCurrent.mMethodData != c.mMethodData) { - String error = "Method exit (" + c.getName() - + ") does not match current method (" + mCurrent.getName() - + ")"; - throw new RuntimeException(error); - } else { - long duration = c.mThreadStartTime - mCurrent.mThreadStartTime; - Call caller = top(); - mCurrent.addExclusiveTime(elapsed); - mCurrent.addInclusiveTime(duration, caller); - if (caller == null) { - caller = mRoot; - } - mCurrent = caller; - } - } - - public void push(Call c) { - mStack.add(c); - } - - public Call pop() { - ArrayList<Call> stack = mStack; - if (stack.size() == 0) - return null; - Call top = stack.get(stack.size() - 1); - stack.remove(stack.size() - 1); - - // Decrement the count on the method in the hash table and remove - // the entry when it goes to zero. - MethodData md = top.mMethodData; - Integer num = mStackMethods.get(md); - if (num != null) { - num -= 1; - if (num <= 0) { - mStackMethods.remove(md); - } else { - mStackMethods.put(md, num); - } - } - return top; - } - - public Call top() { - ArrayList<Call> stack = mStack; - if (stack.size() == 0) - return null; - return stack.get(stack.size() - 1); - } - - public long endTrace() { - // If we have calls on the stack when the trace ends, then clean up - // the stack and compute the inclusive time of the methods by pretending - // that we are exiting from their methods now. - while (mCurrent != mRoot) { - long duration = mLastEventTime - mCurrent.mThreadStartTime; - pop(); - Call caller = top(); - mCurrent.addInclusiveTime(duration, caller); - mCurrent.mGlobalEndTime = mGlobalEndTime; - if (caller == null) { - caller = mRoot; - } - mCurrent = caller; - } - return mLastEventTime; - } - - @Override - public String toString() { - return mName; - } - - public int getId() { - return mId; - } - - public void setCpuTime(long cpuTime) { - mCpuTime = cpuTime; - } - - public long getCpuTime() { - return mCpuTime; - } - - public void setGlobalStartTime(long globalStartTime) { - mGlobalStartTime = globalStartTime; - } - - public long getGlobalStartTime() { - return mGlobalStartTime; - } - - public void setLastEventTime(long lastEventTime) { - mLastEventTime = lastEventTime; - } - - public long getLastEventTime() { - return mLastEventTime; - } - - public void setGlobalEndTime(long globalEndTime) { - mGlobalEndTime = globalEndTime; - } - - public long getGlobalEndTime() { - return mGlobalEndTime; - } - - public void setLastContextSwitch(Call lastContextSwitch) { - mLastContextSwitch = lastContextSwitch; - } - - public Call getLastContextSwitch() { - return mLastContextSwitch; - } -} diff --git a/traceview/src/com/android/traceview/TickScaler.java b/traceview/src/com/android/traceview/TickScaler.java deleted file mode 100644 index 79fa160..0000000 --- a/traceview/src/com/android/traceview/TickScaler.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -class TickScaler { - - private double mMinVal; // required input - private double mMaxVal; // required input - private double mRangeVal; - private int mNumPixels; // required input - private int mPixelsPerTick; // required input - private double mPixelsPerRange; - private double mTickIncrement; - private double mMinMajorTick; - - TickScaler(double minVal, double maxVal, int numPixels, int pixelsPerTick) { - mMinVal = minVal; - mMaxVal = maxVal; - mNumPixels = numPixels; - mPixelsPerTick = pixelsPerTick; - } - - public void setMinVal(double minVal) { - mMinVal = minVal; - } - - public double getMinVal() { - return mMinVal; - } - - public void setMaxVal(double maxVal) { - mMaxVal = maxVal; - } - - public double getMaxVal() { - return mMaxVal; - } - - public void setNumPixels(int numPixels) { - mNumPixels = numPixels; - } - - public int getNumPixels() { - return mNumPixels; - } - - public void setPixelsPerTick(int pixelsPerTick) { - mPixelsPerTick = pixelsPerTick; - } - - public int getPixelsPerTick() { - return mPixelsPerTick; - } - - public void setPixelsPerRange(double pixelsPerRange) { - mPixelsPerRange = pixelsPerRange; - } - - public double getPixelsPerRange() { - return mPixelsPerRange; - } - - public void setTickIncrement(double tickIncrement) { - mTickIncrement = tickIncrement; - } - - public double getTickIncrement() { - return mTickIncrement; - } - - public void setMinMajorTick(double minMajorTick) { - mMinMajorTick = minMajorTick; - } - - public double getMinMajorTick() { - return mMinMajorTick; - } - - // Convert a time value to a 0-based pixel value - public int valueToPixel(double value) { - return (int) Math.ceil(mPixelsPerRange * (value - mMinVal) - 0.5); - } - - // Convert a time value to a 0-based fractional pixel - public double valueToPixelFraction(double value) { - return mPixelsPerRange * (value - mMinVal); - } - - // Convert a 0-based pixel value to a time value - public double pixelToValue(int pixel) { - return mMinVal + (pixel / mPixelsPerRange); - } - - public void computeTicks(boolean useGivenEndPoints) { - int numTicks = mNumPixels / mPixelsPerTick; - mRangeVal = mMaxVal - mMinVal; - mTickIncrement = mRangeVal / numTicks; - double dlogTickIncrement = Math.log10(mTickIncrement); - int logTickIncrement = (int) Math.floor(dlogTickIncrement); - double scale = Math.pow(10, logTickIncrement); - double scaledTickIncr = mTickIncrement / scale; - if (scaledTickIncr > 5.0) - scaledTickIncr = 10; - else if (scaledTickIncr > 2) - scaledTickIncr = 5; - else if (scaledTickIncr > 1) - scaledTickIncr = 2; - else - scaledTickIncr = 1; - mTickIncrement = scaledTickIncr * scale; - - if (!useGivenEndPoints) { - // Round up the max val to the next minor tick - double minorTickIncrement = mTickIncrement / 5; - double dval = mMaxVal / minorTickIncrement; - int ival = (int) dval; - if (ival != dval) - mMaxVal = (ival + 1) * minorTickIncrement; - - // Round down the min val to a multiple of tickIncrement - ival = (int) (mMinVal / mTickIncrement); - mMinVal = ival * mTickIncrement; - mMinMajorTick = mMinVal; - } else { - int ival = (int) (mMinVal / mTickIncrement); - mMinMajorTick = ival * mTickIncrement; - if (mMinMajorTick < mMinVal) - mMinMajorTick = mMinMajorTick + mTickIncrement; - } - - mRangeVal = mMaxVal - mMinVal; - mPixelsPerRange = (double) mNumPixels / mRangeVal; - } -} diff --git a/traceview/src/com/android/traceview/TimeLineView.java b/traceview/src/com/android/traceview/TimeLineView.java deleted file mode 100644 index 67dc97b..0000000 --- a/traceview/src/com/android/traceview/TimeLineView.java +++ /dev/null @@ -1,1961 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import org.eclipse.jface.resource.FontRegistry; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseMoveListener; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Cursor; -import org.eclipse.swt.graphics.FontData; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Canvas; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.ScrollBar; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Observable; -import java.util.Observer; - -public class TimeLineView extends Composite implements Observer { - - private HashMap<String, RowData> mRowByName; - private double mTotalElapsed; - private RowData[] mRows; - private Segment[] mSegments; - private ArrayList<Segment> mSegmentList = new ArrayList<Segment>(); - private HashMap<Integer, String> mThreadLabels; - private Timescale mTimescale; - private Surface mSurface; - private RowLabels mLabels; - private SashForm mSashForm; - private int mScrollOffsetY; - - public static final int PixelsPerTick = 50; - private TickScaler mScaleInfo = new TickScaler(0, 0, 0, PixelsPerTick); - private static final int LeftMargin = 10; // blank space on left - private static final int RightMargin = 60; // blank space on right - - private Color mColorBlack; - private Color mColorGray; - private Color mColorDarkGray; - private Color mColorForeground; - private Color mColorRowBack; - private Color mColorZoomSelection; - private FontRegistry mFontRegistry; - - /** vertical height of drawn blocks in each row */ - private static final int rowHeight = 20; - - /** the blank space between rows */ - private static final int rowYMargin = 12; - private static final int rowYMarginHalf = rowYMargin / 2; - - /** total vertical space for row */ - private static final int rowYSpace = rowHeight + rowYMargin; - private static final int majorTickLength = 8; - private static final int minorTickLength = 4; - private static final int timeLineOffsetY = 38; - private static final int tickToFontSpacing = 2; - - /** start of first row */ - private static final int topMargin = 70; - private int mMouseRow = -1; - private int mNumRows; - private int mStartRow; - private int mEndRow; - private TraceUnits mUnits; - private int mSmallFontWidth; - private int mSmallFontHeight; - private int mMediumFontWidth; - private SelectionController mSelectionController; - private MethodData mHighlightMethodData; - private Call mHighlightCall; - private static final int MinInclusiveRange = 3; - - /** Setting the fonts looks good on Linux but bad on Macs */ - private boolean mSetFonts = false; - - public static interface Block { - public String getName(); - public MethodData getMethodData(); - public long getStartTime(); - public long getEndTime(); - public Color getColor(); - public double addWeight(int x, int y, double weight); - public void clearWeight(); - } - - public static interface Row { - public int getId(); - public String getName(); - } - - public static class Record { - Row row; - Block block; - - public Record(Row row, Block block) { - this.row = row; - this.block = block; - } - } - - public TimeLineView(Composite parent, TraceReader reader, - SelectionController selectionController) { - super(parent, SWT.NONE); - mRowByName = new HashMap<String, RowData>(); - this.mSelectionController = selectionController; - selectionController.addObserver(this); - mUnits = reader.getTraceUnits(); - mThreadLabels = reader.getThreadLabels(); - - Display display = getDisplay(); - mColorGray = display.getSystemColor(SWT.COLOR_GRAY); - mColorDarkGray = display.getSystemColor(SWT.COLOR_DARK_GRAY); - mColorBlack = display.getSystemColor(SWT.COLOR_BLACK); - // mColorBackground = display.getSystemColor(SWT.COLOR_WHITE); - mColorForeground = display.getSystemColor(SWT.COLOR_BLACK); - mColorRowBack = new Color(display, 240, 240, 255); - mColorZoomSelection = new Color(display, 230, 230, 230); - - mFontRegistry = new FontRegistry(display); - mFontRegistry.put("small", // $NON-NLS-1$ - new FontData[] { new FontData("Arial", 8, SWT.NORMAL) }); // $NON-NLS-1$ - mFontRegistry.put("courier8", // $NON-NLS-1$ - new FontData[] { new FontData("Courier New", 8, SWT.BOLD) }); // $NON-NLS-1$ - mFontRegistry.put("medium", // $NON-NLS-1$ - new FontData[] { new FontData("Courier New", 10, SWT.NORMAL) }); // $NON-NLS-1$ - - Image image = new Image(display, new Rectangle(100, 100, 100, 100)); - GC gc = new GC(image); - if (mSetFonts) { - gc.setFont(mFontRegistry.get("small")); // $NON-NLS-1$ - } - mSmallFontWidth = gc.getFontMetrics().getAverageCharWidth(); - mSmallFontHeight = gc.getFontMetrics().getHeight(); - - if (mSetFonts) { - gc.setFont(mFontRegistry.get("medium")); // $NON-NLS-1$ - } - mMediumFontWidth = gc.getFontMetrics().getAverageCharWidth(); - - image.dispose(); - gc.dispose(); - - setLayout(new FillLayout()); - - // Create a sash form for holding two canvas views, one for the - // thread labels and one for the thread timeline. - mSashForm = new SashForm(this, SWT.HORIZONTAL); - mSashForm.setBackground(mColorGray); - mSashForm.SASH_WIDTH = 3; - - // Create a composite for the left side of the sash - Composite composite = new Composite(mSashForm, SWT.NONE); - GridLayout layout = new GridLayout(1, true /* make columns equal width */); - layout.marginHeight = 0; - layout.marginWidth = 0; - layout.verticalSpacing = 1; - composite.setLayout(layout); - - // Create a blank corner space in the upper left corner - BlankCorner corner = new BlankCorner(composite); - GridData gridData = new GridData(GridData.FILL_HORIZONTAL); - gridData.heightHint = topMargin; - corner.setLayoutData(gridData); - - // Add the thread labels below the blank corner. - mLabels = new RowLabels(composite); - gridData = new GridData(GridData.FILL_BOTH); - mLabels.setLayoutData(gridData); - - // Create another composite for the right side of the sash - composite = new Composite(mSashForm, SWT.NONE); - layout = new GridLayout(1, true /* make columns equal width */); - layout.marginHeight = 0; - layout.marginWidth = 0; - layout.verticalSpacing = 1; - composite.setLayout(layout); - - mTimescale = new Timescale(composite); - gridData = new GridData(GridData.FILL_HORIZONTAL); - gridData.heightHint = topMargin; - mTimescale.setLayoutData(gridData); - - mSurface = new Surface(composite); - gridData = new GridData(GridData.FILL_BOTH); - mSurface.setLayoutData(gridData); - mSashForm.setWeights(new int[] { 1, 5 }); - - final ScrollBar vBar = mSurface.getVerticalBar(); - vBar.addListener(SWT.Selection, new Listener() { - public void handleEvent(Event e) { - mScrollOffsetY = vBar.getSelection(); - Point dim = mSurface.getSize(); - int newScrollOffsetY = computeVisibleRows(dim.y); - if (newScrollOffsetY != mScrollOffsetY) { - mScrollOffsetY = newScrollOffsetY; - vBar.setSelection(newScrollOffsetY); - } - mLabels.redraw(); - mSurface.redraw(); - } - }); - - mSurface.addListener(SWT.Resize, new Listener() { - public void handleEvent(Event e) { - Point dim = mSurface.getSize(); - - // If we don't need the scroll bar then don't display it. - if (dim.y >= mNumRows * rowYSpace) { - vBar.setVisible(false); - } else { - vBar.setVisible(true); - } - int newScrollOffsetY = computeVisibleRows(dim.y); - if (newScrollOffsetY != mScrollOffsetY) { - mScrollOffsetY = newScrollOffsetY; - vBar.setSelection(newScrollOffsetY); - } - - int spaceNeeded = mNumRows * rowYSpace; - vBar.setMaximum(spaceNeeded); - vBar.setThumb(dim.y); - - mLabels.redraw(); - mSurface.redraw(); - } - }); - - mSurface.addMouseListener(new MouseAdapter() { - @Override - public void mouseUp(MouseEvent me) { - mSurface.mouseUp(me); - } - - @Override - public void mouseDown(MouseEvent me) { - mSurface.mouseDown(me); - } - - @Override - public void mouseDoubleClick(MouseEvent me) { - mSurface.mouseDoubleClick(me); - } - }); - - mSurface.addMouseMoveListener(new MouseMoveListener() { - public void mouseMove(MouseEvent me) { - mSurface.mouseMove(me); - } - }); - - mTimescale.addMouseListener(new MouseAdapter() { - @Override - public void mouseUp(MouseEvent me) { - mTimescale.mouseUp(me); - } - - @Override - public void mouseDown(MouseEvent me) { - mTimescale.mouseDown(me); - } - - @Override - public void mouseDoubleClick(MouseEvent me) { - mTimescale.mouseDoubleClick(me); - } - }); - - mTimescale.addMouseMoveListener(new MouseMoveListener() { - public void mouseMove(MouseEvent me) { - mTimescale.mouseMove(me); - } - }); - - mLabels.addMouseMoveListener(new MouseMoveListener() { - public void mouseMove(MouseEvent me) { - mLabels.mouseMove(me); - } - }); - - setData(reader.getThreadTimeRecords()); - } - - public void update(Observable objservable, Object arg) { - // Ignore updates from myself - if (arg == "TimeLineView") // $NON-NLS-1$ - return; - // System.out.printf("timeline update from %s\n", arg); - boolean foundHighlight = false; - ArrayList<Selection> selections; - selections = mSelectionController.getSelections(); - for (Selection selection : selections) { - Selection.Action action = selection.getAction(); - if (action != Selection.Action.Highlight) - continue; - String name = selection.getName(); - // System.out.printf(" timeline highlight %s from %s\n", name, arg); - if (name == "MethodData") { // $NON-NLS-1$ - foundHighlight = true; - mHighlightMethodData = (MethodData) selection.getValue(); - // System.out.printf(" method %s\n", - // highlightMethodData.getName()); - mHighlightCall = null; - startHighlighting(); - } else if (name == "Call") { // $NON-NLS-1$ - foundHighlight = true; - mHighlightCall = (Call) selection.getValue(); - // System.out.printf(" call %s\n", highlightCall.getName()); - mHighlightMethodData = null; - startHighlighting(); - } - } - if (foundHighlight == false) - mSurface.clearHighlights(); - } - - public void setData(ArrayList<Record> records) { - if (records == null) - records = new ArrayList<Record>(); - - if (false) { - System.out.println("TimelineView() list of records:"); // $NON-NLS-1$ - for (Record r : records) { - System.out.printf("row '%s' block '%s' [%d, %d]\n", r.row // $NON-NLS-1$ - .getName(), r.block.getName(), r.block.getStartTime(), - r.block.getEndTime()); - if (r.block.getStartTime() > r.block.getEndTime()) { - System.err.printf("Error: block startTime > endTime\n"); // $NON-NLS-1$ - System.exit(1); - } - } - } - - // Sort the records into increasing start time, and decreasing end time - Collections.sort(records, new Comparator<Record>() { - public int compare(Record r1, Record r2) { - long start1 = r1.block.getStartTime(); - long start2 = r2.block.getStartTime(); - if (start1 > start2) - return 1; - if (start1 < start2) - return -1; - - // The start times are the same, so compare the end times - long end1 = r1.block.getEndTime(); - long end2 = r2.block.getEndTime(); - if (end1 > end2) - return -1; - if (end1 < end2) - return 1; - - return 0; - } - }); - - // The records are sorted into increasing start time, - // so the minimum start time is the start time of the first record. - double minVal = 0; - if (records.size() > 0) - minVal = records.get(0).block.getStartTime(); - - // Sum the time spent in each row and block, and - // keep track of the maximum end time. - double maxVal = 0; - for (Record rec : records) { - Row row = rec.row; - Block block = rec.block; - String rowName = row.getName(); - RowData rd = mRowByName.get(rowName); - if (rd == null) { - rd = new RowData(row); - mRowByName.put(rowName, rd); - } - long blockStartTime = block.getStartTime(); - long blockEndTime = block.getEndTime(); - if (blockEndTime > rd.mEndTime) { - long start = Math.max(blockStartTime, rd.mEndTime); - rd.mElapsed += blockEndTime - start; - mTotalElapsed += blockEndTime - start; - rd.mEndTime = blockEndTime; - } - if (blockEndTime > maxVal) - maxVal = blockEndTime; - - // Keep track of nested blocks by using a stack (for each row). - // Create a Segment object for each visible part of a block. - Block top = rd.top(); - if (top == null) { - rd.push(block); - continue; - } - - long topStartTime = top.getStartTime(); - long topEndTime = top.getEndTime(); - if (topEndTime >= blockStartTime) { - // Add this segment if it has a non-zero elapsed time. - if (topStartTime < blockStartTime) { - Segment segment = new Segment(rd, top, topStartTime, - blockStartTime); - mSegmentList.add(segment); - } - - // If this block starts where the previous (top) block ends, - // then pop off the top block. - if (topEndTime == blockStartTime) - rd.pop(); - rd.push(block); - } else { - // We may have to pop several frames here. - popFrames(rd, top, blockStartTime); - rd.push(block); - } - } - - // Clean up the stack of each row - for (RowData rd : mRowByName.values()) { - Block top = rd.top(); - popFrames(rd, top, Integer.MAX_VALUE); - } - - mSurface.setRange(minVal, maxVal); - mSurface.setLimitRange(minVal, maxVal); - - // Sort the rows into decreasing elapsed time - Collection<RowData> rv = mRowByName.values(); - mRows = rv.toArray(new RowData[rv.size()]); - Arrays.sort(mRows, new Comparator<RowData>() { - public int compare(RowData rd1, RowData rd2) { - return (int) (rd2.mElapsed - rd1.mElapsed); - } - }); - - // Assign ranks to the sorted rows - for (int ii = 0; ii < mRows.length; ++ii) { - mRows[ii].mRank = ii; - } - - // Compute the number of rows with data - mNumRows = 0; - for (int ii = 0; ii < mRows.length; ++ii) { - if (mRows[ii].mElapsed == 0) - break; - mNumRows += 1; - } - - // Sort the blocks into increasing rows, and within rows into - // increasing start values. - mSegments = mSegmentList.toArray(new Segment[mSegmentList.size()]); - Arrays.sort(mSegments, new Comparator<Segment>() { - public int compare(Segment bd1, Segment bd2) { - RowData rd1 = bd1.mRowData; - RowData rd2 = bd2.mRowData; - int diff = rd1.mRank - rd2.mRank; - if (diff == 0) { - long timeDiff = bd1.mStartTime - bd2.mStartTime; - if (timeDiff == 0) - timeDiff = bd1.mEndTime - bd2.mEndTime; - return (int) timeDiff; - } - return diff; - } - }); - - if (false) { - for (Segment segment : mSegments) { - System.out.printf("seg '%s' [%6d, %6d] %s\n", - segment.mRowData.mName, segment.mStartTime, - segment.mEndTime, segment.mBlock.getName()); - if (segment.mStartTime > segment.mEndTime) { - System.err.printf("Error: segment startTime > endTime\n"); - System.exit(1); - } - } - } - } - - private void popFrames(RowData rd, Block top, long startTime) { - long topEndTime = top.getEndTime(); - long lastEndTime = top.getStartTime(); - while (topEndTime <= startTime) { - if (topEndTime > lastEndTime) { - Segment segment = new Segment(rd, top, lastEndTime, topEndTime); - mSegmentList.add(segment); - lastEndTime = topEndTime; - } - rd.pop(); - top = rd.top(); - if (top == null) - return; - topEndTime = top.getEndTime(); - } - - // If we get here, then topEndTime > startTime - if (lastEndTime < startTime) { - Segment bd = new Segment(rd, top, lastEndTime, startTime); - mSegmentList.add(bd); - } - } - - private class RowLabels extends Canvas { - - /** The space between the row label and the sash line */ - private static final int labelMarginX = 2; - - public RowLabels(Composite parent) { - super(parent, SWT.NO_BACKGROUND); - addPaintListener(new PaintListener() { - public void paintControl(PaintEvent pe) { - draw(pe.display, pe.gc); - } - }); - } - - private void mouseMove(MouseEvent me) { - int rownum = (me.y + mScrollOffsetY) / rowYSpace; - if (mMouseRow != rownum) { - mMouseRow = rownum; - redraw(); - mSurface.redraw(); - } - } - - private void draw(Display display, GC gc) { - if (mSegments.length == 0) { - // gc.setBackground(colorBackground); - // gc.fillRectangle(getBounds()); - return; - } - Point dim = getSize(); - - // Create an image for double-buffering - Image image = new Image(display, getBounds()); - - // Set up the off-screen gc - GC gcImage = new GC(image); - if (mSetFonts) - gcImage.setFont(mFontRegistry.get("medium")); // $NON-NLS-1$ - - if (mNumRows > 2) { - // Draw the row background stripes - gcImage.setBackground(mColorRowBack); - for (int ii = 1; ii < mNumRows; ii += 2) { - RowData rd = mRows[ii]; - int y1 = rd.mRank * rowYSpace - mScrollOffsetY; - gcImage.fillRectangle(0, y1, dim.x, rowYSpace); - } - } - - // Draw the row labels - int offsetY = rowYMarginHalf - mScrollOffsetY; - for (int ii = mStartRow; ii <= mEndRow; ++ii) { - RowData rd = mRows[ii]; - int y1 = rd.mRank * rowYSpace + offsetY; - Point extent = gcImage.stringExtent(rd.mName); - int x1 = dim.x - extent.x - labelMarginX; - gcImage.drawString(rd.mName, x1, y1, true); - } - - // Draw a highlight box on the row where the mouse is. - if (mMouseRow >= mStartRow && mMouseRow <= mEndRow) { - gcImage.setForeground(mColorGray); - int y1 = mMouseRow * rowYSpace - mScrollOffsetY; - gcImage.drawRectangle(0, y1, dim.x, rowYSpace); - } - - // Draw the off-screen buffer to the screen - gc.drawImage(image, 0, 0); - - // Clean up - image.dispose(); - gcImage.dispose(); - } - } - - private class BlankCorner extends Canvas { - public BlankCorner(Composite parent) { - //super(parent, SWT.NO_BACKGROUND); - super(parent, SWT.NONE); - addPaintListener(new PaintListener() { - public void paintControl(PaintEvent pe) { - draw(pe.display, pe.gc); - } - }); - } - - private void draw(Display display, GC gc) { - // Create a blank image and draw it to the canvas - Image image = new Image(display, getBounds()); - gc.drawImage(image, 0, 0); - - // Clean up - image.dispose(); - } - } - - private class Timescale extends Canvas { - private Point mMouse = new Point(LeftMargin, 0); - private Cursor mZoomCursor; - private String mMethodName = null; - private Color mMethodColor = null; - private int mMethodStartY; - private int mMarkStartX; - private int mMarkEndX; - - /** The space between the colored block and the method name */ - private static final int METHOD_BLOCK_MARGIN = 10; - - public Timescale(Composite parent) { - //super(parent, SWT.NO_BACKGROUND); - super(parent, SWT.NONE); - Display display = getDisplay(); - mZoomCursor = new Cursor(display, SWT.CURSOR_SIZEWE); - setCursor(mZoomCursor); - mMethodStartY = mSmallFontHeight + 1; - addPaintListener(new PaintListener() { - public void paintControl(PaintEvent pe) { - draw(pe.display, pe.gc); - } - }); - } - - public void setVbarPosition(int x) { - mMouse.x = x; - } - - public void setMarkStart(int x) { - mMarkStartX = x; - } - - public void setMarkEnd(int x) { - mMarkEndX = x; - } - - public void setMethodName(String name) { - mMethodName = name; - } - - public void setMethodColor(Color color) { - mMethodColor = color; - } - - private void mouseMove(MouseEvent me) { - me.y = -1; - mSurface.mouseMove(me); - } - - private void mouseDown(MouseEvent me) { - mSurface.startScaling(me.x); - mSurface.redraw(); - } - - private void mouseUp(MouseEvent me) { - mSurface.stopScaling(me.x); - } - - private void mouseDoubleClick(MouseEvent me) { - mSurface.resetScale(); - mSurface.redraw(); - } - - private void draw(Display display, GC gc) { - Point dim = getSize(); - - // Create an image for double-buffering - Image image = new Image(display, getBounds()); - - // Set up the off-screen gc - GC gcImage = new GC(image); - if (mSetFonts) - gcImage.setFont(mFontRegistry.get("medium")); // $NON-NLS-1$ - - if (mSurface.drawingSelection()) { - drawSelection(display, gcImage); - } - - drawTicks(display, gcImage); - - // Draw the vertical bar where the mouse is - gcImage.setForeground(mColorDarkGray); - gcImage.drawLine(mMouse.x, timeLineOffsetY, mMouse.x, dim.y); - - // Draw the current millseconds - drawTickLegend(display, gcImage); - - // Draw the method name and color, if needed - drawMethod(display, gcImage); - - // Draw the off-screen buffer to the screen - gc.drawImage(image, 0, 0); - - // Clean up - image.dispose(); - gcImage.dispose(); - } - - private void drawSelection(Display display, GC gc) { - Point dim = getSize(); - gc.setForeground(mColorGray); - gc.drawLine(mMarkStartX, timeLineOffsetY, mMarkStartX, dim.y); - gc.setBackground(mColorZoomSelection); - int x, width; - if (mMarkStartX < mMarkEndX) { - x = mMarkStartX; - width = mMarkEndX - mMarkStartX; - } else { - x = mMarkEndX; - width = mMarkStartX - mMarkEndX; - } - if (width > 1) { - gc.fillRectangle(x, timeLineOffsetY, width, dim.y); - } - } - - private void drawTickLegend(Display display, GC gc) { - int mouseX = mMouse.x - LeftMargin; - double mouseXval = mScaleInfo.pixelToValue(mouseX); - String info = mUnits.labelledString(mouseXval); - gc.setForeground(mColorForeground); - gc.drawString(info, LeftMargin + 2, 1, true); - - // Display the maximum data value - double maxVal = mScaleInfo.getMaxVal(); - info = mUnits.labelledString(maxVal); - info = String.format(" max %s ", info); // $NON-NLS-1$ - Point extent = gc.stringExtent(info); - Point dim = getSize(); - int x1 = dim.x - RightMargin - extent.x; - gc.drawString(info, x1, 1, true); - } - - private void drawMethod(Display display, GC gc) { - if (mMethodName == null) { - return; - } - - int x1 = LeftMargin; - int y1 = mMethodStartY; - gc.setBackground(mMethodColor); - int width = 2 * mSmallFontWidth; - gc.fillRectangle(x1, y1, width, mSmallFontHeight); - x1 += width + METHOD_BLOCK_MARGIN; - gc.drawString(mMethodName, x1, y1, true); - } - - private void drawTicks(Display display, GC gc) { - Point dim = getSize(); - int y2 = majorTickLength + timeLineOffsetY; - int y3 = minorTickLength + timeLineOffsetY; - int y4 = y2 + tickToFontSpacing; - gc.setForeground(mColorForeground); - gc.drawLine(LeftMargin, timeLineOffsetY, dim.x - RightMargin, - timeLineOffsetY); - double minVal = mScaleInfo.getMinVal(); - double maxVal = mScaleInfo.getMaxVal(); - double minMajorTick = mScaleInfo.getMinMajorTick(); - double tickIncrement = mScaleInfo.getTickIncrement(); - double minorTickIncrement = tickIncrement / 5; - double pixelsPerRange = mScaleInfo.getPixelsPerRange(); - - // Draw the initial minor ticks, if any - if (minVal < minMajorTick) { - gc.setForeground(mColorGray); - double xMinor = minMajorTick; - for (int ii = 1; ii <= 4; ++ii) { - xMinor -= minorTickIncrement; - if (xMinor < minVal) - break; - int x1 = LeftMargin - + (int) (0.5 + (xMinor - minVal) * pixelsPerRange); - gc.drawLine(x1, timeLineOffsetY, x1, y3); - } - } - - if (tickIncrement <= 10) { - // TODO avoid rendering the loop when tickIncrement is invalid. It can be zero - // or too small. - // System.out.println(String.format("Timescale.drawTicks error: tickIncrement=%1f", tickIncrement)); - return; - } - for (double x = minMajorTick; x <= maxVal; x += tickIncrement) { - int x1 = LeftMargin - + (int) (0.5 + (x - minVal) * pixelsPerRange); - - // Draw a major tick - gc.setForeground(mColorForeground); - gc.drawLine(x1, timeLineOffsetY, x1, y2); - if (x > maxVal) - break; - - // Draw the tick text - String tickString = mUnits.valueOf(x); - gc.drawString(tickString, x1, y4, true); - - // Draw 4 minor ticks between major ticks - gc.setForeground(mColorGray); - double xMinor = x; - for (int ii = 1; ii <= 4; ii++) { - xMinor += minorTickIncrement; - if (xMinor > maxVal) - break; - x1 = LeftMargin - + (int) (0.5 + (xMinor - minVal) * pixelsPerRange); - gc.drawLine(x1, timeLineOffsetY, x1, y3); - } - } - } - } - - private static enum GraphicsState { - Normal, Marking, Scaling, Animating - }; - - private class Surface extends Canvas { - - public Surface(Composite parent) { - super(parent, SWT.NO_BACKGROUND | SWT.V_SCROLL); - Display display = getDisplay(); - mNormalCursor = new Cursor(display, SWT.CURSOR_CROSS); - mIncreasingCursor = new Cursor(display, SWT.CURSOR_SIZEE); - mDecreasingCursor = new Cursor(display, SWT.CURSOR_SIZEW); - - initZoomFractionsWithExp(); - - addPaintListener(new PaintListener() { - public void paintControl(PaintEvent pe) { - draw(pe.display, pe.gc); - } - }); - - mZoomAnimator = new Runnable() { - public void run() { - animateZoom(); - } - }; - - mHighlightAnimator = new Runnable() { - public void run() { - animateHighlight(); - } - }; - } - - private void initZoomFractionsWithExp() { - mZoomFractions = new double[ZOOM_STEPS]; - int next = 0; - for (int ii = 0; ii < ZOOM_STEPS / 2; ++ii, ++next) { - mZoomFractions[next] = (double) (1 << ii) - / (double) (1 << (ZOOM_STEPS / 2)); - // System.out.printf("%d %f\n", next, zoomFractions[next]); - } - for (int ii = 2; ii < 2 + ZOOM_STEPS / 2; ++ii, ++next) { - mZoomFractions[next] = (double) ((1 << ii) - 1) - / (double) (1 << ii); - // System.out.printf("%d %f\n", next, zoomFractions[next]); - } - } - - @SuppressWarnings("unused") - private void initZoomFractionsWithSinWave() { - mZoomFractions = new double[ZOOM_STEPS]; - for (int ii = 0; ii < ZOOM_STEPS; ++ii) { - double offset = Math.PI * (double) ii / (double) ZOOM_STEPS; - mZoomFractions[ii] = (Math.sin((1.5 * Math.PI + offset)) + 1.0) / 2.0; - // System.out.printf("%d %f\n", ii, zoomFractions[ii]); - } - } - - public void setRange(double minVal, double maxVal) { - mMinDataVal = minVal; - mMaxDataVal = maxVal; - mScaleInfo.setMinVal(minVal); - mScaleInfo.setMaxVal(maxVal); - } - - public void setLimitRange(double minVal, double maxVal) { - mLimitMinVal = minVal; - mLimitMaxVal = maxVal; - } - - public void resetScale() { - mScaleInfo.setMinVal(mLimitMinVal); - mScaleInfo.setMaxVal(mLimitMaxVal); - } - - private void draw(Display display, GC gc) { - if (mSegments.length == 0) { - // gc.setBackground(colorBackground); - // gc.fillRectangle(getBounds()); - return; - } - - // Create an image for double-buffering - Image image = new Image(display, getBounds()); - - // Set up the off-screen gc - GC gcImage = new GC(image); - if (mSetFonts) - gcImage.setFont(mFontRegistry.get("small")); // $NON-NLS-1$ - - // Draw the background - // gcImage.setBackground(colorBackground); - // gcImage.fillRectangle(image.getBounds()); - - if (mGraphicsState == GraphicsState.Scaling) { - double diff = mMouse.x - mMouseMarkStartX; - if (diff > 0) { - double newMinVal = mScaleMinVal - diff / mScalePixelsPerRange; - if (newMinVal < mLimitMinVal) - newMinVal = mLimitMinVal; - mScaleInfo.setMinVal(newMinVal); - // System.out.printf("diff %f scaleMin %f newMin %f\n", - // diff, scaleMinVal, newMinVal); - } else if (diff < 0) { - double newMaxVal = mScaleMaxVal - diff / mScalePixelsPerRange; - if (newMaxVal > mLimitMaxVal) - newMaxVal = mLimitMaxVal; - mScaleInfo.setMaxVal(newMaxVal); - // System.out.printf("diff %f scaleMax %f newMax %f\n", - // diff, scaleMaxVal, newMaxVal); - } - } - - // Recompute the ticks and strips only if the size has changed, - // or we scrolled so that a new row is visible. - Point dim = getSize(); - if (mStartRow != mCachedStartRow || mEndRow != mCachedEndRow - || mScaleInfo.getMinVal() != mCachedMinVal - || mScaleInfo.getMaxVal() != mCachedMaxVal) { - mCachedStartRow = mStartRow; - mCachedEndRow = mEndRow; - int xdim = dim.x - TotalXMargin; - mScaleInfo.setNumPixels(xdim); - boolean forceEndPoints = (mGraphicsState == GraphicsState.Scaling - || mGraphicsState == GraphicsState.Animating); - mScaleInfo.computeTicks(forceEndPoints); - mCachedMinVal = mScaleInfo.getMinVal(); - mCachedMaxVal = mScaleInfo.getMaxVal(); - if (mLimitMinVal > mScaleInfo.getMinVal()) - mLimitMinVal = mScaleInfo.getMinVal(); - if (mLimitMaxVal < mScaleInfo.getMaxVal()) - mLimitMaxVal = mScaleInfo.getMaxVal(); - - // Compute the strips - computeStrips(); - } - - if (mNumRows > 2) { - // Draw the row background stripes - gcImage.setBackground(mColorRowBack); - for (int ii = 1; ii < mNumRows; ii += 2) { - RowData rd = mRows[ii]; - int y1 = rd.mRank * rowYSpace - mScrollOffsetY; - gcImage.fillRectangle(0, y1, dim.x, rowYSpace); - } - } - - if (drawingSelection()) { - drawSelection(display, gcImage); - } - - String blockName = null; - Color blockColor = null; - - if (mDebug) { - double pixelsPerRange = mScaleInfo.getPixelsPerRange(); - System.out - .printf( - "dim.x %d pixels %d minVal %f, maxVal %f ppr %f rpp %f\n", - dim.x, dim.x - TotalXMargin, mScaleInfo - .getMinVal(), mScaleInfo.getMaxVal(), - pixelsPerRange, 1.0 / pixelsPerRange); - } - - // Draw the strips - Block selectBlock = null; - for (Strip strip : mStripList) { - if (strip.mColor == null) { - // System.out.printf("strip.color is null\n"); - continue; - } - gcImage.setBackground(strip.mColor); - gcImage.fillRectangle(strip.mX, strip.mY - mScrollOffsetY, strip.mWidth, - strip.mHeight); - if (mMouseRow == strip.mRowData.mRank) { - if (mMouse.x >= strip.mX - && mMouse.x < strip.mX + strip.mWidth) { - blockName = strip.mSegment.mBlock.getName(); - blockColor = strip.mColor; - } - if (mMouseSelect.x >= strip.mX - && mMouseSelect.x < strip.mX + strip.mWidth) { - selectBlock = strip.mSegment.mBlock; - } - } - } - mMouseSelect.x = 0; - mMouseSelect.y = 0; - - if (selectBlock != null) { - ArrayList<Selection> selections = new ArrayList<Selection>(); - // Get the row label - RowData rd = mRows[mMouseRow]; - selections.add(Selection.highlight("Thread", rd.mName)); // $NON-NLS-1$ - selections.add(Selection.highlight("Call", selectBlock)); // $NON-NLS-1$ - - int mouseX = mMouse.x - LeftMargin; - double mouseXval = mScaleInfo.pixelToValue(mouseX); - selections.add(Selection.highlight("Time", mouseXval)); // $NON-NLS-1$ - - mSelectionController.change(selections, "TimeLineView"); // $NON-NLS-1$ - mHighlightMethodData = null; - mHighlightCall = (Call) selectBlock; - startHighlighting(); - } - - // Draw a highlight box on the row where the mouse is. - // Except don't draw the box if we are animating the - // highlighing of a call or method because the inclusive - // highlight bar passes through the highlight box and - // causes an annoying flashing artifact. - if (mMouseRow >= 0 && mMouseRow < mNumRows && mHighlightStep == 0) { - gcImage.setForeground(mColorGray); - int y1 = mMouseRow * rowYSpace - mScrollOffsetY; - gcImage.drawLine(0, y1, dim.x, y1); - gcImage.drawLine(0, y1 + rowYSpace, dim.x, y1 + rowYSpace); - } - - // Highlight a selected method, if any - drawHighlights(gcImage, dim); - - // Draw a vertical line where the mouse is. - gcImage.setForeground(mColorDarkGray); - int lineEnd = Math.min(dim.y, mNumRows * rowYSpace); - gcImage.drawLine(mMouse.x, 0, mMouse.x, lineEnd); - - if (blockName != null) { - mTimescale.setMethodName(blockName); - mTimescale.setMethodColor(blockColor); - mShowHighlightName = false; - } else if (mShowHighlightName) { - // Draw the highlighted method name - MethodData md = mHighlightMethodData; - if (md == null && mHighlightCall != null) - md = mHighlightCall.getMethodData(); - if (md == null) - System.out.printf("null highlight?\n"); // $NON-NLS-1$ - if (md != null) { - mTimescale.setMethodName(md.getProfileName()); - mTimescale.setMethodColor(md.getColor()); - } - } else { - mTimescale.setMethodName(null); - mTimescale.setMethodColor(null); - } - mTimescale.redraw(); - - // Draw the off-screen buffer to the screen - gc.drawImage(image, 0, 0); - - // Clean up - image.dispose(); - gcImage.dispose(); - } - - private void drawHighlights(GC gc, Point dim) { - int height = highlightHeight; - if (height <= 0) - return; - for (Range range : mHighlightExclusive) { - gc.setBackground(range.mColor); - int xStart = range.mXdim.x; - int width = range.mXdim.y; - gc.fillRectangle(xStart, range.mY - height - mScrollOffsetY, width, height); - } - - // Draw the inclusive lines a bit shorter - height -= 1; - if (height <= 0) - height = 1; - - // Highlight the inclusive ranges - gc.setForeground(mColorDarkGray); - gc.setBackground(mColorDarkGray); - for (Range range : mHighlightInclusive) { - int x1 = range.mXdim.x; - int x2 = range.mXdim.y; - boolean drawLeftEnd = false; - boolean drawRightEnd = false; - if (x1 >= LeftMargin) - drawLeftEnd = true; - else - x1 = LeftMargin; - if (x2 >= LeftMargin) - drawRightEnd = true; - else - x2 = dim.x - RightMargin; - int y1 = range.mY + rowHeight + 2 - mScrollOffsetY; - - // If the range is very narrow, then just draw a small - // rectangle. - if (x2 - x1 < MinInclusiveRange) { - int width = x2 - x1; - if (width < 2) - width = 2; - gc.fillRectangle(x1, y1, width, height); - continue; - } - if (drawLeftEnd) { - if (drawRightEnd) { - // Draw both ends - int[] points = { x1, y1, x1, y1 + height, x2, - y1 + height, x2, y1 }; - gc.drawPolyline(points); - } else { - // Draw the left end - int[] points = { x1, y1, x1, y1 + height, x2, - y1 + height }; - gc.drawPolyline(points); - } - } else { - if (drawRightEnd) { - // Draw the right end - int[] points = { x1, y1 + height, x2, y1 + height, x2, - y1 }; - gc.drawPolyline(points); - } else { - // Draw neither end, just the line - int[] points = { x1, y1 + height, x2, y1 + height }; - gc.drawPolyline(points); - } - } - - // Draw the arrowheads, if necessary - if (drawLeftEnd == false) { - int[] points = { x1 + 7, y1 + height - 4, x1, y1 + height, - x1 + 7, y1 + height + 4 }; - gc.fillPolygon(points); - } - if (drawRightEnd == false) { - int[] points = { x2 - 7, y1 + height - 4, x2, y1 + height, - x2 - 7, y1 + height + 4 }; - gc.fillPolygon(points); - } - } - } - - private boolean drawingSelection() { - return mGraphicsState == GraphicsState.Marking - || mGraphicsState == GraphicsState.Animating; - } - - private void drawSelection(Display display, GC gc) { - Point dim = getSize(); - gc.setForeground(mColorGray); - gc.drawLine(mMouseMarkStartX, 0, mMouseMarkStartX, dim.y); - gc.setBackground(mColorZoomSelection); - int width; - int mouseX = (mGraphicsState == GraphicsState.Animating) ? mMouseMarkEndX : mMouse.x; - int x; - if (mMouseMarkStartX < mouseX) { - x = mMouseMarkStartX; - width = mouseX - mMouseMarkStartX; - } else { - x = mouseX; - width = mMouseMarkStartX - mouseX; - } - gc.fillRectangle(x, 0, width, dim.y); - } - - private void computeStrips() { - double minVal = mScaleInfo.getMinVal(); - double maxVal = mScaleInfo.getMaxVal(); - - // Allocate space for the pixel data - Pixel[] pixels = new Pixel[mNumRows]; - for (int ii = 0; ii < mNumRows; ++ii) - pixels[ii] = new Pixel(); - - // Clear the per-block pixel data - for (int ii = 0; ii < mSegments.length; ++ii) { - mSegments[ii].mBlock.clearWeight(); - } - - mStripList.clear(); - mHighlightExclusive.clear(); - mHighlightInclusive.clear(); - MethodData callMethod = null; - long callStart = 0; - long callEnd = -1; - RowData callRowData = null; - int prevMethodStart = -1; - int prevCallStart = -1; - if (mHighlightCall != null) { - int callPixelStart = -1; - int callPixelEnd = -1; - callStart = mHighlightCall.mGlobalStartTime; - callEnd = mHighlightCall.mGlobalEndTime; - callMethod = mHighlightCall.mMethodData; - if (callStart >= minVal) - callPixelStart = mScaleInfo.valueToPixel(callStart); - if (callEnd <= maxVal) - callPixelEnd = mScaleInfo.valueToPixel(callEnd); - // System.out.printf("callStart,End %d,%d minVal,maxVal %f,%f - // callPixelStart,End %d,%d\n", - // callStart, callEnd, minVal, maxVal, callPixelStart, - // callPixelEnd); - int threadId = mHighlightCall.getThreadId(); - String threadName = mThreadLabels.get(threadId); - callRowData = mRowByName.get(threadName); - int y1 = callRowData.mRank * rowYSpace + rowYMarginHalf; - Color color = callMethod.getColor(); - mHighlightInclusive.add(new Range(callPixelStart + LeftMargin, - callPixelEnd + LeftMargin, y1, color)); - } - for (Segment segment : mSegments) { - if (segment.mEndTime <= minVal) - continue; - if (segment.mStartTime >= maxVal) - continue; - Block block = segment.mBlock; - Color color = block.getColor(); - if (color == null) - continue; - - double recordStart = Math.max(segment.mStartTime, minVal); - double recordEnd = Math.min(segment.mEndTime, maxVal); - if (recordStart == recordEnd) - continue; - int pixelStart = mScaleInfo.valueToPixel(recordStart); - int pixelEnd = mScaleInfo.valueToPixel(recordEnd); - int width = pixelEnd - pixelStart; - - RowData rd = segment.mRowData; - MethodData md = block.getMethodData(); - - // We will add the scroll offset later when we draw the strips - int y1 = rd.mRank * rowYSpace + rowYMarginHalf; - - // If we can't display any more rows, then quit - if (rd.mRank > mEndRow) - break; - - // System.out.printf("segment %s val: [%.1f, %.1f] frac [%f, %f] - // pixel: [%d, %d] pix.start %d weight %.2f %s\n", - // block.getName(), recordStart, recordEnd, - // scaleInfo.valueToPixelFraction(recordStart), - // scaleInfo.valueToPixelFraction(recordEnd), - // pixelStart, pixelEnd, pixels[rd.rank].start, - // pixels[rd.rank].maxWeight, - // pixels[rd.rank].segment != null - // ? pixels[rd.rank].segment.block.getName() - // : "null"); - - if (mHighlightMethodData != null) { - if (mHighlightMethodData == md) { - if (prevMethodStart != pixelStart) { - prevMethodStart = pixelStart; - int rangeWidth = width; - if (rangeWidth == 0) - rangeWidth = 1; - mHighlightExclusive.add(new Range(pixelStart - + LeftMargin, rangeWidth, y1, color)); - Call call = (Call) block; - callStart = call.mGlobalStartTime; - int callPixelStart = -1; - if (callStart >= minVal) - callPixelStart = mScaleInfo.valueToPixel(callStart); - if (prevCallStart != callPixelStart) { - prevCallStart = callPixelStart; - int callPixelEnd = -1; - callEnd = call.mGlobalEndTime; - if (callEnd <= maxVal) - callPixelEnd = mScaleInfo.valueToPixel(callEnd); - mHighlightInclusive.add(new Range( - callPixelStart + LeftMargin, - callPixelEnd + LeftMargin, y1, color)); - } - } - } else if (mFadeColors) { - color = md.getFadedColor(); - } - } else if (mHighlightCall != null) { - if (segment.mStartTime >= callStart - && segment.mEndTime <= callEnd && callMethod == md - && callRowData == rd) { - if (prevMethodStart != pixelStart) { - prevMethodStart = pixelStart; - int rangeWidth = width; - if (rangeWidth == 0) - rangeWidth = 1; - mHighlightExclusive.add(new Range(pixelStart - + LeftMargin, rangeWidth, y1, color)); - } - } else if (mFadeColors) { - color = md.getFadedColor(); - } - } - - // Cases: - // 1. This segment starts on a different pixel than the - // previous segment started on. In this case, emit - // the pixel strip, if any, and: - // A. If the width is 0, then add this segment's - // weight to the Pixel. - // B. If the width > 0, then emit a strip for this - // segment (no partial Pixel data). - // - // 2. Otherwise (the new segment starts on the same - // pixel as the previous segment): add its "weight" - // to the current pixel, and: - // A. If the new segment has width 1, - // then emit the pixel strip and then - // add the segment's weight to the pixel. - // B. If the new segment has width > 1, - // then emit the pixel strip, and emit the rest - // of the strip for this segment (no partial Pixel - // data). - - Pixel pix = pixels[rd.mRank]; - if (pix.mStart != pixelStart) { - if (pix.mSegment != null) { - // Emit the pixel strip. This also clears the pixel. - emitPixelStrip(rd, y1, pix); - } - - if (width == 0) { - // Compute the "weight" of this segment for the first - // pixel. For a pixel N, the "weight" of a segment is - // how much of the region [N - 0.5, N + 0.5] is covered - // by the segment. - double weight = computeWeight(recordStart, recordEnd, - pixelStart); - weight = block.addWeight(pixelStart, rd.mRank, weight); - if (weight > pix.mMaxWeight) { - pix.setFields(pixelStart, weight, segment, color, - rd); - } - } else { - int x1 = pixelStart + LeftMargin; - Strip strip = new Strip(x1, y1, width, rowHeight, rd, - segment, color); - mStripList.add(strip); - } - } else { - double weight = computeWeight(recordStart, recordEnd, - pixelStart); - weight = block.addWeight(pixelStart, rd.mRank, weight); - if (weight > pix.mMaxWeight) { - pix.setFields(pixelStart, weight, segment, color, rd); - } - if (width == 1) { - // Emit the pixel strip. This also clears the pixel. - emitPixelStrip(rd, y1, pix); - - // Compute the weight for the next pixel - pixelStart += 1; - weight = computeWeight(recordStart, recordEnd, - pixelStart); - weight = block.addWeight(pixelStart, rd.mRank, weight); - pix.setFields(pixelStart, weight, segment, color, rd); - } else if (width > 1) { - // Emit the pixel strip. This also clears the pixel. - emitPixelStrip(rd, y1, pix); - - // Emit a strip for the rest of the segment. - pixelStart += 1; - width -= 1; - int x1 = pixelStart + LeftMargin; - Strip strip = new Strip(x1, y1, width, rowHeight, rd, - segment, color); - mStripList.add(strip); - } - } - } - - // Emit the last pixels of each row, if any - for (int ii = 0; ii < mNumRows; ++ii) { - Pixel pix = pixels[ii]; - if (pix.mSegment != null) { - RowData rd = pix.mRowData; - int y1 = rd.mRank * rowYSpace + rowYMarginHalf; - // Emit the pixel strip. This also clears the pixel. - emitPixelStrip(rd, y1, pix); - } - } - - if (false) { - System.out.printf("computeStrips()\n"); - for (Strip strip : mStripList) { - System.out.printf("%3d, %3d width %3d height %d %s\n", - strip.mX, strip.mY, strip.mWidth, strip.mHeight, - strip.mSegment.mBlock.getName()); - } - } - } - - private double computeWeight(double start, double end, int pixel) { - double pixelStartFraction = mScaleInfo.valueToPixelFraction(start); - double pixelEndFraction = mScaleInfo.valueToPixelFraction(end); - double leftEndPoint = Math.max(pixelStartFraction, pixel - 0.5); - double rightEndPoint = Math.min(pixelEndFraction, pixel + 0.5); - double weight = rightEndPoint - leftEndPoint; - return weight; - } - - private void emitPixelStrip(RowData rd, int y, Pixel pixel) { - Strip strip; - - if (pixel.mSegment == null) - return; - - int x = pixel.mStart + LeftMargin; - // Compute the percentage of the row height proportional to - // the weight of this pixel. But don't let the proportion - // exceed 3/4 of the row height so that we can easily see - // if a given time range includes more than one method. - int height = (int) (pixel.mMaxWeight * rowHeight * 0.75); - if (height < mMinStripHeight) - height = mMinStripHeight; - int remainder = rowHeight - height; - if (remainder > 0) { - strip = new Strip(x, y, 1, remainder, rd, pixel.mSegment, - mFadeColors ? mColorGray : mColorBlack); - mStripList.add(strip); - // System.out.printf("emitPixel (%d, %d) height %d black\n", - // x, y, remainder); - } - strip = new Strip(x, y + remainder, 1, height, rd, pixel.mSegment, - pixel.mColor); - mStripList.add(strip); - // System.out.printf("emitPixel (%d, %d) height %d %s\n", - // x, y + remainder, height, pixel.segment.block.getName()); - pixel.mSegment = null; - pixel.mMaxWeight = 0.0; - } - - private void mouseMove(MouseEvent me) { - if (false) { - if (mHighlightMethodData != null) { - mHighlightMethodData = null; - // Force a recomputation of the strip colors - mCachedEndRow = -1; - } - } - Point dim = mSurface.getSize(); - int x = me.x; - if (x < LeftMargin) - x = LeftMargin; - if (x > dim.x - RightMargin) - x = dim.x - RightMargin; - mMouse.x = x; - mMouse.y = me.y; - mTimescale.setVbarPosition(x); - if (mGraphicsState == GraphicsState.Marking) { - mTimescale.setMarkEnd(x); - } - - if (mGraphicsState == GraphicsState.Normal) { - // Set the cursor to the normal state. - mSurface.setCursor(mNormalCursor); - } else if (mGraphicsState == GraphicsState.Marking) { - // Make the cursor point in the direction of the sweep - if (mMouse.x >= mMouseMarkStartX) - mSurface.setCursor(mIncreasingCursor); - else - mSurface.setCursor(mDecreasingCursor); - } - int rownum = (mMouse.y + mScrollOffsetY) / rowYSpace; - if (me.y < 0 || me.y >= dim.y) { - rownum = -1; - } - if (mMouseRow != rownum) { - mMouseRow = rownum; - mLabels.redraw(); - } - redraw(); - } - - private void mouseDown(MouseEvent me) { - Point dim = mSurface.getSize(); - int x = me.x; - if (x < LeftMargin) - x = LeftMargin; - if (x > dim.x - RightMargin) - x = dim.x - RightMargin; - mMouseMarkStartX = x; - mGraphicsState = GraphicsState.Marking; - mSurface.setCursor(mIncreasingCursor); - mTimescale.setMarkStart(mMouseMarkStartX); - mTimescale.setMarkEnd(mMouseMarkStartX); - redraw(); - } - - private void mouseUp(MouseEvent me) { - mSurface.setCursor(mNormalCursor); - if (mGraphicsState != GraphicsState.Marking) { - mGraphicsState = GraphicsState.Normal; - return; - } - mGraphicsState = GraphicsState.Animating; - Point dim = mSurface.getSize(); - - // If the user released the mouse outside the drawing area then - // cancel the zoom. - if (me.y <= 0 || me.y >= dim.y) { - mGraphicsState = GraphicsState.Normal; - redraw(); - return; - } - - int x = me.x; - if (x < LeftMargin) - x = LeftMargin; - if (x > dim.x - RightMargin) - x = dim.x - RightMargin; - mMouseMarkEndX = x; - - // If the user clicked and released the mouse at the same point - // (+/- a pixel or two) then cancel the zoom (but select the - // method). - int dist = mMouseMarkEndX - mMouseMarkStartX; - if (dist < 0) - dist = -dist; - if (dist <= 2) { - mGraphicsState = GraphicsState.Normal; - - // Select the method underneath the mouse - mMouseSelect.x = mMouseMarkStartX; - mMouseSelect.y = me.y; - redraw(); - return; - } - - // Make mouseEndX be the higher end point - if (mMouseMarkEndX < mMouseMarkStartX) { - int temp = mMouseMarkEndX; - mMouseMarkEndX = mMouseMarkStartX; - mMouseMarkStartX = temp; - } - - // If the zoom area is the whole window (or nearly the whole - // window) then cancel the zoom. - if (mMouseMarkStartX <= LeftMargin + MinZoomPixelMargin - && mMouseMarkEndX >= dim.x - RightMargin - MinZoomPixelMargin) { - mGraphicsState = GraphicsState.Normal; - redraw(); - return; - } - - // Compute some variables needed for zooming. - // It's probably easiest to explain by an example. There - // are two scales (or dimensions) involved: one for the pixels - // and one for the values (microseconds). To keep the example - // simple, suppose we have pixels in the range [0,16] and - // values in the range [100, 260], and suppose the user - // selects a zoom window from pixel 4 to pixel 8. - // - // usec: 100 140 180 260 - // |-------|ZZZZZZZ|---------------| - // pixel: 0 4 8 16 - // - // I've drawn the pixels starting at zero for simplicity, but - // in fact the drawable area is offset from the left margin - // by the value of "LeftMargin". - // - // The "pixels-per-range" (ppr) in this case is 0.1 (a tenth of - // a pixel per usec). What we want is to redraw the screen in - // several steps, each time increasing the zoom window until the - // zoom window fills the screen. For simplicity, assume that - // we want to zoom in four equal steps. Then the snapshots - // of the screen at each step would look something like this: - // - // usec: 100 140 180 260 - // |-------|ZZZZZZZ|---------------| - // pixel: 0 4 8 16 - // - // usec: ? 140 180 ? - // |-----|ZZZZZZZZZZZZZ|-----------| - // pixel: 0 3 10 16 - // - // usec: ? 140 180 ? - // |---|ZZZZZZZZZZZZZZZZZZZ|-------| - // pixel: 0 2 12 16 - // - // usec: ?140 180 ? - // |-|ZZZZZZZZZZZZZZZZZZZZZZZZZ|---| - // pixel: 0 1 14 16 - // - // usec: 140 180 - // |ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ| - // pixel: 0 16 - // - // The problem is how to compute the endpoints (denoted by ?) - // for each step. This is a little tricky. We first need to - // compute the "fixed point": this is the point in the selection - // that doesn't move left or right. Then we can recompute the - // "ppr" (pixels per range) at each step and then find the - // endpoints. The computation of the end points is done - // in animateZoom(). This method computes the fixed point - // and some other variables needed in animateZoom(). - - double minVal = mScaleInfo.getMinVal(); - double maxVal = mScaleInfo.getMaxVal(); - double ppr = mScaleInfo.getPixelsPerRange(); - mZoomMin = minVal + ((mMouseMarkStartX - LeftMargin) / ppr); - mZoomMax = minVal + ((mMouseMarkEndX - LeftMargin) / ppr); - - // Clamp the min and max values to the actual data min and max - if (mZoomMin < mMinDataVal) - mZoomMin = mMinDataVal; - if (mZoomMax > mMaxDataVal) - mZoomMax = mMaxDataVal; - - // Snap the min and max points to the grid determined by the - // TickScaler - // before we zoom. - int xdim = dim.x - TotalXMargin; - TickScaler scaler = new TickScaler(mZoomMin, mZoomMax, xdim, - PixelsPerTick); - scaler.computeTicks(false); - mZoomMin = scaler.getMinVal(); - mZoomMax = scaler.getMaxVal(); - - // Also snap the mouse points (in pixel space) to be consistent with - // zoomMin and zoomMax (in value space). - mMouseMarkStartX = (int) ((mZoomMin - minVal) * ppr + LeftMargin); - mMouseMarkEndX = (int) ((mZoomMax - minVal) * ppr + LeftMargin); - mTimescale.setMarkStart(mMouseMarkStartX); - mTimescale.setMarkEnd(mMouseMarkEndX); - - // Compute the mouse selection end point distances - mMouseEndDistance = dim.x - RightMargin - mMouseMarkEndX; - mMouseStartDistance = mMouseMarkStartX - LeftMargin; - mZoomMouseStart = mMouseMarkStartX; - mZoomMouseEnd = mMouseMarkEndX; - mZoomStep = 0; - - // Compute the fixed point in both value space and pixel space. - mMin2ZoomMin = mZoomMin - minVal; - mZoomMax2Max = maxVal - mZoomMax; - mZoomFixed = mZoomMin + (mZoomMax - mZoomMin) * mMin2ZoomMin - / (mMin2ZoomMin + mZoomMax2Max); - mZoomFixedPixel = (mZoomFixed - minVal) * ppr + LeftMargin; - mFixedPixelStartDistance = mZoomFixedPixel - LeftMargin; - mFixedPixelEndDistance = dim.x - RightMargin - mZoomFixedPixel; - - mZoomMin2Fixed = mZoomFixed - mZoomMin; - mFixed2ZoomMax = mZoomMax - mZoomFixed; - - getDisplay().timerExec(ZOOM_TIMER_INTERVAL, mZoomAnimator); - redraw(); - update(); - } - - // No defined behavior yet for double-click. - private void mouseDoubleClick(MouseEvent me) { - } - - public void startScaling(int mouseX) { - Point dim = mSurface.getSize(); - int x = mouseX; - if (x < LeftMargin) - x = LeftMargin; - if (x > dim.x - RightMargin) - x = dim.x - RightMargin; - mMouseMarkStartX = x; - mGraphicsState = GraphicsState.Scaling; - mScalePixelsPerRange = mScaleInfo.getPixelsPerRange(); - mScaleMinVal = mScaleInfo.getMinVal(); - mScaleMaxVal = mScaleInfo.getMaxVal(); - } - - public void stopScaling(int mouseX) { - mGraphicsState = GraphicsState.Normal; - } - - private void animateHighlight() { - mHighlightStep += 1; - if (mHighlightStep >= HIGHLIGHT_STEPS) { - mFadeColors = false; - mHighlightStep = 0; - // Force a recomputation of the strip colors - mCachedEndRow = -1; - } else { - mFadeColors = true; - mShowHighlightName = true; - highlightHeight = highlightHeights[mHighlightStep]; - getDisplay().timerExec(HIGHLIGHT_TIMER_INTERVAL, mHighlightAnimator); - } - redraw(); - } - - private void clearHighlights() { - // System.out.printf("clearHighlights()\n"); - mShowHighlightName = false; - highlightHeight = 0; - mHighlightMethodData = null; - mHighlightCall = null; - mFadeColors = false; - mHighlightStep = 0; - // Force a recomputation of the strip colors - mCachedEndRow = -1; - redraw(); - } - - private void animateZoom() { - mZoomStep += 1; - if (mZoomStep > ZOOM_STEPS) { - mGraphicsState = GraphicsState.Normal; - // Force a normal recomputation - mCachedMinVal = mScaleInfo.getMinVal() + 1; - } else if (mZoomStep == ZOOM_STEPS) { - mScaleInfo.setMinVal(mZoomMin); - mScaleInfo.setMaxVal(mZoomMax); - mMouseMarkStartX = LeftMargin; - Point dim = getSize(); - mMouseMarkEndX = dim.x - RightMargin; - mTimescale.setMarkStart(mMouseMarkStartX); - mTimescale.setMarkEnd(mMouseMarkEndX); - getDisplay().timerExec(ZOOM_TIMER_INTERVAL, mZoomAnimator); - } else { - // Zoom in slowly at first, then speed up, then slow down. - // The zoom fractions are precomputed to save time. - double fraction = mZoomFractions[mZoomStep]; - mMouseMarkStartX = (int) (mZoomMouseStart - fraction * mMouseStartDistance); - mMouseMarkEndX = (int) (mZoomMouseEnd + fraction * mMouseEndDistance); - mTimescale.setMarkStart(mMouseMarkStartX); - mTimescale.setMarkEnd(mMouseMarkEndX); - - // Compute the new pixels-per-range. Avoid division by zero. - double ppr; - if (mZoomMin2Fixed >= mFixed2ZoomMax) - ppr = (mZoomFixedPixel - mMouseMarkStartX) / mZoomMin2Fixed; - else - ppr = (mMouseMarkEndX - mZoomFixedPixel) / mFixed2ZoomMax; - double newMin = mZoomFixed - mFixedPixelStartDistance / ppr; - double newMax = mZoomFixed + mFixedPixelEndDistance / ppr; - mScaleInfo.setMinVal(newMin); - mScaleInfo.setMaxVal(newMax); - - getDisplay().timerExec(ZOOM_TIMER_INTERVAL, mZoomAnimator); - } - redraw(); - } - - private static final int TotalXMargin = LeftMargin + RightMargin; - private static final int yMargin = 1; // blank space on top - // The minimum margin on each side of the zoom window, in pixels. - private static final int MinZoomPixelMargin = 10; - private GraphicsState mGraphicsState = GraphicsState.Normal; - private Point mMouse = new Point(LeftMargin, 0); - private int mMouseMarkStartX; - private int mMouseMarkEndX; - private boolean mDebug = false; - private ArrayList<Strip> mStripList = new ArrayList<Strip>(); - private ArrayList<Range> mHighlightExclusive = new ArrayList<Range>(); - private ArrayList<Range> mHighlightInclusive = new ArrayList<Range>(); - private int mMinStripHeight = 2; - private double mCachedMinVal; - private double mCachedMaxVal; - private int mCachedStartRow; - private int mCachedEndRow; - private double mScalePixelsPerRange; - private double mScaleMinVal; - private double mScaleMaxVal; - private double mLimitMinVal; - private double mLimitMaxVal; - private double mMinDataVal; - private double mMaxDataVal; - private Cursor mNormalCursor; - private Cursor mIncreasingCursor; - private Cursor mDecreasingCursor; - private static final int ZOOM_TIMER_INTERVAL = 10; - private static final int HIGHLIGHT_TIMER_INTERVAL = 50; - private static final int ZOOM_STEPS = 8; // must be even - private int highlightHeight = 4; - private final int[] highlightHeights = { 0, 2, 4, 5, 6, 5, 4, 2, 4, 5, - 6 }; - private final int HIGHLIGHT_STEPS = highlightHeights.length; - private boolean mFadeColors; - private boolean mShowHighlightName; - private double[] mZoomFractions; - private int mZoomStep; - private int mZoomMouseStart; - private int mZoomMouseEnd; - private int mMouseStartDistance; - private int mMouseEndDistance; - private Point mMouseSelect = new Point(0, 0); - private double mZoomFixed; - private double mZoomFixedPixel; - private double mFixedPixelStartDistance; - private double mFixedPixelEndDistance; - private double mZoomMin2Fixed; - private double mMin2ZoomMin; - private double mFixed2ZoomMax; - private double mZoomMax2Max; - private double mZoomMin; - private double mZoomMax; - private Runnable mZoomAnimator; - private Runnable mHighlightAnimator; - private int mHighlightStep; - } - - private int computeVisibleRows(int ydim) { - // If we resize, then move the bottom row down. Don't allow the scroll - // to waste space at the bottom. - int offsetY = mScrollOffsetY; - int spaceNeeded = mNumRows * rowYSpace; - if (offsetY + ydim > spaceNeeded) { - offsetY = spaceNeeded - ydim; - if (offsetY < 0) { - offsetY = 0; - } - } - mStartRow = offsetY / rowYSpace; - mEndRow = (offsetY + ydim) / rowYSpace; - if (mEndRow >= mNumRows) { - mEndRow = mNumRows - 1; - } - - return offsetY; - } - - private void startHighlighting() { - // System.out.printf("startHighlighting()\n"); - mSurface.mHighlightStep = 0; - mSurface.mFadeColors = true; - // Force a recomputation of the color strips - mSurface.mCachedEndRow = -1; - getDisplay().timerExec(0, mSurface.mHighlightAnimator); - } - - private static class RowData { - RowData(Row row) { - mName = row.getName(); - mStack = new ArrayList<Block>(); - } - - public void push(Block block) { - mStack.add(block); - } - - public Block top() { - if (mStack.size() == 0) - return null; - return mStack.get(mStack.size() - 1); - } - - public void pop() { - if (mStack.size() == 0) - return; - mStack.remove(mStack.size() - 1); - } - - private String mName; - private int mRank; - private long mElapsed; - private long mEndTime; - private ArrayList<Block> mStack; - } - - private static class Segment { - Segment(RowData rowData, Block block, long startTime, long endTime) { - mRowData = rowData; - mBlock = block; - mStartTime = startTime; - mEndTime = endTime; - } - - private RowData mRowData; - private Block mBlock; - private long mStartTime; - private long mEndTime; - } - - private static class Strip { - Strip(int x, int y, int width, int height, RowData rowData, - Segment segment, Color color) { - mX = x; - mY = y; - mWidth = width; - mHeight = height; - mRowData = rowData; - mSegment = segment; - mColor = color; - } - - int mX; - int mY; - int mWidth; - int mHeight; - RowData mRowData; - Segment mSegment; - Color mColor; - } - - private static class Pixel { - public void setFields(int start, double weight, Segment segment, - Color color, RowData rowData) { - mStart = start; - mMaxWeight = weight; - mSegment = segment; - mColor = color; - mRowData = rowData; - } - - int mStart = -2; // some value that won't match another pixel - double mMaxWeight; - Segment mSegment; - Color mColor; // we need the color here because it may be faded - RowData mRowData; - } - - private static class Range { - Range(int xStart, int width, int y, Color color) { - mXdim.x = xStart; - mXdim.y = width; - mY = y; - mColor = color; - } - - Point mXdim = new Point(0, 0); - int mY; - Color mColor; - } -} diff --git a/traceview/src/com/android/traceview/TraceReader.java b/traceview/src/com/android/traceview/TraceReader.java deleted file mode 100644 index ae75876..0000000 --- a/traceview/src/com/android/traceview/TraceReader.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import java.util.ArrayList; -import java.util.HashMap; - -public abstract class TraceReader { - - private TraceUnits mTraceUnits; - - public TraceUnits getTraceUnits() { - if (mTraceUnits == null) - mTraceUnits = new TraceUnits(); - return mTraceUnits; - } - - public ArrayList<TimeLineView.Record> getThreadTimeRecords() { - return null; - } - - public HashMap<Integer, String> getThreadLabels() { - return null; - } - - public MethodData[] getMethods() { - return null; - } - - public ThreadData[] getThreads() { - return null; - } - - public long getEndTime() { - return 0; - } - - public ProfileProvider getProfileProvider() { - return null; - } -} diff --git a/traceview/src/com/android/traceview/TraceUnits.java b/traceview/src/com/android/traceview/TraceUnits.java deleted file mode 100644 index 20938f5..0000000 --- a/traceview/src/com/android/traceview/TraceUnits.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * 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. - */ - -package com.android.traceview; - -import java.text.DecimalFormat; - -// This should be a singleton. -public class TraceUnits { - - private TimeScale mTimeScale = TimeScale.MicroSeconds; - private double mScale = 1.0; - DecimalFormat mFormatter = new DecimalFormat(); - - public double getScaledValue(long value) { - return value * mScale; - } - - public double getScaledValue(double value) { - return value * mScale; - } - - public String valueOf(long value) { - return valueOf((double) value); - } - - public String valueOf(double value) { - String pattern; - double scaled = value * mScale; - if ((int) scaled == scaled) - pattern = "###,###"; - else - pattern = "###,###.###"; - mFormatter.applyPattern(pattern); - return mFormatter.format(scaled); - } - - public String labelledString(double value) { - String units = label(); - String num = valueOf(value); - return String.format("%s: %s", units, num); - } - - public String labelledString(long value) { - return labelledString((double) value); - } - - public String label() { - if (mScale == 1.0) - return "usec"; - if (mScale == 0.001) - return "msec"; - if (mScale == 0.000001) - return "sec"; - return null; - } - - public void setTimeScale(TimeScale val) { - mTimeScale = val; - switch (val) { - case Seconds: - mScale = 0.000001; - break; - case MilliSeconds: - mScale = 0.001; - break; - case MicroSeconds: - mScale = 1.0; - break; - } - } - - public TimeScale getTimeScale() { - return mTimeScale; - } - - public enum TimeScale { - Seconds, MilliSeconds, MicroSeconds - }; -} diff --git a/traceview/src/resources/icons/sort_down.png b/traceview/src/resources/icons/sort_down.png Binary files differdeleted file mode 100644 index de6a2a0..0000000 --- a/traceview/src/resources/icons/sort_down.png +++ /dev/null diff --git a/traceview/src/resources/icons/sort_up.png b/traceview/src/resources/icons/sort_up.png Binary files differdeleted file mode 100644 index 8578a87..0000000 --- a/traceview/src/resources/icons/sort_up.png +++ /dev/null |