OSDN Git Service

original
[gb-231r1-is01/GB_2.3_IS01.git] / sdk / traceview / src / com / android / traceview / ProfileProvider.java
diff --git a/sdk/traceview/src/com/android/traceview/ProfileProvider.java b/sdk/traceview/src/com/android/traceview/ProfileProvider.java
new file mode 100644 (file)
index 0000000..fe5c832
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ * 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();
+        }
+    }
+}