Home | History | Annotate | Download | only in os
      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.os;
     18 
     19 import com.android.internal.util.FastPrintWriter;
     20 import com.android.internal.util.TypedProperties;
     21 
     22 import android.util.Log;
     23 
     24 import java.io.FileDescriptor;
     25 import java.io.FileNotFoundException;
     26 import java.io.FileOutputStream;
     27 import java.io.FileReader;
     28 import java.io.IOException;
     29 import java.io.PrintWriter;
     30 import java.io.Reader;
     31 import java.lang.reflect.Field;
     32 import java.lang.reflect.Modifier;
     33 import java.lang.annotation.Target;
     34 import java.lang.annotation.ElementType;
     35 import java.lang.annotation.Retention;
     36 import java.lang.annotation.RetentionPolicy;
     37 
     38 import org.apache.harmony.dalvik.ddmc.Chunk;
     39 import org.apache.harmony.dalvik.ddmc.ChunkHandler;
     40 import org.apache.harmony.dalvik.ddmc.DdmServer;
     41 
     42 import dalvik.bytecode.OpcodeInfo;
     43 import dalvik.system.VMDebug;
     44 
     45 
     46 /**
     47  * Provides various debugging methods for Android applications, including
     48  * tracing and allocation counts.
     49  * <p><strong>Logging Trace Files</strong></p>
     50  * <p>Debug can create log files that give details about an application, such as
     51  * a call stack and start/stop times for any running methods. See <a
     52 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
     53  * information about reading trace files. To start logging trace files, call one
     54  * of the startMethodTracing() methods. To stop tracing, call
     55  * {@link #stopMethodTracing()}.
     56  */
     57 public final class Debug
     58 {
     59     private static final String TAG = "Debug";
     60 
     61     /**
     62      * Flags for startMethodTracing().  These can be ORed together.
     63      *
     64      * TRACE_COUNT_ALLOCS adds the results from startAllocCounting to the
     65      * trace key file.
     66      */
     67     public static final int TRACE_COUNT_ALLOCS  = VMDebug.TRACE_COUNT_ALLOCS;
     68 
     69     /**
     70      * Flags for printLoadedClasses().  Default behavior is to only show
     71      * the class name.
     72      */
     73     public static final int SHOW_FULL_DETAIL    = 1;
     74     public static final int SHOW_CLASSLOADER    = (1 << 1);
     75     public static final int SHOW_INITIALIZED    = (1 << 2);
     76 
     77     // set/cleared by waitForDebugger()
     78     private static volatile boolean mWaiting = false;
     79 
     80     private Debug() {}
     81 
     82     /*
     83      * How long to wait for the debugger to finish sending requests.  I've
     84      * seen this hit 800msec on the device while waiting for a response
     85      * to travel over USB and get processed, so we take that and add
     86      * half a second.
     87      */
     88     private static final int MIN_DEBUGGER_IDLE = 1300;      // msec
     89 
     90     /* how long to sleep when polling for activity */
     91     private static final int SPIN_DELAY = 200;              // msec
     92 
     93     /**
     94      * Default trace file path and file
     95      */
     96     private static final String DEFAULT_TRACE_PATH_PREFIX =
     97         Environment.getLegacyExternalStorageDirectory().getPath() + "/";
     98     private static final String DEFAULT_TRACE_BODY = "dmtrace";
     99     private static final String DEFAULT_TRACE_EXTENSION = ".trace";
    100     private static final String DEFAULT_TRACE_FILE_PATH =
    101         DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
    102         + DEFAULT_TRACE_EXTENSION;
    103 
    104 
    105     /**
    106      * This class is used to retrieved various statistics about the memory mappings for this
    107      * process. The returns info broken down by dalvik, native, and other. All results are in kB.
    108      */
    109     public static class MemoryInfo implements Parcelable {
    110         /** The proportional set size for dalvik heap.  (Doesn't include other Dalvik overhead.) */
    111         public int dalvikPss;
    112         /** The proportional set size that is swappable for dalvik heap. */
    113         /** @hide We may want to expose this, eventually. */
    114         public int dalvikSwappablePss;
    115         /** The private dirty pages used by dalvik heap. */
    116         public int dalvikPrivateDirty;
    117         /** The shared dirty pages used by dalvik heap. */
    118         public int dalvikSharedDirty;
    119         /** The private clean pages used by dalvik heap. */
    120         /** @hide We may want to expose this, eventually. */
    121         public int dalvikPrivateClean;
    122         /** The shared clean pages used by dalvik heap. */
    123         /** @hide We may want to expose this, eventually. */
    124         public int dalvikSharedClean;
    125         /** The dirty dalvik pages that have been swapped out. */
    126         /** @hide We may want to expose this, eventually. */
    127         public int dalvikSwappedOut;
    128 
    129         /** The proportional set size for the native heap. */
    130         public int nativePss;
    131         /** The proportional set size that is swappable for the native heap. */
    132         /** @hide We may want to expose this, eventually. */
    133         public int nativeSwappablePss;
    134         /** The private dirty pages used by the native heap. */
    135         public int nativePrivateDirty;
    136         /** The shared dirty pages used by the native heap. */
    137         public int nativeSharedDirty;
    138         /** The private clean pages used by the native heap. */
    139         /** @hide We may want to expose this, eventually. */
    140         public int nativePrivateClean;
    141         /** The shared clean pages used by the native heap. */
    142         /** @hide We may want to expose this, eventually. */
    143         public int nativeSharedClean;
    144         /** The dirty native pages that have been swapped out. */
    145         /** @hide We may want to expose this, eventually. */
    146         public int nativeSwappedOut;
    147 
    148         /** The proportional set size for everything else. */
    149         public int otherPss;
    150         /** The proportional set size that is swappable for everything else. */
    151         /** @hide We may want to expose this, eventually. */
    152         public int otherSwappablePss;
    153         /** The private dirty pages used by everything else. */
    154         public int otherPrivateDirty;
    155         /** The shared dirty pages used by everything else. */
    156         public int otherSharedDirty;
    157         /** The private clean pages used by everything else. */
    158         /** @hide We may want to expose this, eventually. */
    159         public int otherPrivateClean;
    160         /** The shared clean pages used by everything else. */
    161         /** @hide We may want to expose this, eventually. */
    162         public int otherSharedClean;
    163         /** The dirty pages used by anyting else that have been swapped out. */
    164         /** @hide We may want to expose this, eventually. */
    165         public int otherSwappedOut;
    166 
    167         /** @hide */
    168         public static final int NUM_OTHER_STATS = 16;
    169 
    170         /** @hide */
    171         public static final int NUM_DVK_STATS = 5;
    172 
    173         /** @hide */
    174         public static final int NUM_CATEGORIES = 7;
    175 
    176         /** @hide */
    177         public static final int offsetPss = 0;
    178         /** @hide */
    179         public static final int offsetSwappablePss = 1;
    180         /** @hide */
    181         public static final int offsetPrivateDirty = 2;
    182         /** @hide */
    183         public static final int offsetSharedDirty = 3;
    184         /** @hide */
    185         public static final int offsetPrivateClean = 4;
    186         /** @hide */
    187         public static final int offsetSharedClean = 5;
    188         /** @hide */
    189         public static final int offsetSwappedOut = 6;
    190 
    191         private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES];
    192 
    193         public MemoryInfo() {
    194         }
    195 
    196         /**
    197          * Return total PSS memory usage in kB.
    198          */
    199         public int getTotalPss() {
    200             return dalvikPss + nativePss + otherPss;
    201         }
    202 
    203         /**
    204          * @hide Return total PSS memory usage in kB.
    205          */
    206         public int getTotalUss() {
    207             return dalvikPrivateClean + dalvikPrivateDirty
    208                     + nativePrivateClean + nativePrivateDirty
    209                     + otherPrivateClean + otherPrivateDirty;
    210         }
    211 
    212         /**
    213          * Return total PSS memory usage in kB.
    214          */
    215         public int getTotalSwappablePss() {
    216             return dalvikSwappablePss + nativeSwappablePss + otherSwappablePss;
    217         }
    218 
    219         /**
    220          * Return total private dirty memory usage in kB.
    221          */
    222         public int getTotalPrivateDirty() {
    223             return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty;
    224         }
    225 
    226         /**
    227          * Return total shared dirty memory usage in kB.
    228          */
    229         public int getTotalSharedDirty() {
    230             return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty;
    231         }
    232 
    233         /**
    234          * Return total shared clean memory usage in kB.
    235          */
    236         public int getTotalPrivateClean() {
    237             return dalvikPrivateClean + nativePrivateClean + otherPrivateClean;
    238         }
    239 
    240         /**
    241          * Return total shared clean memory usage in kB.
    242          */
    243         public int getTotalSharedClean() {
    244             return dalvikSharedClean + nativeSharedClean + otherSharedClean;
    245         }
    246 
    247         /**
    248          * Return total swapped out memory in kB.
    249          * @hide
    250          */
    251         public int getTotalSwappedOut() {
    252             return dalvikSwappedOut + nativeSwappedOut + otherSwappedOut;
    253         }
    254 
    255         /** @hide */
    256         public int getOtherPss(int which) {
    257             return otherStats[which*NUM_CATEGORIES + offsetPss];
    258         }
    259 
    260 
    261         /** @hide */
    262         public int getOtherSwappablePss(int which) {
    263             return otherStats[which*NUM_CATEGORIES + offsetSwappablePss];
    264         }
    265 
    266 
    267         /** @hide */
    268         public int getOtherPrivateDirty(int which) {
    269             return otherStats[which*NUM_CATEGORIES + offsetPrivateDirty];
    270         }
    271 
    272         /** @hide */
    273         public int getOtherSharedDirty(int which) {
    274             return otherStats[which*NUM_CATEGORIES + offsetSharedDirty];
    275         }
    276 
    277         /** @hide */
    278         public int getOtherPrivateClean(int which) {
    279             return otherStats[which*NUM_CATEGORIES + offsetPrivateClean];
    280         }
    281 
    282         /** @hide */
    283         public int getOtherSharedClean(int which) {
    284             return otherStats[which*NUM_CATEGORIES + offsetSharedClean];
    285         }
    286 
    287         /** @hide */
    288         public int getOtherSwappedOut(int which) {
    289             return otherStats[which*NUM_CATEGORIES + offsetSwappedOut];
    290         }
    291 
    292         /** @hide */
    293         public static String getOtherLabel(int which) {
    294             switch (which) {
    295                 case 0: return "Dalvik Other";
    296                 case 1: return "Stack";
    297                 case 2: return "Cursor";
    298                 case 3: return "Ashmem";
    299                 case 4: return "Other dev";
    300                 case 5: return ".so mmap";
    301                 case 6: return ".jar mmap";
    302                 case 7: return ".apk mmap";
    303                 case 8: return ".ttf mmap";
    304                 case 9: return ".dex mmap";
    305                 case 10: return "code mmap";
    306                 case 11: return "image mmap";
    307                 case 12: return "Other mmap";
    308                 case 13: return "Graphics";
    309                 case 14: return "GL";
    310                 case 15: return "Memtrack";
    311                 case 16: return ".Heap";
    312                 case 17: return ".LOS";
    313                 case 18: return ".LinearAlloc";
    314                 case 19: return ".GC";
    315                 case 20: return ".JITCache";
    316                 default: return "????";
    317             }
    318         }
    319 
    320         public int describeContents() {
    321             return 0;
    322         }
    323 
    324         public void writeToParcel(Parcel dest, int flags) {
    325             dest.writeInt(dalvikPss);
    326             dest.writeInt(dalvikSwappablePss);
    327             dest.writeInt(dalvikPrivateDirty);
    328             dest.writeInt(dalvikSharedDirty);
    329             dest.writeInt(dalvikPrivateClean);
    330             dest.writeInt(dalvikSharedClean);
    331             dest.writeInt(dalvikSwappedOut);
    332             dest.writeInt(nativePss);
    333             dest.writeInt(nativeSwappablePss);
    334             dest.writeInt(nativePrivateDirty);
    335             dest.writeInt(nativeSharedDirty);
    336             dest.writeInt(nativePrivateClean);
    337             dest.writeInt(nativeSharedClean);
    338             dest.writeInt(nativeSwappedOut);
    339             dest.writeInt(otherPss);
    340             dest.writeInt(otherSwappablePss);
    341             dest.writeInt(otherPrivateDirty);
    342             dest.writeInt(otherSharedDirty);
    343             dest.writeInt(otherPrivateClean);
    344             dest.writeInt(otherSharedClean);
    345             dest.writeInt(otherSwappedOut);
    346             dest.writeIntArray(otherStats);
    347         }
    348 
    349         public void readFromParcel(Parcel source) {
    350             dalvikPss = source.readInt();
    351             dalvikSwappablePss = source.readInt();
    352             dalvikPrivateDirty = source.readInt();
    353             dalvikSharedDirty = source.readInt();
    354             dalvikPrivateClean = source.readInt();
    355             dalvikSharedClean = source.readInt();
    356             dalvikSwappedOut = source.readInt();
    357             nativePss = source.readInt();
    358             nativeSwappablePss = source.readInt();
    359             nativePrivateDirty = source.readInt();
    360             nativeSharedDirty = source.readInt();
    361             nativePrivateClean = source.readInt();
    362             nativeSharedClean = source.readInt();
    363             nativeSwappedOut = source.readInt();
    364             otherPss = source.readInt();
    365             otherSwappablePss = source.readInt();
    366             otherPrivateDirty = source.readInt();
    367             otherSharedDirty = source.readInt();
    368             otherPrivateClean = source.readInt();
    369             otherSharedClean = source.readInt();
    370             otherSwappedOut = source.readInt();
    371             otherStats = source.createIntArray();
    372         }
    373 
    374         public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
    375             public MemoryInfo createFromParcel(Parcel source) {
    376                 return new MemoryInfo(source);
    377             }
    378             public MemoryInfo[] newArray(int size) {
    379                 return new MemoryInfo[size];
    380             }
    381         };
    382 
    383         private MemoryInfo(Parcel source) {
    384             readFromParcel(source);
    385         }
    386     }
    387 
    388 
    389     /**
    390      * Wait until a debugger attaches.  As soon as the debugger attaches,
    391      * this returns, so you will need to place a breakpoint after the
    392      * waitForDebugger() call if you want to start tracing immediately.
    393      */
    394     public static void waitForDebugger() {
    395         if (!VMDebug.isDebuggingEnabled()) {
    396             //System.out.println("debugging not enabled, not waiting");
    397             return;
    398         }
    399         if (isDebuggerConnected())
    400             return;
    401 
    402         // if DDMS is listening, inform them of our plight
    403         System.out.println("Sending WAIT chunk");
    404         byte[] data = new byte[] { 0 };     // 0 == "waiting for debugger"
    405         Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1);
    406         DdmServer.sendChunk(waitChunk);
    407 
    408         mWaiting = true;
    409         while (!isDebuggerConnected()) {
    410             try { Thread.sleep(SPIN_DELAY); }
    411             catch (InterruptedException ie) {}
    412         }
    413         mWaiting = false;
    414 
    415         System.out.println("Debugger has connected");
    416 
    417         /*
    418          * There is no "ready to go" signal from the debugger, and we're
    419          * not allowed to suspend ourselves -- the debugger expects us to
    420          * be running happily, and gets confused if we aren't.  We need to
    421          * allow the debugger a chance to set breakpoints before we start
    422          * running again.
    423          *
    424          * Sit and spin until the debugger has been idle for a short while.
    425          */
    426         while (true) {
    427             long delta = VMDebug.lastDebuggerActivity();
    428             if (delta < 0) {
    429                 System.out.println("debugger detached?");
    430                 break;
    431             }
    432 
    433             if (delta < MIN_DEBUGGER_IDLE) {
    434                 System.out.println("waiting for debugger to settle...");
    435                 try { Thread.sleep(SPIN_DELAY); }
    436                 catch (InterruptedException ie) {}
    437             } else {
    438                 System.out.println("debugger has settled (" + delta + ")");
    439                 break;
    440             }
    441         }
    442     }
    443 
    444     /**
    445      * Returns "true" if one or more threads is waiting for a debugger
    446      * to attach.
    447      */
    448     public static boolean waitingForDebugger() {
    449         return mWaiting;
    450     }
    451 
    452     /**
    453      * Determine if a debugger is currently attached.
    454      */
    455     public static boolean isDebuggerConnected() {
    456         return VMDebug.isDebuggerConnected();
    457     }
    458 
    459     /**
    460      * Returns an array of strings that identify VM features.  This is
    461      * used by DDMS to determine what sorts of operations the VM can
    462      * perform.
    463      *
    464      * @hide
    465      */
    466     public static String[] getVmFeatureList() {
    467         return VMDebug.getVmFeatureList();
    468     }
    469 
    470     /**
    471      * Change the JDWP port.
    472      *
    473      * @deprecated no longer needed or useful
    474      */
    475     @Deprecated
    476     public static void changeDebugPort(int port) {}
    477 
    478     /**
    479      * This is the pathname to the sysfs file that enables and disables
    480      * tracing on the qemu emulator.
    481      */
    482     private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state";
    483 
    484     /**
    485      * Enable qemu tracing. For this to work requires running everything inside
    486      * the qemu emulator; otherwise, this method will have no effect. The trace
    487      * file is specified on the command line when the emulator is started. For
    488      * example, the following command line <br />
    489      * <code>emulator -trace foo</code><br />
    490      * will start running the emulator and create a trace file named "foo". This
    491      * method simply enables writing the trace records to the trace file.
    492      *
    493      * <p>
    494      * The main differences between this and {@link #startMethodTracing()} are
    495      * that tracing in the qemu emulator traces every cpu instruction of every
    496      * process, including kernel code, so we have more complete information,
    497      * including all context switches. We can also get more detailed information
    498      * such as cache misses. The sequence of calls is determined by
    499      * post-processing the instruction trace. The qemu tracing is also done
    500      * without modifying the application or perturbing the timing of calls
    501      * because no instrumentation is added to the application being traced.
    502      * </p>
    503      *
    504      * <p>
    505      * One limitation of using this method compared to using
    506      * {@link #startMethodTracing()} on the real device is that the emulator
    507      * does not model all of the real hardware effects such as memory and
    508      * bus contention.  The emulator also has a simple cache model and cannot
    509      * capture all the complexities of a real cache.
    510      * </p>
    511      */
    512     public static void startNativeTracing() {
    513         // Open the sysfs file for writing and write "1" to it.
    514         PrintWriter outStream = null;
    515         try {
    516             FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
    517             outStream = new FastPrintWriter(fos);
    518             outStream.println("1");
    519         } catch (Exception e) {
    520         } finally {
    521             if (outStream != null)
    522                 outStream.close();
    523         }
    524 
    525         VMDebug.startEmulatorTracing();
    526     }
    527 
    528     /**
    529      * Stop qemu tracing.  See {@link #startNativeTracing()} to start tracing.
    530      *
    531      * <p>Tracing can be started and stopped as many times as desired.  When
    532      * the qemu emulator itself is stopped then the buffered trace records
    533      * are flushed and written to the trace file.  In fact, it is not necessary
    534      * to call this method at all; simply killing qemu is sufficient.  But
    535      * starting and stopping a trace is useful for examining a specific
    536      * region of code.</p>
    537      */
    538     public static void stopNativeTracing() {
    539         VMDebug.stopEmulatorTracing();
    540 
    541         // Open the sysfs file for writing and write "0" to it.
    542         PrintWriter outStream = null;
    543         try {
    544             FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
    545             outStream = new FastPrintWriter(fos);
    546             outStream.println("0");
    547         } catch (Exception e) {
    548             // We could print an error message here but we probably want
    549             // to quietly ignore errors if we are not running in the emulator.
    550         } finally {
    551             if (outStream != null)
    552                 outStream.close();
    553         }
    554     }
    555 
    556     /**
    557      * Enable "emulator traces", in which information about the current
    558      * method is made available to the "emulator -trace" feature.  There
    559      * is no corresponding "disable" call -- this is intended for use by
    560      * the framework when tracing should be turned on and left that way, so
    561      * that traces captured with F9/F10 will include the necessary data.
    562      *
    563      * This puts the VM into "profile" mode, which has performance
    564      * consequences.
    565      *
    566      * To temporarily enable tracing, use {@link #startNativeTracing()}.
    567      */
    568     public static void enableEmulatorTraceOutput() {
    569         VMDebug.startEmulatorTracing();
    570     }
    571 
    572     /**
    573      * Start method tracing with default log name and buffer size. See <a
    574 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
    575      * information about reading these files. Call stopMethodTracing() to stop
    576      * tracing.
    577      */
    578     public static void startMethodTracing() {
    579         VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0, false, 0);
    580     }
    581 
    582     /**
    583      * Start method tracing, specifying the trace log file name.  The trace
    584      * file will be put under "/sdcard" unless an absolute path is given.
    585      * See <a
    586        href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
    587      * information about reading trace files.
    588      *
    589      * @param traceName Name for the trace log file to create.
    590      * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
    591      * If the files already exist, they will be truncated.
    592      * If the trace file given does not end in ".trace", it will be appended for you.
    593      */
    594     public static void startMethodTracing(String traceName) {
    595         startMethodTracing(traceName, 0, 0);
    596     }
    597 
    598     /**
    599      * Start method tracing, specifying the trace log file name and the
    600      * buffer size. The trace files will be put under "/sdcard" unless an
    601      * absolute path is given. See <a
    602        href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
    603      * information about reading trace files.
    604      * @param traceName    Name for the trace log file to create.
    605      * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
    606      * If the files already exist, they will be truncated.
    607      * If the trace file given does not end in ".trace", it will be appended for you.
    608      *
    609      * @param bufferSize    The maximum amount of trace data we gather. If not given, it defaults to 8MB.
    610      */
    611     public static void startMethodTracing(String traceName, int bufferSize) {
    612         startMethodTracing(traceName, bufferSize, 0);
    613     }
    614 
    615     /**
    616      * Start method tracing, specifying the trace log file name and the
    617      * buffer size. The trace files will be put under "/sdcard" unless an
    618      * absolute path is given. See <a
    619        href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
    620      * information about reading trace files.
    621      *
    622      * <p>
    623      * When method tracing is enabled, the VM will run more slowly than
    624      * usual, so the timings from the trace files should only be considered
    625      * in relative terms (e.g. was run #1 faster than run #2).  The times
    626      * for native methods will not change, so don't try to use this to
    627      * compare the performance of interpreted and native implementations of the
    628      * same method.  As an alternative, consider using sampling-based method
    629      * tracing via {@link #startMethodTracingSampling(String, int, int)} or
    630      * "native" tracing in the emulator via {@link #startNativeTracing()}.
    631      * </p>
    632      *
    633      * @param traceName    Name for the trace log file to create.
    634      * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
    635      * If the files already exist, they will be truncated.
    636      * If the trace file given does not end in ".trace", it will be appended for you.
    637      * @param bufferSize    The maximum amount of trace data we gather. If not given, it defaults to 8MB.
    638      * @param flags    Flags to control method tracing. The only one that is currently defined is {@link #TRACE_COUNT_ALLOCS}.
    639      */
    640     public static void startMethodTracing(String traceName, int bufferSize,
    641         int flags) {
    642         VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, flags, false, 0);
    643     }
    644 
    645     /**
    646      * Start sampling-based method tracing, specifying the trace log file name,
    647      * the buffer size, and the sampling interval. The trace files will be put
    648      * under "/sdcard" unless an absolute path is given. See <a
    649        href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a>
    650      * for information about reading trace files.
    651      *
    652      * @param traceName    Name for the trace log file to create.
    653      * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
    654      * If the files already exist, they will be truncated.
    655      * If the trace file given does not end in ".trace", it will be appended for you.
    656      * @param bufferSize    The maximum amount of trace data we gather. If not given, it defaults to 8MB.
    657      * @param intervalUs    The amount of time between each sample in microseconds.
    658      */
    659     public static void startMethodTracingSampling(String traceName,
    660         int bufferSize, int intervalUs) {
    661         VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, 0, true, intervalUs);
    662     }
    663 
    664     /**
    665      * Formats name of trace log file for method tracing.
    666      */
    667     private static String fixTraceName(String traceName) {
    668         if (traceName == null)
    669             traceName = DEFAULT_TRACE_FILE_PATH;
    670         if (traceName.charAt(0) != '/')
    671             traceName = DEFAULT_TRACE_PATH_PREFIX + traceName;
    672         if (!traceName.endsWith(DEFAULT_TRACE_EXTENSION))
    673             traceName = traceName + DEFAULT_TRACE_EXTENSION;
    674 
    675         return traceName;
    676     }
    677 
    678     /**
    679      * Like startMethodTracing(String, int, int), but taking an already-opened
    680      * FileDescriptor in which the trace is written.  The file name is also
    681      * supplied simply for logging.  Makes a dup of the file descriptor.
    682      *
    683      * Not exposed in the SDK unless we are really comfortable with supporting
    684      * this and find it would be useful.
    685      * @hide
    686      */
    687     public static void startMethodTracing(String traceName, FileDescriptor fd,
    688         int bufferSize, int flags) {
    689         VMDebug.startMethodTracing(traceName, fd, bufferSize, flags, false, 0);
    690     }
    691 
    692     /**
    693      * Starts method tracing without a backing file.  When stopMethodTracing
    694      * is called, the result is sent directly to DDMS.  (If DDMS is not
    695      * attached when tracing ends, the profiling data will be discarded.)
    696      *
    697      * @hide
    698      */
    699     public static void startMethodTracingDdms(int bufferSize, int flags,
    700         boolean samplingEnabled, int intervalUs) {
    701         VMDebug.startMethodTracingDdms(bufferSize, flags, samplingEnabled, intervalUs);
    702     }
    703 
    704     /**
    705      * Determine whether method tracing is currently active and what type is
    706      * active.
    707      *
    708      * @hide
    709      */
    710     public static int getMethodTracingMode() {
    711         return VMDebug.getMethodTracingMode();
    712     }
    713 
    714     /**
    715      * Stop method tracing.
    716      */
    717     public static void stopMethodTracing() {
    718         VMDebug.stopMethodTracing();
    719     }
    720 
    721     /**
    722      * Get an indication of thread CPU usage.  The value returned
    723      * indicates the amount of time that the current thread has spent
    724      * executing code or waiting for certain types of I/O.
    725      *
    726      * The time is expressed in nanoseconds, and is only meaningful
    727      * when compared to the result from an earlier call.  Note that
    728      * nanosecond resolution does not imply nanosecond accuracy.
    729      *
    730      * On system which don't support this operation, the call returns -1.
    731      */
    732     public static long threadCpuTimeNanos() {
    733         return VMDebug.threadCpuTimeNanos();
    734     }
    735 
    736     /**
    737      * Start counting the number and aggregate size of memory allocations.
    738      *
    739      * <p>The {@link #startAllocCounting() start} method resets the counts and enables counting.
    740      * The {@link #stopAllocCounting() stop} method disables the counting so that the analysis
    741      * code doesn't cause additional allocations.  The various <code>get</code> methods return
    742      * the specified value. And the various <code>reset</code> methods reset the specified
    743      * count.</p>
    744      *
    745      * <p>Counts are kept for the system as a whole (global) and for each thread.
    746      * The per-thread counts for threads other than the current thread
    747      * are not cleared by the "reset" or "start" calls.</p>
    748      *
    749      * @deprecated Accurate counting is a burden on the runtime and may be removed.
    750      */
    751     @Deprecated
    752     public static void startAllocCounting() {
    753         VMDebug.startAllocCounting();
    754     }
    755 
    756     /**
    757      * Stop counting the number and aggregate size of memory allocations.
    758      *
    759      * @see #startAllocCounting()
    760      */
    761     @Deprecated
    762     public static void stopAllocCounting() {
    763         VMDebug.stopAllocCounting();
    764     }
    765 
    766     /**
    767      * Returns the global count of objects allocated by the runtime between a
    768      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
    769      */
    770     public static int getGlobalAllocCount() {
    771         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
    772     }
    773 
    774     /**
    775      * Clears the global count of objects allocated.
    776      * @see #getGlobalAllocCount()
    777      */
    778     public static void resetGlobalAllocCount() {
    779         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
    780     }
    781 
    782     /**
    783      * Returns the global size, in bytes, of objects allocated by the runtime between a
    784      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
    785      */
    786     public static int getGlobalAllocSize() {
    787         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
    788     }
    789 
    790     /**
    791      * Clears the global size of objects allocated.
    792      * @see #getGlobalAllocSize()
    793      */
    794     public static void resetGlobalAllocSize() {
    795         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
    796     }
    797 
    798     /**
    799      * Returns the global count of objects freed by the runtime between a
    800      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
    801      */
    802     public static int getGlobalFreedCount() {
    803         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
    804     }
    805 
    806     /**
    807      * Clears the global count of objects freed.
    808      * @see #getGlobalFreedCount()
    809      */
    810     public static void resetGlobalFreedCount() {
    811         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
    812     }
    813 
    814     /**
    815      * Returns the global size, in bytes, of objects freed by the runtime between a
    816      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
    817      */
    818     public static int getGlobalFreedSize() {
    819         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
    820     }
    821 
    822     /**
    823      * Clears the global size of objects freed.
    824      * @see #getGlobalFreedSize()
    825      */
    826     public static void resetGlobalFreedSize() {
    827         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
    828     }
    829 
    830     /**
    831      * Returns the number of non-concurrent GC invocations between a
    832      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
    833      */
    834     public static int getGlobalGcInvocationCount() {
    835         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
    836     }
    837 
    838     /**
    839      * Clears the count of non-concurrent GC invocations.
    840      * @see #getGlobalGcInvocationCount()
    841      */
    842     public static void resetGlobalGcInvocationCount() {
    843         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
    844     }
    845 
    846     /**
    847      * Returns the number of classes successfully initialized (ie those that executed without
    848      * throwing an exception) between a {@link #startAllocCounting() start} and
    849      * {@link #stopAllocCounting() stop}.
    850      */
    851     public static int getGlobalClassInitCount() {
    852         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
    853     }
    854 
    855     /**
    856      * Clears the count of classes initialized.
    857      * @see #getGlobalClassInitCount()
    858      */
    859     public static void resetGlobalClassInitCount() {
    860         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
    861     }
    862 
    863     /**
    864      * Returns the time spent successfully initializing classes between a
    865      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
    866      */
    867     public static int getGlobalClassInitTime() {
    868         /* cumulative elapsed time for class initialization, in usec */
    869         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
    870     }
    871 
    872     /**
    873      * Clears the count of time spent initializing classes.
    874      * @see #getGlobalClassInitTime()
    875      */
    876     public static void resetGlobalClassInitTime() {
    877         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
    878     }
    879 
    880     /**
    881      * This method exists for compatibility and always returns 0.
    882      * @deprecated This method is now obsolete.
    883      */
    884     @Deprecated
    885     public static int getGlobalExternalAllocCount() {
    886         return 0;
    887     }
    888 
    889     /**
    890      * This method exists for compatibility and has no effect.
    891      * @deprecated This method is now obsolete.
    892      */
    893     @Deprecated
    894     public static void resetGlobalExternalAllocSize() {}
    895 
    896     /**
    897      * This method exists for compatibility and has no effect.
    898      * @deprecated This method is now obsolete.
    899      */
    900     @Deprecated
    901     public static void resetGlobalExternalAllocCount() {}
    902 
    903     /**
    904      * This method exists for compatibility and always returns 0.
    905      * @deprecated This method is now obsolete.
    906      */
    907     @Deprecated
    908     public static int getGlobalExternalAllocSize() {
    909         return 0;
    910     }
    911 
    912     /**
    913      * This method exists for compatibility and always returns 0.
    914      * @deprecated This method is now obsolete.
    915      */
    916     @Deprecated
    917     public static int getGlobalExternalFreedCount() {
    918         return 0;
    919     }
    920 
    921     /**
    922      * This method exists for compatibility and has no effect.
    923      * @deprecated This method is now obsolete.
    924      */
    925     @Deprecated
    926     public static void resetGlobalExternalFreedCount() {}
    927 
    928     /**
    929      * This method exists for compatibility and has no effect.
    930      * @deprecated This method is now obsolete.
    931      */
    932     @Deprecated
    933     public static int getGlobalExternalFreedSize() {
    934         return 0;
    935     }
    936 
    937     /**
    938      * This method exists for compatibility and has no effect.
    939      * @deprecated This method is now obsolete.
    940      */
    941     @Deprecated
    942     public static void resetGlobalExternalFreedSize() {}
    943 
    944     /**
    945      * Returns the thread-local count of objects allocated by the runtime between a
    946      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
    947      */
    948     public static int getThreadAllocCount() {
    949         return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
    950     }
    951 
    952     /**
    953      * Clears the thread-local count of objects allocated.
    954      * @see #getThreadAllocCount()
    955      */
    956     public static void resetThreadAllocCount() {
    957         VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
    958     }
    959 
    960     /**
    961      * Returns the thread-local size of objects allocated by the runtime between a
    962      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
    963      * @return The allocated size in bytes.
    964      */
    965     public static int getThreadAllocSize() {
    966         return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
    967     }
    968 
    969     /**
    970      * Clears the thread-local count of objects allocated.
    971      * @see #getThreadAllocSize()
    972      */
    973     public static void resetThreadAllocSize() {
    974         VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
    975     }
    976 
    977     /**
    978      * This method exists for compatibility and has no effect.
    979      * @deprecated This method is now obsolete.
    980      */
    981     @Deprecated
    982     public static int getThreadExternalAllocCount() {
    983         return 0;
    984     }
    985 
    986     /**
    987      * This method exists for compatibility and has no effect.
    988      * @deprecated This method is now obsolete.
    989      */
    990     @Deprecated
    991     public static void resetThreadExternalAllocCount() {}
    992 
    993     /**
    994      * This method exists for compatibility and has no effect.
    995      * @deprecated This method is now obsolete.
    996      */
    997     @Deprecated
    998     public static int getThreadExternalAllocSize() {
    999         return 0;
   1000     }
   1001 
   1002     /**
   1003      * This method exists for compatibility and has no effect.
   1004      * @deprecated This method is now obsolete.
   1005      */
   1006     @Deprecated
   1007     public static void resetThreadExternalAllocSize() {}
   1008 
   1009     /**
   1010      * Returns the number of thread-local non-concurrent GC invocations between a
   1011      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
   1012      */
   1013     public static int getThreadGcInvocationCount() {
   1014         return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
   1015     }
   1016 
   1017     /**
   1018      * Clears the thread-local count of non-concurrent GC invocations.
   1019      * @see #getThreadGcInvocationCount()
   1020      */
   1021     public static void resetThreadGcInvocationCount() {
   1022         VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
   1023     }
   1024 
   1025     /**
   1026      * Clears all the global and thread-local memory allocation counters.
   1027      * @see #startAllocCounting()
   1028      */
   1029     public static void resetAllCounts() {
   1030         VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
   1031     }
   1032 
   1033     /**
   1034      * Returns the size of the native heap.
   1035      * @return The size of the native heap in bytes.
   1036      */
   1037     public static native long getNativeHeapSize();
   1038 
   1039     /**
   1040      * Returns the amount of allocated memory in the native heap.
   1041      * @return The allocated size in bytes.
   1042      */
   1043     public static native long getNativeHeapAllocatedSize();
   1044 
   1045     /**
   1046      * Returns the amount of free memory in the native heap.
   1047      * @return The freed size in bytes.
   1048      */
   1049     public static native long getNativeHeapFreeSize();
   1050 
   1051     /**
   1052      * Retrieves information about this processes memory usages. This information is broken down by
   1053      * how much is in use by dalivk, the native heap, and everything else.
   1054      */
   1055     public static native void getMemoryInfo(MemoryInfo memoryInfo);
   1056 
   1057     /**
   1058      * Note: currently only works when the requested pid has the same UID
   1059      * as the caller.
   1060      * @hide
   1061      */
   1062     public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
   1063 
   1064     /**
   1065      * Retrieves the PSS memory used by the process as given by the
   1066      * smaps.
   1067      */
   1068     public static native long getPss();
   1069 
   1070     /**
   1071      * Retrieves the PSS memory used by the process as given by the
   1072      * smaps.  Optionally supply a long array of 1 entry to also
   1073      * receive the uss of the process.  @hide
   1074      */
   1075     public static native long getPss(int pid, long[] outUss);
   1076 
   1077     /** @hide */
   1078     public static final int MEMINFO_TOTAL = 0;
   1079     /** @hide */
   1080     public static final int MEMINFO_FREE = 1;
   1081     /** @hide */
   1082     public static final int MEMINFO_BUFFERS = 2;
   1083     /** @hide */
   1084     public static final int MEMINFO_CACHED = 3;
   1085     /** @hide */
   1086     public static final int MEMINFO_SHMEM = 4;
   1087     /** @hide */
   1088     public static final int MEMINFO_SLAB = 5;
   1089     /** @hide */
   1090     public static final int MEMINFO_SWAP_TOTAL = 6;
   1091     /** @hide */
   1092     public static final int MEMINFO_SWAP_FREE = 7;
   1093     /** @hide */
   1094     public static final int MEMINFO_ZRAM_TOTAL = 8;
   1095     /** @hide */
   1096     public static final int MEMINFO_COUNT = 9;
   1097 
   1098     /**
   1099      * Retrieves /proc/meminfo.  outSizes is filled with fields
   1100      * as defined by MEMINFO_* offsets.
   1101      * @hide
   1102      */
   1103     public static native void getMemInfo(long[] outSizes);
   1104 
   1105     /**
   1106      * Establish an object allocation limit in the current thread.
   1107      * This feature was never enabled in release builds.  The
   1108      * allocation limits feature was removed in Honeycomb.  This
   1109      * method exists for compatibility and always returns -1 and has
   1110      * no effect.
   1111      *
   1112      * @deprecated This method is now obsolete.
   1113      */
   1114     @Deprecated
   1115     public static int setAllocationLimit(int limit) {
   1116         return -1;
   1117     }
   1118 
   1119     /**
   1120      * Establish a global object allocation limit.  This feature was
   1121      * never enabled in release builds.  The allocation limits feature
   1122      * was removed in Honeycomb.  This method exists for compatibility
   1123      * and always returns -1 and has no effect.
   1124      *
   1125      * @deprecated This method is now obsolete.
   1126      */
   1127     @Deprecated
   1128     public static int setGlobalAllocationLimit(int limit) {
   1129         return -1;
   1130     }
   1131 
   1132     /**
   1133      * Dump a list of all currently loaded class to the log file.
   1134      *
   1135      * @param flags See constants above.
   1136      */
   1137     public static void printLoadedClasses(int flags) {
   1138         VMDebug.printLoadedClasses(flags);
   1139     }
   1140 
   1141     /**
   1142      * Get the number of loaded classes.
   1143      * @return the number of loaded classes.
   1144      */
   1145     public static int getLoadedClassCount() {
   1146         return VMDebug.getLoadedClassCount();
   1147     }
   1148 
   1149     /**
   1150      * Dump "hprof" data to the specified file.  This may cause a GC.
   1151      *
   1152      * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof").
   1153      * @throws UnsupportedOperationException if the VM was built without
   1154      *         HPROF support.
   1155      * @throws IOException if an error occurs while opening or writing files.
   1156      */
   1157     public static void dumpHprofData(String fileName) throws IOException {
   1158         VMDebug.dumpHprofData(fileName);
   1159     }
   1160 
   1161     /**
   1162      * Like dumpHprofData(String), but takes an already-opened
   1163      * FileDescriptor to which the trace is written.  The file name is also
   1164      * supplied simply for logging.  Makes a dup of the file descriptor.
   1165      *
   1166      * Primarily for use by the "am" shell command.
   1167      *
   1168      * @hide
   1169      */
   1170     public static void dumpHprofData(String fileName, FileDescriptor fd)
   1171             throws IOException {
   1172         VMDebug.dumpHprofData(fileName, fd);
   1173     }
   1174 
   1175     /**
   1176      * Collect "hprof" and send it to DDMS.  This may cause a GC.
   1177      *
   1178      * @throws UnsupportedOperationException if the VM was built without
   1179      *         HPROF support.
   1180      * @hide
   1181      */
   1182     public static void dumpHprofDataDdms() {
   1183         VMDebug.dumpHprofDataDdms();
   1184     }
   1185 
   1186     /**
   1187      * Writes native heap data to the specified file descriptor.
   1188      *
   1189      * @hide
   1190      */
   1191     public static native void dumpNativeHeap(FileDescriptor fd);
   1192 
   1193     /**
   1194       * Returns a count of the extant instances of a class.
   1195      *
   1196      * @hide
   1197      */
   1198     public static long countInstancesOfClass(Class cls) {
   1199         return VMDebug.countInstancesOfClass(cls, true);
   1200     }
   1201 
   1202     /**
   1203      * Returns the number of sent transactions from this process.
   1204      * @return The number of sent transactions or -1 if it could not read t.
   1205      */
   1206     public static native int getBinderSentTransactions();
   1207 
   1208     /**
   1209      * Returns the number of received transactions from the binder driver.
   1210      * @return The number of received transactions or -1 if it could not read the stats.
   1211      */
   1212     public static native int getBinderReceivedTransactions();
   1213 
   1214     /**
   1215      * Returns the number of active local Binder objects that exist in the
   1216      * current process.
   1217      */
   1218     public static final native int getBinderLocalObjectCount();
   1219 
   1220     /**
   1221      * Returns the number of references to remote proxy Binder objects that
   1222      * exist in the current process.
   1223      */
   1224     public static final native int getBinderProxyObjectCount();
   1225 
   1226     /**
   1227      * Returns the number of death notification links to Binder objects that
   1228      * exist in the current process.
   1229      */
   1230     public static final native int getBinderDeathObjectCount();
   1231 
   1232     /**
   1233      * Primes the register map cache.
   1234      *
   1235      * Only works for classes in the bootstrap class loader.  Does not
   1236      * cause classes to be loaded if they're not already present.
   1237      *
   1238      * The classAndMethodDesc argument is a concatentation of the VM-internal
   1239      * class descriptor, method name, and method descriptor.  Examples:
   1240      *     Landroid/os/Looper;.loop:()V
   1241      *     Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V
   1242      *
   1243      * @param classAndMethodDesc the method to prepare
   1244      *
   1245      * @hide
   1246      */
   1247     public static final boolean cacheRegisterMap(String classAndMethodDesc) {
   1248         return VMDebug.cacheRegisterMap(classAndMethodDesc);
   1249     }
   1250 
   1251     /**
   1252      * Dumps the contents of VM reference tables (e.g. JNI locals and
   1253      * globals) to the log file.
   1254      *
   1255      * @hide
   1256      */
   1257     public static final void dumpReferenceTables() {
   1258         VMDebug.dumpReferenceTables();
   1259     }
   1260 
   1261     /**
   1262      * API for gathering and querying instruction counts.
   1263      *
   1264      * Example usage:
   1265      * <pre>
   1266      *   Debug.InstructionCount icount = new Debug.InstructionCount();
   1267      *   icount.resetAndStart();
   1268      *    [... do lots of stuff ...]
   1269      *   if (icount.collect()) {
   1270      *       System.out.println("Total instructions executed: "
   1271      *           + icount.globalTotal());
   1272      *       System.out.println("Method invocations: "
   1273      *           + icount.globalMethodInvocations());
   1274      *   }
   1275      * </pre>
   1276      */
   1277     public static class InstructionCount {
   1278         private static final int NUM_INSTR =
   1279             OpcodeInfo.MAXIMUM_PACKED_VALUE + 1;
   1280 
   1281         private int[] mCounts;
   1282 
   1283         public InstructionCount() {
   1284             mCounts = new int[NUM_INSTR];
   1285         }
   1286 
   1287         /**
   1288          * Reset counters and ensure counts are running.  Counts may
   1289          * have already been running.
   1290          *
   1291          * @return true if counting was started
   1292          */
   1293         public boolean resetAndStart() {
   1294             try {
   1295                 VMDebug.startInstructionCounting();
   1296                 VMDebug.resetInstructionCount();
   1297             } catch (UnsupportedOperationException uoe) {
   1298                 return false;
   1299             }
   1300             return true;
   1301         }
   1302 
   1303         /**
   1304          * Collect instruction counts.  May or may not stop the
   1305          * counting process.
   1306          */
   1307         public boolean collect() {
   1308             try {
   1309                 VMDebug.stopInstructionCounting();
   1310                 VMDebug.getInstructionCount(mCounts);
   1311             } catch (UnsupportedOperationException uoe) {
   1312                 return false;
   1313             }
   1314             return true;
   1315         }
   1316 
   1317         /**
   1318          * Return the total number of instructions executed globally (i.e. in
   1319          * all threads).
   1320          */
   1321         public int globalTotal() {
   1322             int count = 0;
   1323 
   1324             for (int i = 0; i < NUM_INSTR; i++) {
   1325                 count += mCounts[i];
   1326             }
   1327 
   1328             return count;
   1329         }
   1330 
   1331         /**
   1332          * Return the total number of method-invocation instructions
   1333          * executed globally.
   1334          */
   1335         public int globalMethodInvocations() {
   1336             int count = 0;
   1337 
   1338             for (int i = 0; i < NUM_INSTR; i++) {
   1339                 if (OpcodeInfo.isInvoke(i)) {
   1340                     count += mCounts[i];
   1341                 }
   1342             }
   1343 
   1344             return count;
   1345         }
   1346     }
   1347 
   1348     /**
   1349      * A Map of typed debug properties.
   1350      */
   1351     private static final TypedProperties debugProperties;
   1352 
   1353     /*
   1354      * Load the debug properties from the standard files into debugProperties.
   1355      */
   1356     static {
   1357         if (false) {
   1358             final String TAG = "DebugProperties";
   1359             final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" };
   1360             final TypedProperties tp = new TypedProperties();
   1361 
   1362             // Read the properties from each of the files, if present.
   1363             for (String file : files) {
   1364                 Reader r;
   1365                 try {
   1366                     r = new FileReader(file);
   1367                 } catch (FileNotFoundException ex) {
   1368                     // It's ok if a file is missing.
   1369                     continue;
   1370                 }
   1371 
   1372                 try {
   1373                     tp.load(r);
   1374                 } catch (Exception ex) {
   1375                     throw new RuntimeException("Problem loading " + file, ex);
   1376                 } finally {
   1377                     try {
   1378                         r.close();
   1379                     } catch (IOException ex) {
   1380                         // Ignore this error.
   1381                     }
   1382                 }
   1383             }
   1384 
   1385             debugProperties = tp.isEmpty() ? null : tp;
   1386         } else {
   1387             debugProperties = null;
   1388         }
   1389     }
   1390 
   1391 
   1392     /**
   1393      * Returns true if the type of the field matches the specified class.
   1394      * Handles the case where the class is, e.g., java.lang.Boolean, but
   1395      * the field is of the primitive "boolean" type.  Also handles all of
   1396      * the java.lang.Number subclasses.
   1397      */
   1398     private static boolean fieldTypeMatches(Field field, Class<?> cl) {
   1399         Class<?> fieldClass = field.getType();
   1400         if (fieldClass == cl) {
   1401             return true;
   1402         }
   1403         Field primitiveTypeField;
   1404         try {
   1405             /* All of the classes we care about (Boolean, Integer, etc.)
   1406              * have a Class field called "TYPE" that points to the corresponding
   1407              * primitive class.
   1408              */
   1409             primitiveTypeField = cl.getField("TYPE");
   1410         } catch (NoSuchFieldException ex) {
   1411             return false;
   1412         }
   1413         try {
   1414             return fieldClass == (Class<?>) primitiveTypeField.get(null);
   1415         } catch (IllegalAccessException ex) {
   1416             return false;
   1417         }
   1418     }
   1419 
   1420 
   1421     /**
   1422      * Looks up the property that corresponds to the field, and sets the field's value
   1423      * if the types match.
   1424      */
   1425     private static void modifyFieldIfSet(final Field field, final TypedProperties properties,
   1426                                          final String propertyName) {
   1427         if (field.getType() == java.lang.String.class) {
   1428             int stringInfo = properties.getStringInfo(propertyName);
   1429             switch (stringInfo) {
   1430                 case TypedProperties.STRING_SET:
   1431                     // Handle as usual below.
   1432                     break;
   1433                 case TypedProperties.STRING_NULL:
   1434                     try {
   1435                         field.set(null, null);  // null object for static fields; null string
   1436                     } catch (IllegalAccessException ex) {
   1437                         throw new IllegalArgumentException(
   1438                             "Cannot set field for " + propertyName, ex);
   1439                     }
   1440                     return;
   1441                 case TypedProperties.STRING_NOT_SET:
   1442                     return;
   1443                 case TypedProperties.STRING_TYPE_MISMATCH:
   1444                     throw new IllegalArgumentException(
   1445                         "Type of " + propertyName + " " +
   1446                         " does not match field type (" + field.getType() + ")");
   1447                 default:
   1448                     throw new IllegalStateException(
   1449                         "Unexpected getStringInfo(" + propertyName + ") return value " +
   1450                         stringInfo);
   1451             }
   1452         }
   1453         Object value = properties.get(propertyName);
   1454         if (value != null) {
   1455             if (!fieldTypeMatches(field, value.getClass())) {
   1456                 throw new IllegalArgumentException(
   1457                     "Type of " + propertyName + " (" + value.getClass() + ") " +
   1458                     " does not match field type (" + field.getType() + ")");
   1459             }
   1460             try {
   1461                 field.set(null, value);  // null object for static fields
   1462             } catch (IllegalAccessException ex) {
   1463                 throw new IllegalArgumentException(
   1464                     "Cannot set field for " + propertyName, ex);
   1465             }
   1466         }
   1467     }
   1468 
   1469 
   1470     /**
   1471      * Equivalent to <code>setFieldsOn(cl, false)</code>.
   1472      *
   1473      * @see #setFieldsOn(Class, boolean)
   1474      *
   1475      * @hide
   1476      */
   1477     public static void setFieldsOn(Class<?> cl) {
   1478         setFieldsOn(cl, false);
   1479     }
   1480 
   1481     /**
   1482      * Reflectively sets static fields of a class based on internal debugging
   1483      * properties.  This method is a no-op if false is
   1484      * false.
   1485      * <p>
   1486      * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: false will
   1487      * always be false in release builds.  This API is typically only useful
   1488      * for platform developers.
   1489      * </p>
   1490      * Class setup: define a class whose only fields are non-final, static
   1491      * primitive types (except for "char") or Strings.  In a static block
   1492      * after the field definitions/initializations, pass the class to
   1493      * this method, Debug.setFieldsOn(). Example:
   1494      * <pre>
   1495      * package com.example;
   1496      *
   1497      * import android.os.Debug;
   1498      *
   1499      * public class MyDebugVars {
   1500      *    public static String s = "a string";
   1501      *    public static String s2 = "second string";
   1502      *    public static String ns = null;
   1503      *    public static boolean b = false;
   1504      *    public static int i = 5;
   1505      *    @Debug.DebugProperty
   1506      *    public static float f = 0.1f;
   1507      *    @@Debug.DebugProperty
   1508      *    public static double d = 0.5d;
   1509      *
   1510      *    // This MUST appear AFTER all fields are defined and initialized!
   1511      *    static {
   1512      *        // Sets all the fields
   1513      *        Debug.setFieldsOn(MyDebugVars.class);
   1514      *
   1515      *        // Sets only the fields annotated with @Debug.DebugProperty
   1516      *        // Debug.setFieldsOn(MyDebugVars.class, true);
   1517      *    }
   1518      * }
   1519      * </pre>
   1520      * setFieldsOn() may override the value of any field in the class based
   1521      * on internal properties that are fixed at boot time.
   1522      * <p>
   1523      * These properties are only set during platform debugging, and are not
   1524      * meant to be used as a general-purpose properties store.
   1525      *
   1526      * {@hide}
   1527      *
   1528      * @param cl The class to (possibly) modify
   1529      * @param partial If false, sets all static fields, otherwise, only set
   1530      *        fields with the {@link android.os.Debug.DebugProperty}
   1531      *        annotation
   1532      * @throws IllegalArgumentException if any fields are final or non-static,
   1533      *         or if the type of the field does not match the type of
   1534      *         the internal debugging property value.
   1535      */
   1536     public static void setFieldsOn(Class<?> cl, boolean partial) {
   1537         if (false) {
   1538             if (debugProperties != null) {
   1539                 /* Only look for fields declared directly by the class,
   1540                  * so we don't mysteriously change static fields in superclasses.
   1541                  */
   1542                 for (Field field : cl.getDeclaredFields()) {
   1543                     if (!partial || field.getAnnotation(DebugProperty.class) != null) {
   1544                         final String propertyName = cl.getName() + "." + field.getName();
   1545                         boolean isStatic = Modifier.isStatic(field.getModifiers());
   1546                         boolean isFinal = Modifier.isFinal(field.getModifiers());
   1547 
   1548                         if (!isStatic || isFinal) {
   1549                             throw new IllegalArgumentException(propertyName +
   1550                                 " must be static and non-final");
   1551                         }
   1552                         modifyFieldIfSet(field, debugProperties, propertyName);
   1553                     }
   1554                 }
   1555             }
   1556         } else {
   1557             Log.wtf(TAG,
   1558                   "setFieldsOn(" + (cl == null ? "null" : cl.getName()) +
   1559                   ") called in non-DEBUG build");
   1560         }
   1561     }
   1562 
   1563     /**
   1564      * Annotation to put on fields you want to set with
   1565      * {@link Debug#setFieldsOn(Class, boolean)}.
   1566      *
   1567      * @hide
   1568      */
   1569     @Target({ ElementType.FIELD })
   1570     @Retention(RetentionPolicy.RUNTIME)
   1571     public @interface DebugProperty {
   1572     }
   1573 
   1574     /**
   1575      * Get a debugging dump of a system service by name.
   1576      *
   1577      * <p>Most services require the caller to hold android.permission.DUMP.
   1578      *
   1579      * @param name of the service to dump
   1580      * @param fd to write dump output to (usually an output log file)
   1581      * @param args to pass to the service's dump method, may be null
   1582      * @return true if the service was dumped successfully, false if
   1583      *     the service could not be found or had an error while dumping
   1584      */
   1585     public static boolean dumpService(String name, FileDescriptor fd, String[] args) {
   1586         IBinder service = ServiceManager.getService(name);
   1587         if (service == null) {
   1588             Log.e(TAG, "Can't find service to dump: " + name);
   1589             return false;
   1590         }
   1591 
   1592         try {
   1593             service.dump(fd, args);
   1594             return true;
   1595         } catch (RemoteException e) {
   1596             Log.e(TAG, "Can't dump service: " + name, e);
   1597             return false;
   1598         }
   1599     }
   1600 
   1601     /**
   1602      * Have the stack traces of the given native process dumped to the
   1603      * specified file.  Will be appended to the file.
   1604      * @hide
   1605      */
   1606     public static native void dumpNativeBacktraceToFile(int pid, String file);
   1607 
   1608     /**
   1609      * Return a String describing the calling method and location at a particular stack depth.
   1610      * @param callStack the Thread stack
   1611      * @param depth the depth of stack to return information for.
   1612      * @return the String describing the caller at that depth.
   1613      */
   1614     private static String getCaller(StackTraceElement callStack[], int depth) {
   1615         // callStack[4] is the caller of the method that called getCallers()
   1616         if (4 + depth >= callStack.length) {
   1617             return "<bottom of call stack>";
   1618         }
   1619         StackTraceElement caller = callStack[4 + depth];
   1620         return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber();
   1621     }
   1622 
   1623     /**
   1624      * Return a string consisting of methods and locations at multiple call stack levels.
   1625      * @param depth the number of levels to return, starting with the immediate caller.
   1626      * @return a string describing the call stack.
   1627      * {@hide}
   1628      */
   1629     public static String getCallers(final int depth) {
   1630         final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
   1631         StringBuffer sb = new StringBuffer();
   1632         for (int i = 0; i < depth; i++) {
   1633             sb.append(getCaller(callStack, i)).append(" ");
   1634         }
   1635         return sb.toString();
   1636     }
   1637 
   1638     /**
   1639      * Return a string consisting of methods and locations at multiple call stack levels.
   1640      * @param depth the number of levels to return, starting with the immediate caller.
   1641      * @return a string describing the call stack.
   1642      * {@hide}
   1643      */
   1644     public static String getCallers(final int start, int depth) {
   1645         final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
   1646         StringBuffer sb = new StringBuffer();
   1647         depth += start;
   1648         for (int i = start; i < depth; i++) {
   1649             sb.append(getCaller(callStack, i)).append(" ");
   1650         }
   1651         return sb.toString();
   1652     }
   1653 
   1654     /**
   1655      * Like {@link #getCallers(int)}, but each location is append to the string
   1656      * as a new line with <var>linePrefix</var> in front of it.
   1657      * @param depth the number of levels to return, starting with the immediate caller.
   1658      * @param linePrefix prefix to put in front of each location.
   1659      * @return a string describing the call stack.
   1660      * {@hide}
   1661      */
   1662     public static String getCallers(final int depth, String linePrefix) {
   1663         final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
   1664         StringBuffer sb = new StringBuffer();
   1665         for (int i = 0; i < depth; i++) {
   1666             sb.append(linePrefix).append(getCaller(callStack, i)).append("\n");
   1667         }
   1668         return sb.toString();
   1669     }
   1670 
   1671     /**
   1672      * @return a String describing the immediate caller of the calling method.
   1673      * {@hide}
   1674      */
   1675     public static String getCaller() {
   1676         return getCaller(Thread.currentThread().getStackTrace(), 0);
   1677     }
   1678 }
   1679