Home | History | Annotate | Download | only in ddm
      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 android.ddm;
     18 
     19 import org.apache.harmony.dalvik.ddmc.Chunk;
     20 import org.apache.harmony.dalvik.ddmc.ChunkHandler;
     21 import org.apache.harmony.dalvik.ddmc.DdmServer;
     22 import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
     23 import android.os.Debug;
     24 import android.util.Log;
     25 import java.io.IOException;
     26 import java.nio.ByteBuffer;
     27 
     28 /**
     29  * Handle native and virtual heap requests.
     30  */
     31 public class DdmHandleHeap extends ChunkHandler {
     32 
     33     public static final int CHUNK_HPIF = type("HPIF");
     34     public static final int CHUNK_HPSG = type("HPSG");
     35     public static final int CHUNK_HPDU = type("HPDU");
     36     public static final int CHUNK_HPDS = type("HPDS");
     37     public static final int CHUNK_NHSG = type("NHSG");
     38     public static final int CHUNK_HPGC = type("HPGC");
     39     public static final int CHUNK_REAE = type("REAE");
     40     public static final int CHUNK_REAQ = type("REAQ");
     41     public static final int CHUNK_REAL = type("REAL");
     42 
     43     private static DdmHandleHeap mInstance = new DdmHandleHeap();
     44 
     45 
     46     /* singleton, do not instantiate */
     47     private DdmHandleHeap() {}
     48 
     49     /**
     50      * Register for the messages we're interested in.
     51      */
     52     public static void register() {
     53         DdmServer.registerHandler(CHUNK_HPIF, mInstance);
     54         DdmServer.registerHandler(CHUNK_HPSG, mInstance);
     55         DdmServer.registerHandler(CHUNK_HPDU, mInstance);
     56         DdmServer.registerHandler(CHUNK_HPDS, mInstance);
     57         DdmServer.registerHandler(CHUNK_NHSG, mInstance);
     58         DdmServer.registerHandler(CHUNK_HPGC, mInstance);
     59         DdmServer.registerHandler(CHUNK_REAE, mInstance);
     60         DdmServer.registerHandler(CHUNK_REAQ, mInstance);
     61         DdmServer.registerHandler(CHUNK_REAL, mInstance);
     62     }
     63 
     64     /**
     65      * Called when the DDM server connects.  The handler is allowed to
     66      * send messages to the server.
     67      */
     68     public void connected() {}
     69 
     70     /**
     71      * Called when the DDM server disconnects.  Can be used to disable
     72      * periodic transmissions or clean up saved state.
     73      */
     74     public void disconnected() {}
     75 
     76     /**
     77      * Handle a chunk of data.
     78      */
     79     public Chunk handleChunk(Chunk request) {
     80         if (false)
     81             Log.v("ddm-heap", "Handling " + name(request.type) + " chunk");
     82         int type = request.type;
     83 
     84         if (type == CHUNK_HPIF) {
     85             return handleHPIF(request);
     86         } else if (type == CHUNK_HPSG) {
     87             return handleHPSGNHSG(request, false);
     88         } else if (type == CHUNK_HPDU) {
     89             return handleHPDU(request);
     90         } else if (type == CHUNK_HPDS) {
     91             return handleHPDS(request);
     92         } else if (type == CHUNK_NHSG) {
     93             return handleHPSGNHSG(request, true);
     94         } else if (type == CHUNK_HPGC) {
     95             return handleHPGC(request);
     96         } else if (type == CHUNK_REAE) {
     97             return handleREAE(request);
     98         } else if (type == CHUNK_REAQ) {
     99             return handleREAQ(request);
    100         } else if (type == CHUNK_REAL) {
    101             return handleREAL(request);
    102         } else {
    103             throw new RuntimeException("Unknown packet "
    104                 + ChunkHandler.name(type));
    105         }
    106     }
    107 
    108     /*
    109      * Handle a "HeaP InFo" request.
    110      */
    111     private Chunk handleHPIF(Chunk request) {
    112         ByteBuffer in = wrapChunk(request);
    113 
    114         int when = in.get();
    115         if (false)
    116             Log.v("ddm-heap", "Heap segment enable: when=" + when);
    117 
    118         boolean ok = DdmVmInternal.heapInfoNotify(when);
    119         if (!ok) {
    120             return createFailChunk(1, "Unsupported HPIF what");
    121         } else {
    122             return null;        // empty response
    123         }
    124     }
    125 
    126     /*
    127      * Handle a "HeaP SeGment" or "Native Heap SeGment" request.
    128      */
    129     private Chunk handleHPSGNHSG(Chunk request, boolean isNative) {
    130         ByteBuffer in = wrapChunk(request);
    131 
    132         int when = in.get();
    133         int what = in.get();
    134         if (false)
    135             Log.v("ddm-heap", "Heap segment enable: when=" + when
    136                 + ", what=" + what + ", isNative=" + isNative);
    137 
    138         boolean ok = DdmVmInternal.heapSegmentNotify(when, what, isNative);
    139         if (!ok) {
    140             return createFailChunk(1, "Unsupported HPSG what/when");
    141         } else {
    142             // TODO: if "when" is non-zero and we want to see a dump
    143             //       right away, initiate a GC.
    144             return null;        // empty response
    145         }
    146     }
    147 
    148     /*
    149      * Handle a "HeaP DUmp" request.
    150      *
    151      * This currently just returns a result code.  We could pull up
    152      * the entire contents of the file and return them, but hprof dump
    153      * files can be a few megabytes.
    154      */
    155     private Chunk handleHPDU(Chunk request) {
    156         ByteBuffer in = wrapChunk(request);
    157         byte result;
    158 
    159         /* get the filename for the output file */
    160         int len = in.getInt();
    161         String fileName = getString(in, len);
    162         if (false)
    163             Log.d("ddm-heap", "Heap dump: file='" + fileName + "'");
    164 
    165         try {
    166             Debug.dumpHprofData(fileName);
    167             result = 0;
    168         } catch (UnsupportedOperationException uoe) {
    169             Log.w("ddm-heap", "hprof dumps not supported in this VM");
    170             result = -1;
    171         } catch (IOException ioe) {
    172             result = -1;
    173         } catch (RuntimeException re) {
    174             result = -1;
    175         }
    176 
    177         /* create a non-empty reply so the handler fires on completion */
    178         byte[] reply = { result };
    179         return new Chunk(CHUNK_HPDU, reply, 0, reply.length);
    180     }
    181 
    182     /*
    183      * Handle a "HeaP Dump Streaming" request.
    184      *
    185      * This tells the VM to create a heap dump and send it directly to
    186      * DDMS.  The dumps are large enough that we don't want to copy the
    187      * data into a byte[] and send it from here.
    188      */
    189     private Chunk handleHPDS(Chunk request) {
    190         ByteBuffer in = wrapChunk(request);
    191         byte result;
    192 
    193         /* get the filename for the output file */
    194         if (false)
    195             Log.d("ddm-heap", "Heap dump: [DDMS]");
    196 
    197         String failMsg = null;
    198         try {
    199             Debug.dumpHprofDataDdms();
    200         } catch (UnsupportedOperationException uoe) {
    201             failMsg = "hprof dumps not supported in this VM";
    202         } catch (RuntimeException re) {
    203             failMsg = "Exception: " + re.getMessage();
    204         }
    205 
    206         if (failMsg != null) {
    207             Log.w("ddm-heap", failMsg);
    208             return createFailChunk(1, failMsg);
    209         } else {
    210             return null;
    211         }
    212     }
    213 
    214     /*
    215      * Handle a "HeaP Garbage Collection" request.
    216      */
    217     private Chunk handleHPGC(Chunk request) {
    218         //ByteBuffer in = wrapChunk(request);
    219 
    220         if (false)
    221             Log.d("ddm-heap", "Heap GC request");
    222         Runtime.getRuntime().gc();
    223 
    224         return null;        // empty response
    225     }
    226 
    227     /*
    228      * Handle a "REcent Allocation Enable" request.
    229      */
    230     private Chunk handleREAE(Chunk request) {
    231         ByteBuffer in = wrapChunk(request);
    232         boolean enable;
    233 
    234         enable = (in.get() != 0);
    235 
    236         if (false)
    237             Log.d("ddm-heap", "Recent allocation enable request: " + enable);
    238 
    239         DdmVmInternal.enableRecentAllocations(enable);
    240 
    241         return null;        // empty response
    242     }
    243 
    244     /*
    245      * Handle a "REcent Allocation Query" request.
    246      */
    247     private Chunk handleREAQ(Chunk request) {
    248         //ByteBuffer in = wrapChunk(request);
    249 
    250         byte[] reply = new byte[1];
    251         reply[0] = DdmVmInternal.getRecentAllocationStatus() ? (byte)1 :(byte)0;
    252         return new Chunk(CHUNK_REAQ, reply, 0, reply.length);
    253     }
    254 
    255     /*
    256      * Handle a "REcent ALlocations" request.
    257      */
    258     private Chunk handleREAL(Chunk request) {
    259         //ByteBuffer in = wrapChunk(request);
    260 
    261         if (false)
    262             Log.d("ddm-heap", "Recent allocations request");
    263 
    264         /* generate the reply in a ready-to-go format */
    265         byte[] reply = DdmVmInternal.getRecentAllocations();
    266         return new Chunk(CHUNK_REAL, reply, 0, reply.length);
    267     }
    268 }
    269 
    270