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