1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ddmuilib; 18 19 import com.android.ddmlib.HeapSegment; 20 import com.android.ddmlib.ClientData.HeapData; 21 import com.android.ddmlib.HeapSegment.HeapSegmentElement; 22 23 import org.eclipse.swt.graphics.ImageData; 24 import org.eclipse.swt.graphics.PaletteData; 25 26 import java.io.ByteArrayOutputStream; 27 import java.util.ArrayList; 28 import java.util.Collection; 29 import java.util.Collections; 30 import java.util.Iterator; 31 import java.util.Map; 32 import java.util.TreeMap; 33 34 35 /** 36 * Base Panel for heap panels. 37 */ 38 public abstract class BaseHeapPanel extends TablePanel { 39 40 /** store the processed heap segment, so that we don't recompute Image for nothing */ 41 protected byte[] mProcessedHeapData; 42 private Map<Integer, ArrayList<HeapSegmentElement>> mHeapMap; 43 44 /** 45 * Serialize the heap data into an array. The resulting array is available through 46 * <code>getSerializedData()</code>. 47 * @param heapData The heap data to serialize 48 * @return true if the data changed. 49 */ 50 protected boolean serializeHeapData(HeapData heapData) { 51 Collection<HeapSegment> heapSegments; 52 53 // Atomically get and clear the heap data. 54 synchronized (heapData) { 55 // get the segments 56 heapSegments = heapData.getHeapSegments(); 57 58 59 if (heapSegments != null) { 60 // if they are not null, we never processed them. 61 // Before we process then, we drop them from the HeapData 62 heapData.clearHeapData(); 63 64 // process them into a linear byte[] 65 doSerializeHeapData(heapSegments); 66 heapData.setProcessedHeapData(mProcessedHeapData); 67 heapData.setProcessedHeapMap(mHeapMap); 68 69 } else { 70 // the heap segments are null. Let see if the heapData contains a 71 // list that is already processed. 72 73 byte[] pixData = heapData.getProcessedHeapData(); 74 75 // and compare it to the one we currently have in the panel. 76 if (pixData == mProcessedHeapData) { 77 // looks like its the same 78 return false; 79 } else { 80 mProcessedHeapData = pixData; 81 } 82 83 Map<Integer, ArrayList<HeapSegmentElement>> heapMap = 84 heapData.getProcessedHeapMap(); 85 mHeapMap = heapMap; 86 } 87 } 88 89 return true; 90 } 91 92 /** 93 * Returns the serialized heap data 94 */ 95 protected byte[] getSerializedData() { 96 return mProcessedHeapData; 97 } 98 99 /** 100 * Processes and serialize the heapData. 101 * <p/> 102 * The resulting serialized array is {@link #mProcessedHeapData}. 103 * <p/> 104 * the resulting map is {@link #mHeapMap}. 105 * @param heapData the collection of {@link HeapSegment} that forms the heap data. 106 */ 107 private void doSerializeHeapData(Collection<HeapSegment> heapData) { 108 mHeapMap = new TreeMap<Integer, ArrayList<HeapSegmentElement>>(); 109 110 Iterator<HeapSegment> iterator; 111 ByteArrayOutputStream out; 112 113 out = new ByteArrayOutputStream(4 * 1024); 114 115 iterator = heapData.iterator(); 116 while (iterator.hasNext()) { 117 HeapSegment hs = iterator.next(); 118 119 HeapSegmentElement e = null; 120 while (true) { 121 int v; 122 123 e = hs.getNextElement(null); 124 if (e == null) { 125 break; 126 } 127 128 if (e.getSolidity() == HeapSegmentElement.SOLIDITY_FREE) { 129 v = 1; 130 } else { 131 v = e.getKind() + 2; 132 } 133 134 // put the element in the map 135 ArrayList<HeapSegmentElement> elementList = mHeapMap.get(v); 136 if (elementList == null) { 137 elementList = new ArrayList<HeapSegmentElement>(); 138 mHeapMap.put(v, elementList); 139 } 140 elementList.add(e); 141 142 143 int len = e.getLength() / 8; 144 while (len > 0) { 145 out.write(v); 146 --len; 147 } 148 } 149 } 150 mProcessedHeapData = out.toByteArray(); 151 152 // sort the segment element in the heap info. 153 Collection<ArrayList<HeapSegmentElement>> elementLists = mHeapMap.values(); 154 for (ArrayList<HeapSegmentElement> elementList : elementLists) { 155 Collections.sort(elementList); 156 } 157 } 158 159 /** 160 * Creates a linear image of the heap data. 161 * @param pixData 162 * @param h 163 * @param palette 164 * @return 165 */ 166 protected ImageData createLinearHeapImage(byte[] pixData, int h, PaletteData palette) { 167 int w = pixData.length / h; 168 if (pixData.length % h != 0) { 169 w++; 170 } 171 172 // Create the heap image. 173 ImageData id = new ImageData(w, h, 8, palette); 174 175 int x = 0; 176 int y = 0; 177 for (byte b : pixData) { 178 if (b >= 0) { 179 id.setPixel(x, y, b); 180 } 181 182 y++; 183 if (y >= h) { 184 y = 0; 185 x++; 186 } 187 } 188 189 return id; 190 } 191 192 193 } 194