ahat - An android heap dump viewer. Initial checkin.

ahat is an android-aware heap dump viewer based on perflib with a
simple html interface.

Change-Id: I7c18a7603dbbe735f778a95cd047f4f9ec1705ef
diff --git a/tools/ahat/src/Sort.java b/tools/ahat/src/Sort.java
new file mode 100644
index 0000000..3b79166
--- /dev/null
+++ b/tools/ahat/src/Sort.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2015 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.ahat;
+
+import com.android.tools.perflib.heap.Instance;
+import com.android.tools.perflib.heap.Heap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Iterator;
+
+/**
+ * Provides Comparators and helper functions for sorting Instances, Sites, and
+ * other things.
+ *
+ * Note: The Comparators defined here impose orderings that are inconsistent
+ * with equals. They should not be used for element lookup or search. They
+ * should only be used for showing elements to the user in different orders.
+ */
+class Sort {
+  /**
+   * Compare instances by their instance id.
+   * This sorts instances from smaller id to larger id.
+   */
+  public static class InstanceById implements Comparator<Instance> {
+    @Override
+    public int compare(Instance a, Instance b) {
+      return Long.compare(a.getId(), b.getId());
+    }
+  }
+
+  /**
+   * Compare instances by their total retained size.
+   * Different instances with the same total retained size are considered
+   * equal for the purposes of comparison.
+   * This sorts instances from larger retained size to smaller retained size.
+   */
+  public static class InstanceByTotalRetainedSize implements Comparator<Instance> {
+    @Override
+    public int compare(Instance a, Instance b) {
+      return Long.compare(b.getTotalRetainedSize(), a.getTotalRetainedSize());
+    }
+  }
+
+  /**
+   * Compare instances by their retained size for a given heap index.
+   * Different instances with the same total retained size are considered
+   * equal for the purposes of comparison.
+   * This sorts instances from larger retained size to smaller retained size.
+   */
+  public static class InstanceByHeapRetainedSize implements Comparator<Instance> {
+    private int mIndex;
+
+    public InstanceByHeapRetainedSize(AhatSnapshot snapshot, Heap heap) {
+      mIndex = snapshot.getHeapIndex(heap);
+    }
+
+    public InstanceByHeapRetainedSize(int heapIndex) {
+      mIndex = heapIndex;
+    }
+
+    @Override
+    public int compare(Instance a, Instance b) {
+      return Long.compare(b.getRetainedSize(mIndex), a.getRetainedSize(mIndex));
+    }
+  }
+
+  /**
+   * Compare objects based on a list of comparators, giving priority to the
+   * earlier comparators in the list.
+   */
+  public static class WithPriority<T> implements Comparator<T> {
+    private List<Comparator<T>> mComparators;
+
+    public WithPriority(Comparator<T>... comparators) {
+      mComparators = Arrays.asList(comparators);
+    }
+
+    public WithPriority(List<Comparator<T>> comparators) {
+      mComparators = comparators;
+    }
+
+    @Override
+    public int compare(T a, T b) {
+      int res = 0;
+      Iterator<Comparator<T>> iter = mComparators.iterator();
+      while (res == 0 && iter.hasNext()) {
+        res = iter.next().compare(a, b);
+      }
+      return res;
+    }
+  }
+
+  public static Comparator<Instance> defaultInstanceCompare(AhatSnapshot snapshot) {
+    List<Comparator<Instance>> comparators = new ArrayList<Comparator<Instance>>();
+
+    // Priority goes to the app heap, if we can find one.
+    Heap appHeap = snapshot.getHeap("app");
+    if (appHeap != null) {
+      comparators.add(new InstanceByHeapRetainedSize(snapshot, appHeap));
+    }
+
+    // Next is by total retained size.
+    comparators.add(new InstanceByTotalRetainedSize());
+    return new WithPriority<Instance>(comparators);
+  }
+
+  /**
+   * Compare Sites by the size of objects allocated on a given heap.
+   * Different object infos with the same size on the given heap are
+   * considered equal for the purposes of comparison.
+   * This sorts sites from larger size to smaller size.
+   */
+  public static class SiteBySize implements Comparator<Site> {
+    String mHeap;
+
+    public SiteBySize(String heap) {
+      mHeap = heap;
+    }
+
+    @Override
+    public int compare(Site a, Site b) {
+      return Long.compare(b.getSize(mHeap), a.getSize(mHeap));
+    }
+  }
+
+  /**
+   * Compare Site.ObjectsInfo by their size.
+   * Different object infos with the same total retained size are considered
+   * equal for the purposes of comparison.
+   * This sorts object infos from larger retained size to smaller size.
+   */
+  public static class ObjectsInfoBySize implements Comparator<Site.ObjectsInfo> {
+    @Override
+    public int compare(Site.ObjectsInfo a, Site.ObjectsInfo b) {
+      return Long.compare(b.numBytes, a.numBytes);
+    }
+  }
+
+  /**
+   * Compare Site.ObjectsInfo by heap name.
+   * Different object infos with the same heap name are considered equal for
+   * the purposes of comparison.
+   */
+  public static class ObjectsInfoByHeapName implements Comparator<Site.ObjectsInfo> {
+    @Override
+    public int compare(Site.ObjectsInfo a, Site.ObjectsInfo b) {
+      return a.heap.getName().compareTo(b.heap.getName());
+    }
+  }
+
+  /**
+   * Compare Site.ObjectsInfo by class name.
+   * Different object infos with the same class name are considered equal for
+   * the purposes of comparison.
+   */
+  public static class ObjectsInfoByClassName implements Comparator<Site.ObjectsInfo> {
+    @Override
+    public int compare(Site.ObjectsInfo a, Site.ObjectsInfo b) {
+      String aName = AhatSnapshot.getClassName(a.classObj);
+      String bName = AhatSnapshot.getClassName(b.classObj);
+      return aName.compareTo(bName);
+    }
+  }
+}
+