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 import java.util.HashMap;
38 import java.util.Map;
39 
40 import org.apache.harmony.dalvik.ddmc.Chunk;
41 import org.apache.harmony.dalvik.ddmc.ChunkHandler;
42 import org.apache.harmony.dalvik.ddmc.DdmServer;
43 
44 import dalvik.bytecode.OpcodeInfo;
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      * @deprecated Accurate counting is a burden on the runtime and may be removed.
70      */
71     @Deprecated
72     public static final int TRACE_COUNT_ALLOCS  = VMDebug.TRACE_COUNT_ALLOCS;
73 
74     /**
75      * Flags for printLoadedClasses().  Default behavior is to only show
76      * the class name.
77      */
78     public static final int SHOW_FULL_DETAIL    = 1;
79     public static final int SHOW_CLASSLOADER    = (1 << 1);
80     public static final int SHOW_INITIALIZED    = (1 << 2);
81 
82     // set/cleared by waitForDebugger()
83     private static volatile boolean mWaiting = false;
84 
Debug()85     private Debug() {}
86 
87     /*
88      * How long to wait for the debugger to finish sending requests.  I've
89      * seen this hit 800msec on the device while waiting for a response
90      * to travel over USB and get processed, so we take that and add
91      * half a second.
92      */
93     private static final int MIN_DEBUGGER_IDLE = 1300;      // msec
94 
95     /* how long to sleep when polling for activity */
96     private static final int SPIN_DELAY = 200;              // msec
97 
98     /**
99      * Default trace file path and file
100      */
101     private static final String DEFAULT_TRACE_PATH_PREFIX =
102         Environment.getLegacyExternalStorageDirectory().getPath() + "/";
103     private static final String DEFAULT_TRACE_BODY = "dmtrace";
104     private static final String DEFAULT_TRACE_EXTENSION = ".trace";
105     private static final String DEFAULT_TRACE_FILE_PATH =
106         DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
107         + DEFAULT_TRACE_EXTENSION;
108 
109 
110     /**
111      * This class is used to retrieved various statistics about the memory mappings for this
112      * process. The returned info is broken down by dalvik, native, and other. All results are in kB.
113      */
114     public static class MemoryInfo implements Parcelable {
115         /** The proportional set size for dalvik heap.  (Doesn't include other Dalvik overhead.) */
116         public int dalvikPss;
117         /** The proportional set size that is swappable for dalvik heap. */
118         /** @hide We may want to expose this, eventually. */
119         public int dalvikSwappablePss;
120         /** The private dirty pages used by dalvik heap. */
121         public int dalvikPrivateDirty;
122         /** The shared dirty pages used by dalvik heap. */
123         public int dalvikSharedDirty;
124         /** The private clean pages used by dalvik heap. */
125         /** @hide We may want to expose this, eventually. */
126         public int dalvikPrivateClean;
127         /** The shared clean pages used by dalvik heap. */
128         /** @hide We may want to expose this, eventually. */
129         public int dalvikSharedClean;
130         /** The dirty dalvik pages that have been swapped out. */
131         /** @hide We may want to expose this, eventually. */
132         public int dalvikSwappedOut;
133 
134         /** The proportional set size for the native heap. */
135         public int nativePss;
136         /** The proportional set size that is swappable for the native heap. */
137         /** @hide We may want to expose this, eventually. */
138         public int nativeSwappablePss;
139         /** The private dirty pages used by the native heap. */
140         public int nativePrivateDirty;
141         /** The shared dirty pages used by the native heap. */
142         public int nativeSharedDirty;
143         /** The private clean pages used by the native heap. */
144         /** @hide We may want to expose this, eventually. */
145         public int nativePrivateClean;
146         /** The shared clean pages used by the native heap. */
147         /** @hide We may want to expose this, eventually. */
148         public int nativeSharedClean;
149         /** The dirty native pages that have been swapped out. */
150         /** @hide We may want to expose this, eventually. */
151         public int nativeSwappedOut;
152 
153         /** The proportional set size for everything else. */
154         public int otherPss;
155         /** The proportional set size that is swappable for everything else. */
156         /** @hide We may want to expose this, eventually. */
157         public int otherSwappablePss;
158         /** The private dirty pages used by everything else. */
159         public int otherPrivateDirty;
160         /** The shared dirty pages used by everything else. */
161         public int otherSharedDirty;
162         /** The private clean pages used by everything else. */
163         /** @hide We may want to expose this, eventually. */
164         public int otherPrivateClean;
165         /** The shared clean pages used by everything else. */
166         /** @hide We may want to expose this, eventually. */
167         public int otherSharedClean;
168         /** The dirty pages used by anyting else that have been swapped out. */
169         /** @hide We may want to expose this, eventually. */
170         public int otherSwappedOut;
171 
172         /** @hide */
173         public static final int HEAP_UNKNOWN = 0;
174         /** @hide */
175         public static final int HEAP_DALVIK = 1;
176         /** @hide */
177         public static final int HEAP_NATIVE = 2;
178 
179         /** @hide */
180         public static final int OTHER_DALVIK_OTHER = 0;
181         /** @hide */
182         public static final int OTHER_STACK = 1;
183         /** @hide */
184         public static final int OTHER_CURSOR = 2;
185         /** @hide */
186         public static final int OTHER_ASHMEM = 3;
187         /** @hide */
188         public static final int OTHER_GL_DEV = 4;
189         /** @hide */
190         public static final int OTHER_UNKNOWN_DEV = 5;
191         /** @hide */
192         public static final int OTHER_SO = 6;
193         /** @hide */
194         public static final int OTHER_JAR = 7;
195         /** @hide */
196         public static final int OTHER_APK = 8;
197         /** @hide */
198         public static final int OTHER_TTF = 9;
199         /** @hide */
200         public static final int OTHER_DEX = 10;
201         /** @hide */
202         public static final int OTHER_OAT = 11;
203         /** @hide */
204         public static final int OTHER_ART = 12;
205         /** @hide */
206         public static final int OTHER_UNKNOWN_MAP = 13;
207         /** @hide */
208         public static final int OTHER_GRAPHICS = 14;
209         /** @hide */
210         public static final int OTHER_GL = 15;
211         /** @hide */
212         public static final int OTHER_OTHER_MEMTRACK = 16;
213 
214         /** @hide */
215         public static final int OTHER_DALVIK_NORMAL = 17;
216         /** @hide */
217         public static final int OTHER_DALVIK_LARGE = 18;
218         /** @hide */
219         public static final int OTHER_DALVIK_LINEARALLOC = 19;
220         /** @hide */
221         public static final int OTHER_DALVIK_ACCOUNTING = 20;
222         /** @hide */
223         public static final int OTHER_DALVIK_CODE_CACHE = 21;
224         /** @hide */
225         public static final int OTHER_DALVIK_ZYGOTE = 22;
226         /** @hide */
227         public static final int OTHER_DALVIK_NON_MOVING = 23;
228         /** @hide */
229         public static final int OTHER_DALVIK_INDIRECT_REFERENCE_TABLE = 24;
230 
231         /** @hide */
232         public static final int NUM_OTHER_STATS = 17;
233 
234         /** @hide */
235         public static final int NUM_DVK_STATS = 8;
236 
237         /** @hide */
238         public static final int NUM_CATEGORIES = 7;
239 
240         /** @hide */
241         public static final int offsetPss = 0;
242         /** @hide */
243         public static final int offsetSwappablePss = 1;
244         /** @hide */
245         public static final int offsetPrivateDirty = 2;
246         /** @hide */
247         public static final int offsetSharedDirty = 3;
248         /** @hide */
249         public static final int offsetPrivateClean = 4;
250         /** @hide */
251         public static final int offsetSharedClean = 5;
252         /** @hide */
253         public static final int offsetSwappedOut = 6;
254 
255         private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES];
256 
MemoryInfo()257         public MemoryInfo() {
258         }
259 
260         /**
261          * Return total PSS memory usage in kB.
262          */
getTotalPss()263         public int getTotalPss() {
264             return dalvikPss + nativePss + otherPss;
265         }
266 
267         /**
268          * @hide Return total PSS memory usage in kB.
269          */
getTotalUss()270         public int getTotalUss() {
271             return dalvikPrivateClean + dalvikPrivateDirty
272                     + nativePrivateClean + nativePrivateDirty
273                     + otherPrivateClean + otherPrivateDirty;
274         }
275 
276         /**
277          * Return total PSS memory usage in kB.
278          */
getTotalSwappablePss()279         public int getTotalSwappablePss() {
280             return dalvikSwappablePss + nativeSwappablePss + otherSwappablePss;
281         }
282 
283         /**
284          * Return total private dirty memory usage in kB.
285          */
getTotalPrivateDirty()286         public int getTotalPrivateDirty() {
287             return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty;
288         }
289 
290         /**
291          * Return total shared dirty memory usage in kB.
292          */
getTotalSharedDirty()293         public int getTotalSharedDirty() {
294             return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty;
295         }
296 
297         /**
298          * Return total shared clean memory usage in kB.
299          */
getTotalPrivateClean()300         public int getTotalPrivateClean() {
301             return dalvikPrivateClean + nativePrivateClean + otherPrivateClean;
302         }
303 
304         /**
305          * Return total shared clean memory usage in kB.
306          */
getTotalSharedClean()307         public int getTotalSharedClean() {
308             return dalvikSharedClean + nativeSharedClean + otherSharedClean;
309         }
310 
311         /**
312          * Return total swapped out memory in kB.
313          * @hide
314          */
getTotalSwappedOut()315         public int getTotalSwappedOut() {
316             return dalvikSwappedOut + nativeSwappedOut + otherSwappedOut;
317         }
318 
319         /** @hide */
getOtherPss(int which)320         public int getOtherPss(int which) {
321             return otherStats[which*NUM_CATEGORIES + offsetPss];
322         }
323 
324 
325         /** @hide */
getOtherSwappablePss(int which)326         public int getOtherSwappablePss(int which) {
327             return otherStats[which*NUM_CATEGORIES + offsetSwappablePss];
328         }
329 
330 
331         /** @hide */
getOtherPrivateDirty(int which)332         public int getOtherPrivateDirty(int which) {
333             return otherStats[which*NUM_CATEGORIES + offsetPrivateDirty];
334         }
335 
336         /** @hide */
getOtherSharedDirty(int which)337         public int getOtherSharedDirty(int which) {
338             return otherStats[which*NUM_CATEGORIES + offsetSharedDirty];
339         }
340 
341         /** @hide */
getOtherPrivateClean(int which)342         public int getOtherPrivateClean(int which) {
343             return otherStats[which*NUM_CATEGORIES + offsetPrivateClean];
344         }
345 
346         /** @hide */
getOtherPrivate(int which)347         public int getOtherPrivate(int which) {
348           return getOtherPrivateClean(which) + getOtherPrivateDirty(which);
349         }
350 
351         /** @hide */
getOtherSharedClean(int which)352         public int getOtherSharedClean(int which) {
353             return otherStats[which*NUM_CATEGORIES + offsetSharedClean];
354         }
355 
356         /** @hide */
getOtherSwappedOut(int which)357         public int getOtherSwappedOut(int which) {
358             return otherStats[which*NUM_CATEGORIES + offsetSwappedOut];
359         }
360 
361         /** @hide */
getOtherLabel(int which)362         public static String getOtherLabel(int which) {
363             switch (which) {
364                 case OTHER_DALVIK_OTHER: return "Dalvik Other";
365                 case OTHER_STACK: return "Stack";
366                 case OTHER_CURSOR: return "Cursor";
367                 case OTHER_ASHMEM: return "Ashmem";
368                 case OTHER_GL_DEV: return "Gfx dev";
369                 case OTHER_UNKNOWN_DEV: return "Other dev";
370                 case OTHER_SO: return ".so mmap";
371                 case OTHER_JAR: return ".jar mmap";
372                 case OTHER_APK: return ".apk mmap";
373                 case OTHER_TTF: return ".ttf mmap";
374                 case OTHER_DEX: return ".dex mmap";
375                 case OTHER_OAT: return ".oat mmap";
376                 case OTHER_ART: return ".art mmap";
377                 case OTHER_UNKNOWN_MAP: return "Other mmap";
378                 case OTHER_GRAPHICS: return "EGL mtrack";
379                 case OTHER_GL: return "GL mtrack";
380                 case OTHER_OTHER_MEMTRACK: return "Other mtrack";
381                 case OTHER_DALVIK_NORMAL: return ".Heap";
382                 case OTHER_DALVIK_LARGE: return ".LOS";
383                 case OTHER_DALVIK_LINEARALLOC: return ".LinearAlloc";
384                 case OTHER_DALVIK_ACCOUNTING: return ".GC";
385                 case OTHER_DALVIK_CODE_CACHE: return ".JITCache";
386                 case OTHER_DALVIK_ZYGOTE: return ".Zygote";
387                 case OTHER_DALVIK_NON_MOVING: return ".NonMoving";
388                 case OTHER_DALVIK_INDIRECT_REFERENCE_TABLE: return ".IndirectRef";
389                 default: return "????";
390             }
391         }
392 
393       /**
394        * Returns the value of a particular memory statistic or {@code null} if no
395        * such memory statistic exists.
396        *
397        * <p>The following table lists the memory statistics that are supported.
398        * Note that memory statistics may be added or removed in a future API level.</p>
399        *
400        * <table>
401        *     <thead>
402        *         <tr>
403        *             <th>Memory statistic name</th>
404        *             <th>Meaning</th>
405        *             <th>Example</th>
406        *             <th>Supported (API Levels)</th>
407        *         </tr>
408        *     </thead>
409        *     <tbody>
410        *         <tr>
411        *             <td>summary.java-heap</td>
412        *             <td>The private Java Heap usage in kB. This corresponds to the Java Heap field
413        *                 in the App Summary section output by dumpsys meminfo.</td>
414        *             <td>{@code 1442}</td>
415        *             <td>23</td>
416        *         </tr>
417        *         <tr>
418        *             <td>summary.native-heap</td>
419        *             <td>The private Native Heap usage in kB. This corresponds to the Native Heap
420        *                 field in the App Summary section output by dumpsys meminfo.</td>
421        *             <td>{@code 1442}</td>
422        *             <td>23</td>
423        *         </tr>
424        *         <tr>
425        *             <td>summary.code</td>
426        *             <td>The memory usage for static code and resources in kB. This corresponds to
427        *                 the Code field in the App Summary section output by dumpsys meminfo.</td>
428        *             <td>{@code 1442}</td>
429        *             <td>23</td>
430        *         </tr>
431        *         <tr>
432        *             <td>summary.stack</td>
433        *             <td>The stack usage in kB. This corresponds to the Stack field in the
434        *                 App Summary section output by dumpsys meminfo.</td>
435        *             <td>{@code 1442}</td>
436        *             <td>23</td>
437        *         </tr>
438        *         <tr>
439        *             <td>summary.graphics</td>
440        *             <td>The graphics usage in kB. This corresponds to the Graphics field in the
441        *                 App Summary section output by dumpsys meminfo.</td>
442        *             <td>{@code 1442}</td>
443        *             <td>23</td>
444        *         </tr>
445        *         <tr>
446        *             <td>summary.private-other</td>
447        *             <td>Other private memory usage in kB. This corresponds to the Private Other
448        *                 field output in the App Summary section by dumpsys meminfo.</td>
449        *             <td>{@code 1442}</td>
450        *             <td>23</td>
451        *         </tr>
452        *         <tr>
453        *             <td>summary.system</td>
454        *             <td>Shared and system memory usage in kB. This corresponds to the System
455        *                 field output in the App Summary section by dumpsys meminfo.</td>
456        *             <td>{@code 1442}</td>
457        *             <td>23</td>
458        *         </tr>
459        *         <tr>
460        *             <td>summary.total-pss</td>
461        *             <td>Total PPS memory usage in kB.</td>
462        *             <td>{@code 1442}</td>
463        *             <td>23</td>
464        *         </tr>
465        *         <tr>
466        *             <td>summary.total-swap</td>
467        *             <td>Total swap usage in kB.</td>
468        *             <td>{@code 1442}</td>
469        *             <td>23</td>
470        *         </tr>
471        *     </tbody>
472        * </table>
473        */
getMemoryStat(String statName)474         public String getMemoryStat(String statName) {
475             switch(statName) {
476                 case "summary.java-heap":
477                     return Integer.toString(getSummaryJavaHeap());
478                 case "summary.native-heap":
479                     return Integer.toString(getSummaryNativeHeap());
480                 case "summary.code":
481                     return Integer.toString(getSummaryCode());
482                 case "summary.stack":
483                     return Integer.toString(getSummaryStack());
484                 case "summary.graphics":
485                     return Integer.toString(getSummaryGraphics());
486                 case "summary.private-other":
487                     return Integer.toString(getSummaryPrivateOther());
488                 case "summary.system":
489                     return Integer.toString(getSummarySystem());
490                 case "summary.total-pss":
491                     return Integer.toString(getSummaryTotalPss());
492                 case "summary.total-swap":
493                     return Integer.toString(getSummaryTotalSwap());
494                 default:
495                     return null;
496             }
497         }
498 
499         /**
500          * Returns a map of the names/values of the memory statistics
501          * that {@link #getMemoryStat(String)} supports.
502          *
503          * @return a map of the names/values of the supported memory statistics.
504          */
getMemoryStats()505         public Map<String, String> getMemoryStats() {
506             Map<String, String> stats = new HashMap<String, String>();
507             stats.put("summary.java-heap", Integer.toString(getSummaryJavaHeap()));
508             stats.put("summary.native-heap", Integer.toString(getSummaryNativeHeap()));
509             stats.put("summary.code", Integer.toString(getSummaryCode()));
510             stats.put("summary.stack", Integer.toString(getSummaryStack()));
511             stats.put("summary.graphics", Integer.toString(getSummaryGraphics()));
512             stats.put("summary.private-other", Integer.toString(getSummaryPrivateOther()));
513             stats.put("summary.system", Integer.toString(getSummarySystem()));
514             stats.put("summary.total-pss", Integer.toString(getSummaryTotalPss()));
515             stats.put("summary.total-swap", Integer.toString(getSummaryTotalSwap()));
516             return stats;
517         }
518 
519         /**
520          * Pss of Java Heap bytes in KB due to the application.
521          * Notes:
522          *  * OTHER_ART is the boot image. Anything private here is blamed on
523          *    the application, not the system.
524          *  * dalvikPrivateDirty includes private zygote, which means the
525          *    application dirtied something allocated by the zygote. We blame
526          *    the application for that memory, not the system.
527          *  * Does not include OTHER_DALVIK_OTHER, which is considered VM
528          *    Overhead and lumped into Private Other.
529          *  * We don't include dalvikPrivateClean, because there should be no
530          *    such thing as private clean for the Java Heap.
531          * @hide
532          */
getSummaryJavaHeap()533         public int getSummaryJavaHeap() {
534             return dalvikPrivateDirty + getOtherPrivate(OTHER_ART);
535         }
536 
537         /**
538          * Pss of Native Heap bytes in KB due to the application.
539          * Notes:
540          *  * Includes private dirty malloc space.
541          *  * We don't include nativePrivateClean, because there should be no
542          *    such thing as private clean for the Native Heap.
543          * @hide
544          */
getSummaryNativeHeap()545         public int getSummaryNativeHeap() {
546             return nativePrivateDirty;
547         }
548 
549         /**
550          * Pss of code and other static resource bytes in KB due to
551          * the application.
552          * @hide
553          */
getSummaryCode()554         public int getSummaryCode() {
555             return getOtherPrivate(OTHER_SO)
556               + getOtherPrivate(OTHER_JAR)
557               + getOtherPrivate(OTHER_APK)
558               + getOtherPrivate(OTHER_TTF)
559               + getOtherPrivate(OTHER_DEX)
560               + getOtherPrivate(OTHER_OAT);
561         }
562 
563         /**
564          * Pss in KB of the stack due to the application.
565          * Notes:
566          *  * Includes private dirty stack, which includes both Java and Native
567          *    stack.
568          *  * Does not include private clean stack, because there should be no
569          *    such thing as private clean for the stack.
570          * @hide
571          */
getSummaryStack()572         public int getSummaryStack() {
573             return getOtherPrivateDirty(OTHER_STACK);
574         }
575 
576         /**
577          * Pss in KB of graphics due to the application.
578          * Notes:
579          *  * Includes private Gfx, EGL, and GL.
580          *  * Warning: These numbers can be misreported by the graphics drivers.
581          *  * We don't include shared graphics. It may make sense to, because
582          *    shared graphics are likely buffers due to the application
583          *    anyway, but it's simpler to implement to just group all shared
584          *    memory into the System category.
585          * @hide
586          */
getSummaryGraphics()587         public int getSummaryGraphics() {
588             return getOtherPrivate(OTHER_GL_DEV)
589               + getOtherPrivate(OTHER_GRAPHICS)
590               + getOtherPrivate(OTHER_GL);
591         }
592 
593         /**
594          * Pss in KB due to the application that haven't otherwise been
595          * accounted for.
596          * @hide
597          */
getSummaryPrivateOther()598         public int getSummaryPrivateOther() {
599             return getTotalPrivateClean()
600               + getTotalPrivateDirty()
601               - getSummaryJavaHeap()
602               - getSummaryNativeHeap()
603               - getSummaryCode()
604               - getSummaryStack()
605               - getSummaryGraphics();
606         }
607 
608         /**
609          * Pss in KB due to the system.
610          * Notes:
611          *  * Includes all shared memory.
612          * @hide
613          */
getSummarySystem()614         public int getSummarySystem() {
615             return getTotalPss()
616               - getTotalPrivateClean()
617               - getTotalPrivateDirty();
618         }
619 
620         /**
621          * Total Pss in KB.
622          * @hide
623          */
getSummaryTotalPss()624         public int getSummaryTotalPss() {
625             return getTotalPss();
626         }
627 
628         /**
629          * Total Swap in KB.
630          * Notes:
631          *  * Some of this memory belongs in other categories, but we don't
632          *    know if the Swap memory is shared or private, so we don't know
633          *    what to blame on the application and what on the system.
634          *    For now, just lump all the Swap in one place.
635          * @hide
636          */
getSummaryTotalSwap()637         public int getSummaryTotalSwap() {
638             return getTotalSwappedOut();
639         }
640 
describeContents()641         public int describeContents() {
642             return 0;
643         }
644 
writeToParcel(Parcel dest, int flags)645         public void writeToParcel(Parcel dest, int flags) {
646             dest.writeInt(dalvikPss);
647             dest.writeInt(dalvikSwappablePss);
648             dest.writeInt(dalvikPrivateDirty);
649             dest.writeInt(dalvikSharedDirty);
650             dest.writeInt(dalvikPrivateClean);
651             dest.writeInt(dalvikSharedClean);
652             dest.writeInt(dalvikSwappedOut);
653             dest.writeInt(nativePss);
654             dest.writeInt(nativeSwappablePss);
655             dest.writeInt(nativePrivateDirty);
656             dest.writeInt(nativeSharedDirty);
657             dest.writeInt(nativePrivateClean);
658             dest.writeInt(nativeSharedClean);
659             dest.writeInt(nativeSwappedOut);
660             dest.writeInt(otherPss);
661             dest.writeInt(otherSwappablePss);
662             dest.writeInt(otherPrivateDirty);
663             dest.writeInt(otherSharedDirty);
664             dest.writeInt(otherPrivateClean);
665             dest.writeInt(otherSharedClean);
666             dest.writeInt(otherSwappedOut);
667             dest.writeIntArray(otherStats);
668         }
669 
readFromParcel(Parcel source)670         public void readFromParcel(Parcel source) {
671             dalvikPss = source.readInt();
672             dalvikSwappablePss = source.readInt();
673             dalvikPrivateDirty = source.readInt();
674             dalvikSharedDirty = source.readInt();
675             dalvikPrivateClean = source.readInt();
676             dalvikSharedClean = source.readInt();
677             dalvikSwappedOut = source.readInt();
678             nativePss = source.readInt();
679             nativeSwappablePss = source.readInt();
680             nativePrivateDirty = source.readInt();
681             nativeSharedDirty = source.readInt();
682             nativePrivateClean = source.readInt();
683             nativeSharedClean = source.readInt();
684             nativeSwappedOut = source.readInt();
685             otherPss = source.readInt();
686             otherSwappablePss = source.readInt();
687             otherPrivateDirty = source.readInt();
688             otherSharedDirty = source.readInt();
689             otherPrivateClean = source.readInt();
690             otherSharedClean = source.readInt();
691             otherSwappedOut = source.readInt();
692             otherStats = source.createIntArray();
693         }
694 
695         public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
696             public MemoryInfo createFromParcel(Parcel source) {
697                 return new MemoryInfo(source);
698             }
699             public MemoryInfo[] newArray(int size) {
700                 return new MemoryInfo[size];
701             }
702         };
703 
MemoryInfo(Parcel source)704         private MemoryInfo(Parcel source) {
705             readFromParcel(source);
706         }
707     }
708 
709 
710     /**
711      * Wait until a debugger attaches.  As soon as the debugger attaches,
712      * this returns, so you will need to place a breakpoint after the
713      * waitForDebugger() call if you want to start tracing immediately.
714      */
waitForDebugger()715     public static void waitForDebugger() {
716         if (!VMDebug.isDebuggingEnabled()) {
717             //System.out.println("debugging not enabled, not waiting");
718             return;
719         }
720         if (isDebuggerConnected())
721             return;
722 
723         // if DDMS is listening, inform them of our plight
724         System.out.println("Sending WAIT chunk");
725         byte[] data = new byte[] { 0 };     // 0 == "waiting for debugger"
726         Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1);
727         DdmServer.sendChunk(waitChunk);
728 
729         mWaiting = true;
730         while (!isDebuggerConnected()) {
731             try { Thread.sleep(SPIN_DELAY); }
732             catch (InterruptedException ie) {}
733         }
734         mWaiting = false;
735 
736         System.out.println("Debugger has connected");
737 
738         /*
739          * There is no "ready to go" signal from the debugger, and we're
740          * not allowed to suspend ourselves -- the debugger expects us to
741          * be running happily, and gets confused if we aren't.  We need to
742          * allow the debugger a chance to set breakpoints before we start
743          * running again.
744          *
745          * Sit and spin until the debugger has been idle for a short while.
746          */
747         while (true) {
748             long delta = VMDebug.lastDebuggerActivity();
749             if (delta < 0) {
750                 System.out.println("debugger detached?");
751                 break;
752             }
753 
754             if (delta < MIN_DEBUGGER_IDLE) {
755                 System.out.println("waiting for debugger to settle...");
756                 try { Thread.sleep(SPIN_DELAY); }
757                 catch (InterruptedException ie) {}
758             } else {
759                 System.out.println("debugger has settled (" + delta + ")");
760                 break;
761             }
762         }
763     }
764 
765     /**
766      * Returns "true" if one or more threads is waiting for a debugger
767      * to attach.
768      */
waitingForDebugger()769     public static boolean waitingForDebugger() {
770         return mWaiting;
771     }
772 
773     /**
774      * Determine if a debugger is currently attached.
775      */
isDebuggerConnected()776     public static boolean isDebuggerConnected() {
777         return VMDebug.isDebuggerConnected();
778     }
779 
780     /**
781      * Returns an array of strings that identify VM features.  This is
782      * used by DDMS to determine what sorts of operations the VM can
783      * perform.
784      *
785      * @hide
786      */
getVmFeatureList()787     public static String[] getVmFeatureList() {
788         return VMDebug.getVmFeatureList();
789     }
790 
791     /**
792      * Change the JDWP port.
793      *
794      * @deprecated no longer needed or useful
795      */
796     @Deprecated
changeDebugPort(int port)797     public static void changeDebugPort(int port) {}
798 
799     /**
800      * This is the pathname to the sysfs file that enables and disables
801      * tracing on the qemu emulator.
802      */
803     private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state";
804 
805     /**
806      * Enable qemu tracing. For this to work requires running everything inside
807      * the qemu emulator; otherwise, this method will have no effect. The trace
808      * file is specified on the command line when the emulator is started. For
809      * example, the following command line <br />
810      * <code>emulator -trace foo</code><br />
811      * will start running the emulator and create a trace file named "foo". This
812      * method simply enables writing the trace records to the trace file.
813      *
814      * <p>
815      * The main differences between this and {@link #startMethodTracing()} are
816      * that tracing in the qemu emulator traces every cpu instruction of every
817      * process, including kernel code, so we have more complete information,
818      * including all context switches. We can also get more detailed information
819      * such as cache misses. The sequence of calls is determined by
820      * post-processing the instruction trace. The qemu tracing is also done
821      * without modifying the application or perturbing the timing of calls
822      * because no instrumentation is added to the application being traced.
823      * </p>
824      *
825      * <p>
826      * One limitation of using this method compared to using
827      * {@link #startMethodTracing()} on the real device is that the emulator
828      * does not model all of the real hardware effects such as memory and
829      * bus contention.  The emulator also has a simple cache model and cannot
830      * capture all the complexities of a real cache.
831      * </p>
832      */
startNativeTracing()833     public static void startNativeTracing() {
834         // Open the sysfs file for writing and write "1" to it.
835         PrintWriter outStream = null;
836         try {
837             FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
838             outStream = new FastPrintWriter(fos);
839             outStream.println("1");
840         } catch (Exception e) {
841         } finally {
842             if (outStream != null)
843                 outStream.close();
844         }
845 
846         VMDebug.startEmulatorTracing();
847     }
848 
849     /**
850      * Stop qemu tracing.  See {@link #startNativeTracing()} to start tracing.
851      *
852      * <p>Tracing can be started and stopped as many times as desired.  When
853      * the qemu emulator itself is stopped then the buffered trace records
854      * are flushed and written to the trace file.  In fact, it is not necessary
855      * to call this method at all; simply killing qemu is sufficient.  But
856      * starting and stopping a trace is useful for examining a specific
857      * region of code.</p>
858      */
stopNativeTracing()859     public static void stopNativeTracing() {
860         VMDebug.stopEmulatorTracing();
861 
862         // Open the sysfs file for writing and write "0" to it.
863         PrintWriter outStream = null;
864         try {
865             FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
866             outStream = new FastPrintWriter(fos);
867             outStream.println("0");
868         } catch (Exception e) {
869             // We could print an error message here but we probably want
870             // to quietly ignore errors if we are not running in the emulator.
871         } finally {
872             if (outStream != null)
873                 outStream.close();
874         }
875     }
876 
877     /**
878      * Enable "emulator traces", in which information about the current
879      * method is made available to the "emulator -trace" feature.  There
880      * is no corresponding "disable" call -- this is intended for use by
881      * the framework when tracing should be turned on and left that way, so
882      * that traces captured with F9/F10 will include the necessary data.
883      *
884      * This puts the VM into "profile" mode, which has performance
885      * consequences.
886      *
887      * To temporarily enable tracing, use {@link #startNativeTracing()}.
888      */
enableEmulatorTraceOutput()889     public static void enableEmulatorTraceOutput() {
890         VMDebug.startEmulatorTracing();
891     }
892 
893     /**
894      * Start method tracing with default log name and buffer size. See <a
895 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
896      * information about reading these files. Call stopMethodTracing() to stop
897      * tracing.
898      */
startMethodTracing()899     public static void startMethodTracing() {
900         VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0, false, 0);
901     }
902 
903     /**
904      * Start method tracing, specifying the trace log file name.  The trace
905      * file will be put under "/sdcard" unless an absolute path is given.
906      * See <a
907        href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
908      * information about reading trace files.
909      *
910      * @param traceName Name for the trace log file to create.
911      * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
912      * If the files already exist, they will be truncated.
913      * If the trace file given does not end in ".trace", it will be appended for you.
914      */
startMethodTracing(String traceName)915     public static void startMethodTracing(String traceName) {
916         startMethodTracing(traceName, 0, 0);
917     }
918 
919     /**
920      * Start method tracing, specifying the trace log file name and the
921      * buffer size. The trace files will be put under "/sdcard" unless an
922      * absolute path is given. See <a
923        href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
924      * information about reading trace files.
925      * @param traceName    Name for the trace log file to create.
926      * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
927      * If the files already exist, they will be truncated.
928      * If the trace file given does not end in ".trace", it will be appended for you.
929      *
930      * @param bufferSize    The maximum amount of trace data we gather. If not given, it defaults to 8MB.
931      */
startMethodTracing(String traceName, int bufferSize)932     public static void startMethodTracing(String traceName, int bufferSize) {
933         startMethodTracing(traceName, bufferSize, 0);
934     }
935 
936     /**
937      * Start method tracing, specifying the trace log file name and the
938      * buffer size. The trace files will be put under "/sdcard" unless an
939      * absolute path is given. See <a
940        href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
941      * information about reading trace files.
942      *
943      * <p>
944      * When method tracing is enabled, the VM will run more slowly than
945      * usual, so the timings from the trace files should only be considered
946      * in relative terms (e.g. was run #1 faster than run #2).  The times
947      * for native methods will not change, so don't try to use this to
948      * compare the performance of interpreted and native implementations of the
949      * same method.  As an alternative, consider using sampling-based method
950      * tracing via {@link #startMethodTracingSampling(String, int, int)} or
951      * "native" tracing in the emulator via {@link #startNativeTracing()}.
952      * </p>
953      *
954      * @param traceName    Name for the trace log file to create.
955      * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
956      * If the files already exist, they will be truncated.
957      * If the trace file given does not end in ".trace", it will be appended for you.
958      * @param bufferSize    The maximum amount of trace data we gather. If not given, it defaults to 8MB.
959      * @param flags    Flags to control method tracing. The only one that is currently defined is {@link #TRACE_COUNT_ALLOCS}.
960      */
startMethodTracing(String traceName, int bufferSize, int flags)961     public static void startMethodTracing(String traceName, int bufferSize,
962         int flags) {
963         VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, flags, false, 0);
964     }
965 
966     /**
967      * Start sampling-based method tracing, specifying the trace log file name,
968      * the buffer size, and the sampling interval. The trace files will be put
969      * under "/sdcard" unless an absolute path is given. See <a
970        href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a>
971      * for information about reading trace files.
972      *
973      * @param traceName    Name for the trace log file to create.
974      * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
975      * If the files already exist, they will be truncated.
976      * If the trace file given does not end in ".trace", it will be appended for you.
977      * @param bufferSize    The maximum amount of trace data we gather. If not given, it defaults to 8MB.
978      * @param intervalUs    The amount of time between each sample in microseconds.
979      */
startMethodTracingSampling(String traceName, int bufferSize, int intervalUs)980     public static void startMethodTracingSampling(String traceName,
981         int bufferSize, int intervalUs) {
982         VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, 0, true, intervalUs);
983     }
984 
985     /**
986      * Formats name of trace log file for method tracing.
987      */
fixTraceName(String traceName)988     private static String fixTraceName(String traceName) {
989         if (traceName == null)
990             traceName = DEFAULT_TRACE_FILE_PATH;
991         if (traceName.charAt(0) != '/')
992             traceName = DEFAULT_TRACE_PATH_PREFIX + traceName;
993         if (!traceName.endsWith(DEFAULT_TRACE_EXTENSION))
994             traceName = traceName + DEFAULT_TRACE_EXTENSION;
995 
996         return traceName;
997     }
998 
999     /**
1000      * Like startMethodTracing(String, int, int), but taking an already-opened
1001      * FileDescriptor in which the trace is written.  The file name is also
1002      * supplied simply for logging.  Makes a dup of the file descriptor.
1003      *
1004      * Not exposed in the SDK unless we are really comfortable with supporting
1005      * this and find it would be useful.
1006      * @hide
1007      */
startMethodTracing(String traceName, FileDescriptor fd, int bufferSize, int flags)1008     public static void startMethodTracing(String traceName, FileDescriptor fd,
1009         int bufferSize, int flags) {
1010         VMDebug.startMethodTracing(traceName, fd, bufferSize, flags, false, 0);
1011     }
1012 
1013     /**
1014      * Starts method tracing without a backing file.  When stopMethodTracing
1015      * is called, the result is sent directly to DDMS.  (If DDMS is not
1016      * attached when tracing ends, the profiling data will be discarded.)
1017      *
1018      * @hide
1019      */
startMethodTracingDdms(int bufferSize, int flags, boolean samplingEnabled, int intervalUs)1020     public static void startMethodTracingDdms(int bufferSize, int flags,
1021         boolean samplingEnabled, int intervalUs) {
1022         VMDebug.startMethodTracingDdms(bufferSize, flags, samplingEnabled, intervalUs);
1023     }
1024 
1025     /**
1026      * Determine whether method tracing is currently active and what type is
1027      * active.
1028      *
1029      * @hide
1030      */
getMethodTracingMode()1031     public static int getMethodTracingMode() {
1032         return VMDebug.getMethodTracingMode();
1033     }
1034 
1035     /**
1036      * Stop method tracing.
1037      */
stopMethodTracing()1038     public static void stopMethodTracing() {
1039         VMDebug.stopMethodTracing();
1040     }
1041 
1042     /**
1043      * Get an indication of thread CPU usage.  The value returned
1044      * indicates the amount of time that the current thread has spent
1045      * executing code or waiting for certain types of I/O.
1046      *
1047      * The time is expressed in nanoseconds, and is only meaningful
1048      * when compared to the result from an earlier call.  Note that
1049      * nanosecond resolution does not imply nanosecond accuracy.
1050      *
1051      * On system which don't support this operation, the call returns -1.
1052      */
threadCpuTimeNanos()1053     public static long threadCpuTimeNanos() {
1054         return VMDebug.threadCpuTimeNanos();
1055     }
1056 
1057     /**
1058      * Start counting the number and aggregate size of memory allocations.
1059      *
1060      * <p>The {@link #startAllocCounting() start} method resets the counts and enables counting.
1061      * The {@link #stopAllocCounting() stop} method disables the counting so that the analysis
1062      * code doesn't cause additional allocations.  The various <code>get</code> methods return
1063      * the specified value. And the various <code>reset</code> methods reset the specified
1064      * count.</p>
1065      *
1066      * <p>Counts are kept for the system as a whole (global) and for each thread.
1067      * The per-thread counts for threads other than the current thread
1068      * are not cleared by the "reset" or "start" calls.</p>
1069      *
1070      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1071      */
1072     @Deprecated
startAllocCounting()1073     public static void startAllocCounting() {
1074         VMDebug.startAllocCounting();
1075     }
1076 
1077     /**
1078      * Stop counting the number and aggregate size of memory allocations.
1079      *
1080      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1081      */
1082     @Deprecated
stopAllocCounting()1083     public static void stopAllocCounting() {
1084         VMDebug.stopAllocCounting();
1085     }
1086 
1087     /**
1088      * Returns the global count of objects allocated by the runtime between a
1089      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
1090      *
1091      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1092      */
1093     @Deprecated
getGlobalAllocCount()1094     public static int getGlobalAllocCount() {
1095         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
1096     }
1097 
1098     /**
1099      * Clears the global count of objects allocated.
1100      * @see #getGlobalAllocCount()
1101      *
1102      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1103      */
1104     @Deprecated
resetGlobalAllocCount()1105     public static void resetGlobalAllocCount() {
1106         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
1107     }
1108 
1109     /**
1110      * Returns the global size, in bytes, of objects allocated by the runtime between a
1111      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
1112      *
1113      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1114      */
1115     @Deprecated
getGlobalAllocSize()1116     public static int getGlobalAllocSize() {
1117         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
1118     }
1119 
1120     /**
1121      * Clears the global size of objects allocated.
1122      * @see #getGlobalAllocSize()
1123      *
1124      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1125      */
1126     @Deprecated
resetGlobalAllocSize()1127     public static void resetGlobalAllocSize() {
1128         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
1129     }
1130 
1131     /**
1132      * Returns the global count of objects freed by the runtime between a
1133      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
1134      *
1135      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1136      */
1137     @Deprecated
getGlobalFreedCount()1138     public static int getGlobalFreedCount() {
1139         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
1140     }
1141 
1142     /**
1143      * Clears the global count of objects freed.
1144      * @see #getGlobalFreedCount()
1145      *
1146      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1147      */
1148     @Deprecated
resetGlobalFreedCount()1149     public static void resetGlobalFreedCount() {
1150         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
1151     }
1152 
1153     /**
1154      * Returns the global size, in bytes, of objects freed by the runtime between a
1155      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
1156      *
1157      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1158      */
1159     @Deprecated
getGlobalFreedSize()1160     public static int getGlobalFreedSize() {
1161         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
1162     }
1163 
1164     /**
1165      * Clears the global size of objects freed.
1166      * @see #getGlobalFreedSize()
1167      *
1168      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1169      */
1170     @Deprecated
resetGlobalFreedSize()1171     public static void resetGlobalFreedSize() {
1172         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
1173     }
1174 
1175     /**
1176      * Returns the number of non-concurrent GC invocations between a
1177      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
1178      *
1179      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1180      */
1181     @Deprecated
getGlobalGcInvocationCount()1182     public static int getGlobalGcInvocationCount() {
1183         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
1184     }
1185 
1186     /**
1187      * Clears the count of non-concurrent GC invocations.
1188      * @see #getGlobalGcInvocationCount()
1189      *
1190      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1191      */
1192     @Deprecated
resetGlobalGcInvocationCount()1193     public static void resetGlobalGcInvocationCount() {
1194         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
1195     }
1196 
1197     /**
1198      * Returns the number of classes successfully initialized (ie those that executed without
1199      * throwing an exception) between a {@link #startAllocCounting() start} and
1200      * {@link #stopAllocCounting() stop}.
1201      *
1202      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1203      */
1204     @Deprecated
getGlobalClassInitCount()1205     public static int getGlobalClassInitCount() {
1206         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
1207     }
1208 
1209     /**
1210      * Clears the count of classes initialized.
1211      * @see #getGlobalClassInitCount()
1212      *
1213      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1214      */
1215     @Deprecated
resetGlobalClassInitCount()1216     public static void resetGlobalClassInitCount() {
1217         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
1218     }
1219 
1220     /**
1221      * Returns the time spent successfully initializing classes between a
1222      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
1223      *
1224      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1225      */
1226     @Deprecated
getGlobalClassInitTime()1227     public static int getGlobalClassInitTime() {
1228         /* cumulative elapsed time for class initialization, in usec */
1229         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
1230     }
1231 
1232     /**
1233      * Clears the count of time spent initializing classes.
1234      * @see #getGlobalClassInitTime()
1235      *
1236      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1237      */
1238     @Deprecated
resetGlobalClassInitTime()1239     public static void resetGlobalClassInitTime() {
1240         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
1241     }
1242 
1243     /**
1244      * This method exists for compatibility and always returns 0.
1245      * @deprecated This method is now obsolete.
1246      */
1247     @Deprecated
getGlobalExternalAllocCount()1248     public static int getGlobalExternalAllocCount() {
1249         return 0;
1250     }
1251 
1252     /**
1253      * This method exists for compatibility and has no effect.
1254      * @deprecated This method is now obsolete.
1255      */
1256     @Deprecated
resetGlobalExternalAllocSize()1257     public static void resetGlobalExternalAllocSize() {}
1258 
1259     /**
1260      * This method exists for compatibility and has no effect.
1261      * @deprecated This method is now obsolete.
1262      */
1263     @Deprecated
resetGlobalExternalAllocCount()1264     public static void resetGlobalExternalAllocCount() {}
1265 
1266     /**
1267      * This method exists for compatibility and always returns 0.
1268      * @deprecated This method is now obsolete.
1269      */
1270     @Deprecated
getGlobalExternalAllocSize()1271     public static int getGlobalExternalAllocSize() {
1272         return 0;
1273     }
1274 
1275     /**
1276      * This method exists for compatibility and always returns 0.
1277      * @deprecated This method is now obsolete.
1278      */
1279     @Deprecated
getGlobalExternalFreedCount()1280     public static int getGlobalExternalFreedCount() {
1281         return 0;
1282     }
1283 
1284     /**
1285      * This method exists for compatibility and has no effect.
1286      * @deprecated This method is now obsolete.
1287      */
1288     @Deprecated
resetGlobalExternalFreedCount()1289     public static void resetGlobalExternalFreedCount() {}
1290 
1291     /**
1292      * This method exists for compatibility and has no effect.
1293      * @deprecated This method is now obsolete.
1294      */
1295     @Deprecated
getGlobalExternalFreedSize()1296     public static int getGlobalExternalFreedSize() {
1297         return 0;
1298     }
1299 
1300     /**
1301      * This method exists for compatibility and has no effect.
1302      * @deprecated This method is now obsolete.
1303      */
1304     @Deprecated
resetGlobalExternalFreedSize()1305     public static void resetGlobalExternalFreedSize() {}
1306 
1307     /**
1308      * Returns the thread-local count of objects allocated by the runtime between a
1309      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
1310      *
1311      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1312      */
1313     @Deprecated
getThreadAllocCount()1314     public static int getThreadAllocCount() {
1315         return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
1316     }
1317 
1318     /**
1319      * Clears the thread-local count of objects allocated.
1320      * @see #getThreadAllocCount()
1321      *
1322      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1323      */
1324     @Deprecated
resetThreadAllocCount()1325     public static void resetThreadAllocCount() {
1326         VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
1327     }
1328 
1329     /**
1330      * Returns the thread-local size of objects allocated by the runtime between a
1331      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
1332      * @return The allocated size in bytes.
1333      *
1334      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1335      */
1336     @Deprecated
getThreadAllocSize()1337     public static int getThreadAllocSize() {
1338         return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
1339     }
1340 
1341     /**
1342      * Clears the thread-local count of objects allocated.
1343      * @see #getThreadAllocSize()
1344      *
1345      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1346      */
1347     @Deprecated
resetThreadAllocSize()1348     public static void resetThreadAllocSize() {
1349         VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
1350     }
1351 
1352     /**
1353      * This method exists for compatibility and has no effect.
1354      * @deprecated This method is now obsolete.
1355      */
1356     @Deprecated
getThreadExternalAllocCount()1357     public static int getThreadExternalAllocCount() {
1358         return 0;
1359     }
1360 
1361     /**
1362      * This method exists for compatibility and has no effect.
1363      * @deprecated This method is now obsolete.
1364      */
1365     @Deprecated
resetThreadExternalAllocCount()1366     public static void resetThreadExternalAllocCount() {}
1367 
1368     /**
1369      * This method exists for compatibility and has no effect.
1370      * @deprecated This method is now obsolete.
1371      */
1372     @Deprecated
getThreadExternalAllocSize()1373     public static int getThreadExternalAllocSize() {
1374         return 0;
1375     }
1376 
1377     /**
1378      * This method exists for compatibility and has no effect.
1379      * @deprecated This method is now obsolete.
1380      */
1381     @Deprecated
resetThreadExternalAllocSize()1382     public static void resetThreadExternalAllocSize() {}
1383 
1384     /**
1385      * Returns the number of thread-local non-concurrent GC invocations between a
1386      * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
1387      *
1388      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1389      */
1390     @Deprecated
getThreadGcInvocationCount()1391     public static int getThreadGcInvocationCount() {
1392         return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
1393     }
1394 
1395     /**
1396      * Clears the thread-local count of non-concurrent GC invocations.
1397      * @see #getThreadGcInvocationCount()
1398      *
1399      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1400      */
1401     @Deprecated
resetThreadGcInvocationCount()1402     public static void resetThreadGcInvocationCount() {
1403         VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
1404     }
1405 
1406     /**
1407      * Clears all the global and thread-local memory allocation counters.
1408      * @see #startAllocCounting()
1409      *
1410      * @deprecated Accurate counting is a burden on the runtime and may be removed.
1411      */
1412     @Deprecated
resetAllCounts()1413     public static void resetAllCounts() {
1414         VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
1415     }
1416 
1417     /**
1418      * Returns the value of a particular runtime statistic or {@code null} if no
1419      * such runtime statistic exists.
1420      *
1421      * <p>The following table lists the runtime statistics that the runtime supports.
1422      * Note runtime statistics may be added or removed in a future API level.</p>
1423      *
1424      * <table>
1425      *     <thead>
1426      *         <tr>
1427      *             <th>Runtime statistic name</th>
1428      *             <th>Meaning</th>
1429      *             <th>Example</th>
1430      *             <th>Supported (API Levels)</th>
1431      *         </tr>
1432      *     </thead>
1433      *     <tbody>
1434      *         <tr>
1435      *             <td>art.gc.gc-count</td>
1436      *             <td>The number of garbage collection runs.</td>
1437      *             <td>{@code 164}</td>
1438      *             <td>23</td>
1439      *         </tr>
1440      *         <tr>
1441      *             <td>art.gc.gc-time</td>
1442      *             <td>The total duration of garbage collection runs in ms.</td>
1443      *             <td>{@code 62364}</td>
1444      *             <td>23</td>
1445      *         </tr>
1446      *         <tr>
1447      *             <td>art.gc.bytes-allocated</td>
1448      *             <td>The total number of bytes that the application allocated.</td>
1449      *             <td>{@code 1463948408}</td>
1450      *             <td>23</td>
1451      *         </tr>
1452      *         <tr>
1453      *             <td>art.gc.bytes-freed</td>
1454      *             <td>The total number of bytes that garbage collection reclaimed.</td>
1455      *             <td>{@code 1313493084}</td>
1456      *             <td>23</td>
1457      *         </tr>
1458      *         <tr>
1459      *             <td>art.gc.blocking-gc-count</td>
1460      *             <td>The number of blocking garbage collection runs.</td>
1461      *             <td>{@code 2}</td>
1462      *             <td>23</td>
1463      *         </tr>
1464      *         <tr>
1465      *             <td>art.gc.blocking-gc-time</td>
1466      *             <td>The total duration of blocking garbage collection runs in ms.</td>
1467      *             <td>{@code 804}</td>
1468      *             <td>23</td>
1469      *         </tr>
1470      *         <tr>
1471      *             <td>art.gc.gc-count-rate-histogram</td>
1472      *             <td>Every 10 seconds, the gc-count-rate is computed as the number of garbage
1473      *                 collection runs that have occurred over the last 10
1474      *                 seconds. art.gc.gc-count-rate-histogram is a histogram of the gc-count-rate
1475      *                 samples taken since the process began. The histogram can be used to identify
1476      *                 instances of high rates of garbage collection runs. For example, a histogram
1477      *                 of "0:34503,1:45350,2:11281,3:8088,4:43,5:8" shows that most of the time
1478      *                 there are between 0 and 2 garbage collection runs every 10 seconds, but there
1479      *                 were 8 distinct 10-second intervals in which 5 garbage collection runs
1480      *                 occurred.</td>
1481      *             <td>{@code 0:34503,1:45350,2:11281,3:8088,4:43,5:8}</td>
1482      *             <td>23</td>
1483      *         </tr>
1484      *         <tr>
1485      *             <td>art.gc.blocking-gc-count-rate-histogram</td>
1486      *             <td>Every 10 seconds, the blocking-gc-count-rate is computed as the number of
1487      *                 blocking garbage collection runs that have occurred over the last 10
1488      *                 seconds. art.gc.blocking-gc-count-rate-histogram is a histogram of the
1489      *                 blocking-gc-count-rate samples taken since the process began. The histogram
1490      *                 can be used to identify instances of high rates of blocking garbage
1491      *                 collection runs. For example, a histogram of "0:99269,1:1,2:1" shows that
1492      *                 most of the time there are zero blocking garbage collection runs every 10
1493      *                 seconds, but there was one 10-second interval in which one blocking garbage
1494      *                 collection run occurred, and there was one interval in which two blocking
1495      *                 garbage collection runs occurred.</td>
1496      *             <td>{@code 0:99269,1:1,2:1}</td>
1497      *             <td>23</td>
1498      *         </tr>
1499      *     </tbody>
1500      * </table>
1501      *
1502      * @param statName
1503      *            the name of the runtime statistic to look up.
1504      * @return the value of the specified runtime statistic or {@code null} if the
1505      *         runtime statistic doesn't exist.
1506      */
getRuntimeStat(String statName)1507     public static String getRuntimeStat(String statName) {
1508         return VMDebug.getRuntimeStat(statName);
1509     }
1510 
1511     /**
1512      * Returns a map of the names/values of the runtime statistics
1513      * that {@link #getRuntimeStat(String)} supports.
1514      *
1515      * @return a map of the names/values of the supported runtime statistics.
1516      */
getRuntimeStats()1517     public static Map<String, String> getRuntimeStats() {
1518         return VMDebug.getRuntimeStats();
1519     }
1520 
1521     /**
1522      * Returns the size of the native heap.
1523      * @return The size of the native heap in bytes.
1524      */
getNativeHeapSize()1525     public static native long getNativeHeapSize();
1526 
1527     /**
1528      * Returns the amount of allocated memory in the native heap.
1529      * @return The allocated size in bytes.
1530      */
getNativeHeapAllocatedSize()1531     public static native long getNativeHeapAllocatedSize();
1532 
1533     /**
1534      * Returns the amount of free memory in the native heap.
1535      * @return The freed size in bytes.
1536      */
getNativeHeapFreeSize()1537     public static native long getNativeHeapFreeSize();
1538 
1539     /**
1540      * Retrieves information about this processes memory usages. This information is broken down by
1541      * how much is in use by dalivk, the native heap, and everything else.
1542      */
getMemoryInfo(MemoryInfo memoryInfo)1543     public static native void getMemoryInfo(MemoryInfo memoryInfo);
1544 
1545     /**
1546      * Note: currently only works when the requested pid has the same UID
1547      * as the caller.
1548      * @hide
1549      */
getMemoryInfo(int pid, MemoryInfo memoryInfo)1550     public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
1551 
1552     /**
1553      * Retrieves the PSS memory used by the process as given by the
1554      * smaps.
1555      */
getPss()1556     public static native long getPss();
1557 
1558     /**
1559      * Retrieves the PSS memory used by the process as given by the
1560      * smaps.  Optionally supply a long array of 1 entry to also
1561      * receive the uss of the process, and another array to also
1562      * retrieve the separate memtrack size.  @hide
1563      */
getPss(int pid, long[] outUss, long[] outMemtrack)1564     public static native long getPss(int pid, long[] outUss, long[] outMemtrack);
1565 
1566     /** @hide */
1567     public static final int MEMINFO_TOTAL = 0;
1568     /** @hide */
1569     public static final int MEMINFO_FREE = 1;
1570     /** @hide */
1571     public static final int MEMINFO_BUFFERS = 2;
1572     /** @hide */
1573     public static final int MEMINFO_CACHED = 3;
1574     /** @hide */
1575     public static final int MEMINFO_SHMEM = 4;
1576     /** @hide */
1577     public static final int MEMINFO_SLAB = 5;
1578     /** @hide */
1579     public static final int MEMINFO_SWAP_TOTAL = 6;
1580     /** @hide */
1581     public static final int MEMINFO_SWAP_FREE = 7;
1582     /** @hide */
1583     public static final int MEMINFO_ZRAM_TOTAL = 8;
1584     /** @hide */
1585     public static final int MEMINFO_MAPPED = 9;
1586     /** @hide */
1587     public static final int MEMINFO_VM_ALLOC_USED = 10;
1588     /** @hide */
1589     public static final int MEMINFO_PAGE_TABLES = 11;
1590     /** @hide */
1591     public static final int MEMINFO_KERNEL_STACK = 12;
1592     /** @hide */
1593     public static final int MEMINFO_COUNT = 13;
1594 
1595     /**
1596      * Retrieves /proc/meminfo.  outSizes is filled with fields
1597      * as defined by MEMINFO_* offsets.
1598      * @hide
1599      */
getMemInfo(long[] outSizes)1600     public static native void getMemInfo(long[] outSizes);
1601 
1602     /**
1603      * Establish an object allocation limit in the current thread.
1604      * This feature was never enabled in release builds.  The
1605      * allocation limits feature was removed in Honeycomb.  This
1606      * method exists for compatibility and always returns -1 and has
1607      * no effect.
1608      *
1609      * @deprecated This method is now obsolete.
1610      */
1611     @Deprecated
setAllocationLimit(int limit)1612     public static int setAllocationLimit(int limit) {
1613         return -1;
1614     }
1615 
1616     /**
1617      * Establish a global object allocation limit.  This feature was
1618      * never enabled in release builds.  The allocation limits feature
1619      * was removed in Honeycomb.  This method exists for compatibility
1620      * and always returns -1 and has no effect.
1621      *
1622      * @deprecated This method is now obsolete.
1623      */
1624     @Deprecated
setGlobalAllocationLimit(int limit)1625     public static int setGlobalAllocationLimit(int limit) {
1626         return -1;
1627     }
1628 
1629     /**
1630      * Dump a list of all currently loaded class to the log file.
1631      *
1632      * @param flags See constants above.
1633      */
printLoadedClasses(int flags)1634     public static void printLoadedClasses(int flags) {
1635         VMDebug.printLoadedClasses(flags);
1636     }
1637 
1638     /**
1639      * Get the number of loaded classes.
1640      * @return the number of loaded classes.
1641      */
getLoadedClassCount()1642     public static int getLoadedClassCount() {
1643         return VMDebug.getLoadedClassCount();
1644     }
1645 
1646     /**
1647      * Dump "hprof" data to the specified file.  This may cause a GC.
1648      *
1649      * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof").
1650      * @throws UnsupportedOperationException if the VM was built without
1651      *         HPROF support.
1652      * @throws IOException if an error occurs while opening or writing files.
1653      */
dumpHprofData(String fileName)1654     public static void dumpHprofData(String fileName) throws IOException {
1655         VMDebug.dumpHprofData(fileName);
1656     }
1657 
1658     /**
1659      * Like dumpHprofData(String), but takes an already-opened
1660      * FileDescriptor to which the trace is written.  The file name is also
1661      * supplied simply for logging.  Makes a dup of the file descriptor.
1662      *
1663      * Primarily for use by the "am" shell command.
1664      *
1665      * @hide
1666      */
dumpHprofData(String fileName, FileDescriptor fd)1667     public static void dumpHprofData(String fileName, FileDescriptor fd)
1668             throws IOException {
1669         VMDebug.dumpHprofData(fileName, fd);
1670     }
1671 
1672     /**
1673      * Collect "hprof" and send it to DDMS.  This may cause a GC.
1674      *
1675      * @throws UnsupportedOperationException if the VM was built without
1676      *         HPROF support.
1677      * @hide
1678      */
dumpHprofDataDdms()1679     public static void dumpHprofDataDdms() {
1680         VMDebug.dumpHprofDataDdms();
1681     }
1682 
1683     /**
1684      * Writes native heap data to the specified file descriptor.
1685      *
1686      * @hide
1687      */
dumpNativeHeap(FileDescriptor fd)1688     public static native void dumpNativeHeap(FileDescriptor fd);
1689 
1690     /**
1691       * Returns a count of the extant instances of a class.
1692      *
1693      * @hide
1694      */
countInstancesOfClass(Class cls)1695     public static long countInstancesOfClass(Class cls) {
1696         return VMDebug.countInstancesOfClass(cls, true);
1697     }
1698 
1699     /**
1700      * Returns the number of sent transactions from this process.
1701      * @return The number of sent transactions or -1 if it could not read t.
1702      */
getBinderSentTransactions()1703     public static native int getBinderSentTransactions();
1704 
1705     /**
1706      * Returns the number of received transactions from the binder driver.
1707      * @return The number of received transactions or -1 if it could not read the stats.
1708      */
getBinderReceivedTransactions()1709     public static native int getBinderReceivedTransactions();
1710 
1711     /**
1712      * Returns the number of active local Binder objects that exist in the
1713      * current process.
1714      */
getBinderLocalObjectCount()1715     public static final native int getBinderLocalObjectCount();
1716 
1717     /**
1718      * Returns the number of references to remote proxy Binder objects that
1719      * exist in the current process.
1720      */
getBinderProxyObjectCount()1721     public static final native int getBinderProxyObjectCount();
1722 
1723     /**
1724      * Returns the number of death notification links to Binder objects that
1725      * exist in the current process.
1726      */
getBinderDeathObjectCount()1727     public static final native int getBinderDeathObjectCount();
1728 
1729     /**
1730      * Primes the register map cache.
1731      *
1732      * Only works for classes in the bootstrap class loader.  Does not
1733      * cause classes to be loaded if they're not already present.
1734      *
1735      * The classAndMethodDesc argument is a concatentation of the VM-internal
1736      * class descriptor, method name, and method descriptor.  Examples:
1737      *     Landroid/os/Looper;.loop:()V
1738      *     Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V
1739      *
1740      * @param classAndMethodDesc the method to prepare
1741      *
1742      * @hide
1743      */
cacheRegisterMap(String classAndMethodDesc)1744     public static final boolean cacheRegisterMap(String classAndMethodDesc) {
1745         return VMDebug.cacheRegisterMap(classAndMethodDesc);
1746     }
1747 
1748     /**
1749      * Dumps the contents of VM reference tables (e.g. JNI locals and
1750      * globals) to the log file.
1751      *
1752      * @hide
1753      */
dumpReferenceTables()1754     public static final void dumpReferenceTables() {
1755         VMDebug.dumpReferenceTables();
1756     }
1757 
1758     /**
1759      * API for gathering and querying instruction counts.
1760      *
1761      * Example usage:
1762      * <pre>
1763      *   Debug.InstructionCount icount = new Debug.InstructionCount();
1764      *   icount.resetAndStart();
1765      *    [... do lots of stuff ...]
1766      *   if (icount.collect()) {
1767      *       System.out.println("Total instructions executed: "
1768      *           + icount.globalTotal());
1769      *       System.out.println("Method invocations: "
1770      *           + icount.globalMethodInvocations());
1771      *   }
1772      * </pre>
1773      *
1774      * @deprecated Instruction counting is no longer supported.
1775      */
1776     @Deprecated
1777     public static class InstructionCount {
1778         private static final int NUM_INSTR =
1779             OpcodeInfo.MAXIMUM_PACKED_VALUE + 1;
1780 
1781         private int[] mCounts;
1782 
InstructionCount()1783         public InstructionCount() {
1784             mCounts = new int[NUM_INSTR];
1785         }
1786 
1787         /**
1788          * Reset counters and ensure counts are running.  Counts may
1789          * have already been running.
1790          *
1791          * @return true if counting was started
1792          */
resetAndStart()1793         public boolean resetAndStart() {
1794             try {
1795                 VMDebug.startInstructionCounting();
1796                 VMDebug.resetInstructionCount();
1797             } catch (UnsupportedOperationException uoe) {
1798                 return false;
1799             }
1800             return true;
1801         }
1802 
1803         /**
1804          * Collect instruction counts.  May or may not stop the
1805          * counting process.
1806          */
collect()1807         public boolean collect() {
1808             try {
1809                 VMDebug.stopInstructionCounting();
1810                 VMDebug.getInstructionCount(mCounts);
1811             } catch (UnsupportedOperationException uoe) {
1812                 return false;
1813             }
1814             return true;
1815         }
1816 
1817         /**
1818          * Return the total number of instructions executed globally (i.e. in
1819          * all threads).
1820          */
globalTotal()1821         public int globalTotal() {
1822             int count = 0;
1823 
1824             for (int i = 0; i < NUM_INSTR; i++) {
1825                 count += mCounts[i];
1826             }
1827 
1828             return count;
1829         }
1830 
1831         /**
1832          * Return the total number of method-invocation instructions
1833          * executed globally.
1834          */
globalMethodInvocations()1835         public int globalMethodInvocations() {
1836             int count = 0;
1837 
1838             for (int i = 0; i < NUM_INSTR; i++) {
1839                 if (OpcodeInfo.isInvoke(i)) {
1840                     count += mCounts[i];
1841                 }
1842             }
1843 
1844             return count;
1845         }
1846     }
1847 
1848     /**
1849      * A Map of typed debug properties.
1850      */
1851     private static final TypedProperties debugProperties;
1852 
1853     /*
1854      * Load the debug properties from the standard files into debugProperties.
1855      */
1856     static {
1857         if (false) {
1858             final String TAG = "DebugProperties";
1859             final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" };
1860             final TypedProperties tp = new TypedProperties();
1861 
1862             // Read the properties from each of the files, if present.
1863             for (String file : files) {
1864                 Reader r;
1865                 try {
1866                     r = new FileReader(file);
1867                 } catch (FileNotFoundException ex) {
1868                     // It's ok if a file is missing.
1869                     continue;
1870                 }
1871 
1872                 try {
1873                     tp.load(r);
1874                 } catch (Exception ex) {
1875                     throw new RuntimeException("Problem loading " + file, ex);
1876                 } finally {
1877                     try {
r.close()1878                         r.close();
1879                     } catch (IOException ex) {
1880                         // Ignore this error.
1881                     }
1882                 }
1883             }
1884 
1885             debugProperties = tp.isEmpty() ? null : tp;
1886         } else {
1887             debugProperties = null;
1888         }
1889     }
1890 
1891 
1892     /**
1893      * Returns true if the type of the field matches the specified class.
1894      * Handles the case where the class is, e.g., java.lang.Boolean, but
1895      * the field is of the primitive "boolean" type.  Also handles all of
1896      * the java.lang.Number subclasses.
1897      */
fieldTypeMatches(Field field, Class<?> cl)1898     private static boolean fieldTypeMatches(Field field, Class<?> cl) {
1899         Class<?> fieldClass = field.getType();
1900         if (fieldClass == cl) {
1901             return true;
1902         }
1903         Field primitiveTypeField;
1904         try {
1905             /* All of the classes we care about (Boolean, Integer, etc.)
1906              * have a Class field called "TYPE" that points to the corresponding
1907              * primitive class.
1908              */
1909             primitiveTypeField = cl.getField("TYPE");
1910         } catch (NoSuchFieldException ex) {
1911             return false;
1912         }
1913         try {
1914             return fieldClass == (Class<?>) primitiveTypeField.get(null);
1915         } catch (IllegalAccessException ex) {
1916             return false;
1917         }
1918     }
1919 
1920 
1921     /**
1922      * Looks up the property that corresponds to the field, and sets the field's value
1923      * if the types match.
1924      */
modifyFieldIfSet(final Field field, final TypedProperties properties, final String propertyName)1925     private static void modifyFieldIfSet(final Field field, final TypedProperties properties,
1926                                          final String propertyName) {
1927         if (field.getType() == java.lang.String.class) {
1928             int stringInfo = properties.getStringInfo(propertyName);
1929             switch (stringInfo) {
1930                 case TypedProperties.STRING_SET:
1931                     // Handle as usual below.
1932                     break;
1933                 case TypedProperties.STRING_NULL:
1934                     try {
1935                         field.set(null, null);  // null object for static fields; null string
1936                     } catch (IllegalAccessException ex) {
1937                         throw new IllegalArgumentException(
1938                             "Cannot set field for " + propertyName, ex);
1939                     }
1940                     return;
1941                 case TypedProperties.STRING_NOT_SET:
1942                     return;
1943                 case TypedProperties.STRING_TYPE_MISMATCH:
1944                     throw new IllegalArgumentException(
1945                         "Type of " + propertyName + " " +
1946                         " does not match field type (" + field.getType() + ")");
1947                 default:
1948                     throw new IllegalStateException(
1949                         "Unexpected getStringInfo(" + propertyName + ") return value " +
1950                         stringInfo);
1951             }
1952         }
1953         Object value = properties.get(propertyName);
1954         if (value != null) {
1955             if (!fieldTypeMatches(field, value.getClass())) {
1956                 throw new IllegalArgumentException(
1957                     "Type of " + propertyName + " (" + value.getClass() + ") " +
1958                     " does not match field type (" + field.getType() + ")");
1959             }
1960             try {
1961                 field.set(null, value);  // null object for static fields
1962             } catch (IllegalAccessException ex) {
1963                 throw new IllegalArgumentException(
1964                     "Cannot set field for " + propertyName, ex);
1965             }
1966         }
1967     }
1968 
1969 
1970     /**
1971      * Equivalent to <code>setFieldsOn(cl, false)</code>.
1972      *
1973      * @see #setFieldsOn(Class, boolean)
1974      *
1975      * @hide
1976      */
setFieldsOn(Class<?> cl)1977     public static void setFieldsOn(Class<?> cl) {
1978         setFieldsOn(cl, false);
1979     }
1980 
1981     /**
1982      * Reflectively sets static fields of a class based on internal debugging
1983      * properties.  This method is a no-op if false is
1984      * false.
1985      * <p>
1986      * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: false will
1987      * always be false in release builds.  This API is typically only useful
1988      * for platform developers.
1989      * </p>
1990      * Class setup: define a class whose only fields are non-final, static
1991      * primitive types (except for "char") or Strings.  In a static block
1992      * after the field definitions/initializations, pass the class to
1993      * this method, Debug.setFieldsOn(). Example:
1994      * <pre>
1995      * package com.example;
1996      *
1997      * import android.os.Debug;
1998      *
1999      * public class MyDebugVars {
2000      *    public static String s = "a string";
2001      *    public static String s2 = "second string";
2002      *    public static String ns = null;
2003      *    public static boolean b = false;
2004      *    public static int i = 5;
2005      *    @Debug.DebugProperty
2006      *    public static float f = 0.1f;
2007      *    @@Debug.DebugProperty
2008      *    public static double d = 0.5d;
2009      *
2010      *    // This MUST appear AFTER all fields are defined and initialized!
2011      *    static {
2012      *        // Sets all the fields
2013      *        Debug.setFieldsOn(MyDebugVars.class);
2014      *
2015      *        // Sets only the fields annotated with @Debug.DebugProperty
2016      *        // Debug.setFieldsOn(MyDebugVars.class, true);
2017      *    }
2018      * }
2019      * </pre>
2020      * setFieldsOn() may override the value of any field in the class based
2021      * on internal properties that are fixed at boot time.
2022      * <p>
2023      * These properties are only set during platform debugging, and are not
2024      * meant to be used as a general-purpose properties store.
2025      *
2026      * {@hide}
2027      *
2028      * @param cl The class to (possibly) modify
2029      * @param partial If false, sets all static fields, otherwise, only set
2030      *        fields with the {@link android.os.Debug.DebugProperty}
2031      *        annotation
2032      * @throws IllegalArgumentException if any fields are final or non-static,
2033      *         or if the type of the field does not match the type of
2034      *         the internal debugging property value.
2035      */
setFieldsOn(Class<?> cl, boolean partial)2036     public static void setFieldsOn(Class<?> cl, boolean partial) {
2037         if (false) {
2038             if (debugProperties != null) {
2039                 /* Only look for fields declared directly by the class,
2040                  * so we don't mysteriously change static fields in superclasses.
2041                  */
2042                 for (Field field : cl.getDeclaredFields()) {
2043                     if (!partial || field.getAnnotation(DebugProperty.class) != null) {
2044                         final String propertyName = cl.getName() + "." + field.getName();
2045                         boolean isStatic = Modifier.isStatic(field.getModifiers());
2046                         boolean isFinal = Modifier.isFinal(field.getModifiers());
2047 
2048                         if (!isStatic || isFinal) {
2049                             throw new IllegalArgumentException(propertyName +
2050                                 " must be static and non-final");
2051                         }
2052                         modifyFieldIfSet(field, debugProperties, propertyName);
2053                     }
2054                 }
2055             }
2056         } else {
2057             Log.wtf(TAG,
2058                   "setFieldsOn(" + (cl == null ? "null" : cl.getName()) +
2059                   ") called in non-DEBUG build");
2060         }
2061     }
2062 
2063     /**
2064      * Annotation to put on fields you want to set with
2065      * {@link Debug#setFieldsOn(Class, boolean)}.
2066      *
2067      * @hide
2068      */
2069     @Target({ ElementType.FIELD })
2070     @Retention(RetentionPolicy.RUNTIME)
2071     public @interface DebugProperty {
2072     }
2073 
2074     /**
2075      * Get a debugging dump of a system service by name.
2076      *
2077      * <p>Most services require the caller to hold android.permission.DUMP.
2078      *
2079      * @param name of the service to dump
2080      * @param fd to write dump output to (usually an output log file)
2081      * @param args to pass to the service's dump method, may be null
2082      * @return true if the service was dumped successfully, false if
2083      *     the service could not be found or had an error while dumping
2084      */
dumpService(String name, FileDescriptor fd, String[] args)2085     public static boolean dumpService(String name, FileDescriptor fd, String[] args) {
2086         IBinder service = ServiceManager.getService(name);
2087         if (service == null) {
2088             Log.e(TAG, "Can't find service to dump: " + name);
2089             return false;
2090         }
2091 
2092         try {
2093             service.dump(fd, args);
2094             return true;
2095         } catch (RemoteException e) {
2096             Log.e(TAG, "Can't dump service: " + name, e);
2097             return false;
2098         }
2099     }
2100 
2101     /**
2102      * Have the stack traces of the given native process dumped to the
2103      * specified file.  Will be appended to the file.
2104      * @hide
2105      */
dumpNativeBacktraceToFile(int pid, String file)2106     public static native void dumpNativeBacktraceToFile(int pid, String file);
2107 
2108     /**
2109      * Return a String describing the calling method and location at a particular stack depth.
2110      * @param callStack the Thread stack
2111      * @param depth the depth of stack to return information for.
2112      * @return the String describing the caller at that depth.
2113      */
getCaller(StackTraceElement callStack[], int depth)2114     private static String getCaller(StackTraceElement callStack[], int depth) {
2115         // callStack[4] is the caller of the method that called getCallers()
2116         if (4 + depth >= callStack.length) {
2117             return "<bottom of call stack>";
2118         }
2119         StackTraceElement caller = callStack[4 + depth];
2120         return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber();
2121     }
2122 
2123     /**
2124      * Return a string consisting of methods and locations at multiple call stack levels.
2125      * @param depth the number of levels to return, starting with the immediate caller.
2126      * @return a string describing the call stack.
2127      * {@hide}
2128      */
getCallers(final int depth)2129     public static String getCallers(final int depth) {
2130         final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
2131         StringBuffer sb = new StringBuffer();
2132         for (int i = 0; i < depth; i++) {
2133             sb.append(getCaller(callStack, i)).append(" ");
2134         }
2135         return sb.toString();
2136     }
2137 
2138     /**
2139      * Return a string consisting of methods and locations at multiple call stack levels.
2140      * @param depth the number of levels to return, starting with the immediate caller.
2141      * @return a string describing the call stack.
2142      * {@hide}
2143      */
getCallers(final int start, int depth)2144     public static String getCallers(final int start, int depth) {
2145         final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
2146         StringBuffer sb = new StringBuffer();
2147         depth += start;
2148         for (int i = start; i < depth; i++) {
2149             sb.append(getCaller(callStack, i)).append(" ");
2150         }
2151         return sb.toString();
2152     }
2153 
2154     /**
2155      * Like {@link #getCallers(int)}, but each location is append to the string
2156      * as a new line with <var>linePrefix</var> in front of it.
2157      * @param depth the number of levels to return, starting with the immediate caller.
2158      * @param linePrefix prefix to put in front of each location.
2159      * @return a string describing the call stack.
2160      * {@hide}
2161      */
getCallers(final int depth, String linePrefix)2162     public static String getCallers(final int depth, String linePrefix) {
2163         final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
2164         StringBuffer sb = new StringBuffer();
2165         for (int i = 0; i < depth; i++) {
2166             sb.append(linePrefix).append(getCaller(callStack, i)).append("\n");
2167         }
2168         return sb.toString();
2169     }
2170 
2171     /**
2172      * @return a String describing the immediate caller of the calling method.
2173      * {@hide}
2174      */
getCaller()2175     public static String getCaller() {
2176         return getCaller(Thread.currentThread().getStackTrace(), 0);
2177     }
2178 }
2179