--- /dev/null
+/*
+ * Copyright (C) 2007 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.ddmuilib;
+
+import com.android.ddmlib.HeapSegment;
+import com.android.ddmlib.ClientData.HeapData;
+import com.android.ddmlib.HeapSegment.HeapSegmentElement;
+
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+
+/**
+ * Base Panel for heap panels.
+ */
+public abstract class BaseHeapPanel extends TablePanel {
+
+ /** store the processed heap segment, so that we don't recompute Image for nothing */
+ protected byte[] mProcessedHeapData;
+ private Map<Integer, ArrayList<HeapSegmentElement>> mHeapMap;
+
+ /**
+ * Serialize the heap data into an array. The resulting array is available through
+ * <code>getSerializedData()</code>.
+ * @param heapData The heap data to serialize
+ * @return true if the data changed.
+ */
+ protected boolean serializeHeapData(HeapData heapData) {
+ Collection<HeapSegment> heapSegments;
+
+ // Atomically get and clear the heap data.
+ synchronized (heapData) {
+ // get the segments
+ heapSegments = heapData.getHeapSegments();
+
+
+ if (heapSegments != null) {
+ // if they are not null, we never processed them.
+ // Before we process then, we drop them from the HeapData
+ heapData.clearHeapData();
+
+ // process them into a linear byte[]
+ doSerializeHeapData(heapSegments);
+ heapData.setProcessedHeapData(mProcessedHeapData);
+ heapData.setProcessedHeapMap(mHeapMap);
+
+ } else {
+ // the heap segments are null. Let see if the heapData contains a
+ // list that is already processed.
+
+ byte[] pixData = heapData.getProcessedHeapData();
+
+ // and compare it to the one we currently have in the panel.
+ if (pixData == mProcessedHeapData) {
+ // looks like its the same
+ return false;
+ } else {
+ mProcessedHeapData = pixData;
+ }
+
+ Map<Integer, ArrayList<HeapSegmentElement>> heapMap =
+ heapData.getProcessedHeapMap();
+ mHeapMap = heapMap;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the serialized heap data
+ */
+ protected byte[] getSerializedData() {
+ return mProcessedHeapData;
+ }
+
+ /**
+ * Processes and serialize the heapData.
+ * <p/>
+ * The resulting serialized array is {@link #mProcessedHeapData}.
+ * <p/>
+ * the resulting map is {@link #mHeapMap}.
+ * @param heapData the collection of {@link HeapSegment} that forms the heap data.
+ */
+ private void doSerializeHeapData(Collection<HeapSegment> heapData) {
+ mHeapMap = new TreeMap<Integer, ArrayList<HeapSegmentElement>>();
+
+ Iterator<HeapSegment> iterator;
+ ByteArrayOutputStream out;
+
+ out = new ByteArrayOutputStream(4 * 1024);
+
+ iterator = heapData.iterator();
+ while (iterator.hasNext()) {
+ HeapSegment hs = iterator.next();
+
+ HeapSegmentElement e = null;
+ while (true) {
+ int v;
+
+ e = hs.getNextElement(null);
+ if (e == null) {
+ break;
+ }
+
+ if (e.getSolidity() == HeapSegmentElement.SOLIDITY_FREE) {
+ v = 1;
+ } else {
+ v = e.getKind() + 2;
+ }
+
+ // put the element in the map
+ ArrayList<HeapSegmentElement> elementList = mHeapMap.get(v);
+ if (elementList == null) {
+ elementList = new ArrayList<HeapSegmentElement>();
+ mHeapMap.put(v, elementList);
+ }
+ elementList.add(e);
+
+
+ int len = e.getLength() / 8;
+ while (len > 0) {
+ out.write(v);
+ --len;
+ }
+ }
+ }
+ mProcessedHeapData = out.toByteArray();
+
+ // sort the segment element in the heap info.
+ Collection<ArrayList<HeapSegmentElement>> elementLists = mHeapMap.values();
+ for (ArrayList<HeapSegmentElement> elementList : elementLists) {
+ Collections.sort(elementList);
+ }
+ }
+
+ /**
+ * Creates a linear image of the heap data.
+ * @param pixData
+ * @param h
+ * @param palette
+ * @return
+ */
+ protected ImageData createLinearHeapImage(byte[] pixData, int h, PaletteData palette) {
+ int w = pixData.length / h;
+ if (pixData.length % h != 0) {
+ w++;
+ }
+
+ // Create the heap image.
+ ImageData id = new ImageData(w, h, 8, palette);
+
+ int x = 0;
+ int y = 0;
+ for (byte b : pixData) {
+ if (b >= 0) {
+ id.setPixel(x, y, b);
+ }
+
+ y++;
+ if (y >= h) {
+ y = 0;
+ x++;
+ }
+ }
+
+ return id;
+ }
+
+
+}