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