Home | History | Annotate | Download | only in ddmuilib
      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