OSDN Git Service

"Fix" issue #24357296: Debug.getMemoryInfo doesn't include EGL mtrack...
[android-x86/frameworks-base.git] / core / java / android / os / Debug.java
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
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
257         public MemoryInfo() {
258         }
259
260         /**
261          * Return total PSS memory usage in kB.
262          */
263         public int getTotalPss() {
264             return dalvikPss + nativePss + otherPss;
265         }
266
267         /**
268          * @hide Return total PSS memory usage in kB.
269          */
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          */
279         public int getTotalSwappablePss() {
280             return dalvikSwappablePss + nativeSwappablePss + otherSwappablePss;
281         }
282
283         /**
284          * Return total private dirty memory usage in kB.
285          */
286         public int getTotalPrivateDirty() {
287             return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty;
288         }
289
290         /**
291          * Return total shared dirty memory usage in kB.
292          */
293         public int getTotalSharedDirty() {
294             return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty;
295         }
296
297         /**
298          * Return total shared clean memory usage in kB.
299          */
300         public int getTotalPrivateClean() {
301             return dalvikPrivateClean + nativePrivateClean + otherPrivateClean;
302         }
303
304         /**
305          * Return total shared clean memory usage in kB.
306          */
307         public int getTotalSharedClean() {
308             return dalvikSharedClean + nativeSharedClean + otherSharedClean;
309         }
310
311         /**
312          * Return total swapped out memory in kB.
313          * @hide
314          */
315         public int getTotalSwappedOut() {
316             return dalvikSwappedOut + nativeSwappedOut + otherSwappedOut;
317         }
318
319         /** @hide */
320         public int getOtherPss(int which) {
321             return otherStats[which*NUM_CATEGORIES + offsetPss];
322         }
323
324
325         /** @hide */
326         public int getOtherSwappablePss(int which) {
327             return otherStats[which*NUM_CATEGORIES + offsetSwappablePss];
328         }
329
330
331         /** @hide */
332         public int getOtherPrivateDirty(int which) {
333             return otherStats[which*NUM_CATEGORIES + offsetPrivateDirty];
334         }
335
336         /** @hide */
337         public int getOtherSharedDirty(int which) {
338             return otherStats[which*NUM_CATEGORIES + offsetSharedDirty];
339         }
340
341         /** @hide */
342         public int getOtherPrivateClean(int which) {
343             return otherStats[which*NUM_CATEGORIES + offsetPrivateClean];
344         }
345
346         /** @hide */
347         public int getOtherPrivate(int which) {
348           return getOtherPrivateClean(which) + getOtherPrivateDirty(which);
349         }
350
351         /** @hide */
352         public int getOtherSharedClean(int which) {
353             return otherStats[which*NUM_CATEGORIES + offsetSharedClean];
354         }
355
356         /** @hide */
357         public int getOtherSwappedOut(int which) {
358             return otherStats[which*NUM_CATEGORIES + offsetSwappedOut];
359         }
360
361         /** @hide */
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        */
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          */
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          */
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          */
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          */
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          */
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          */
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          */
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          */
614         public int getSummarySystem() {
615             return getTotalPss()
616               - getTotalPrivateClean()
617               - getTotalPrivateDirty();
618         }
619
620         /**
621          * Total Pss in KB.
622          * @hide
623          */
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          */
637         public int getSummaryTotalSwap() {
638             return getTotalSwappedOut();
639         }
640
641         public int describeContents() {
642             return 0;
643         }
644
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
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
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      */
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      */
769     public static boolean waitingForDebugger() {
770         return mWaiting;
771     }
772
773     /**
774      * Determine if a debugger is currently attached.
775      */
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      */
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
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
1031     public static int getMethodTracingMode() {
1032         return VMDebug.getMethodTracingMode();
1033     }
1034
1035     /**
1036      * Stop method tracing.
1037      */
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      */
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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      */
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      */
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      */
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      */
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      */
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 dalvik, the native heap, and everything else.
1542      *
1543      * <p><b>Note:</b> this method directly retrieves memory information for the give process
1544      * from low-level data available to it.  It may not be able to retrieve information about
1545      * some protected allocations, such as graphics.  If you want to be sure you can see
1546      * all information about allocations by the process, use instead
1547      * {@link android.app.ActivityManager#getProcessMemoryInfo(int[])}.</p>
1548      */
1549     public static native void getMemoryInfo(MemoryInfo memoryInfo);
1550
1551     /**
1552      * Note: currently only works when the requested pid has the same UID
1553      * as the caller.
1554      * @hide
1555      */
1556     public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
1557
1558     /**
1559      * Retrieves the PSS memory used by the process as given by the
1560      * smaps.
1561      */
1562     public static native long getPss();
1563
1564     /**
1565      * Retrieves the PSS memory used by the process as given by the
1566      * smaps.  Optionally supply a long array of 1 entry to also
1567      * receive the uss of the process, and another array to also
1568      * retrieve the separate memtrack size.  @hide
1569      */
1570     public static native long getPss(int pid, long[] outUss, long[] outMemtrack);
1571
1572     /** @hide */
1573     public static final int MEMINFO_TOTAL = 0;
1574     /** @hide */
1575     public static final int MEMINFO_FREE = 1;
1576     /** @hide */
1577     public static final int MEMINFO_BUFFERS = 2;
1578     /** @hide */
1579     public static final int MEMINFO_CACHED = 3;
1580     /** @hide */
1581     public static final int MEMINFO_SHMEM = 4;
1582     /** @hide */
1583     public static final int MEMINFO_SLAB = 5;
1584     /** @hide */
1585     public static final int MEMINFO_SWAP_TOTAL = 6;
1586     /** @hide */
1587     public static final int MEMINFO_SWAP_FREE = 7;
1588     /** @hide */
1589     public static final int MEMINFO_ZRAM_TOTAL = 8;
1590     /** @hide */
1591     public static final int MEMINFO_MAPPED = 9;
1592     /** @hide */
1593     public static final int MEMINFO_VM_ALLOC_USED = 10;
1594     /** @hide */
1595     public static final int MEMINFO_PAGE_TABLES = 11;
1596     /** @hide */
1597     public static final int MEMINFO_KERNEL_STACK = 12;
1598     /** @hide */
1599     public static final int MEMINFO_COUNT = 13;
1600
1601     /**
1602      * Retrieves /proc/meminfo.  outSizes is filled with fields
1603      * as defined by MEMINFO_* offsets.
1604      * @hide
1605      */
1606     public static native void getMemInfo(long[] outSizes);
1607
1608     /**
1609      * Establish an object allocation limit in the current thread.
1610      * This feature was never enabled in release builds.  The
1611      * allocation limits feature was removed in Honeycomb.  This
1612      * method exists for compatibility and always returns -1 and has
1613      * no effect.
1614      *
1615      * @deprecated This method is now obsolete.
1616      */
1617     @Deprecated
1618     public static int setAllocationLimit(int limit) {
1619         return -1;
1620     }
1621
1622     /**
1623      * Establish a global object allocation limit.  This feature was
1624      * never enabled in release builds.  The allocation limits feature
1625      * was removed in Honeycomb.  This method exists for compatibility
1626      * and always returns -1 and has no effect.
1627      *
1628      * @deprecated This method is now obsolete.
1629      */
1630     @Deprecated
1631     public static int setGlobalAllocationLimit(int limit) {
1632         return -1;
1633     }
1634
1635     /**
1636      * Dump a list of all currently loaded class to the log file.
1637      *
1638      * @param flags See constants above.
1639      */
1640     public static void printLoadedClasses(int flags) {
1641         VMDebug.printLoadedClasses(flags);
1642     }
1643
1644     /**
1645      * Get the number of loaded classes.
1646      * @return the number of loaded classes.
1647      */
1648     public static int getLoadedClassCount() {
1649         return VMDebug.getLoadedClassCount();
1650     }
1651
1652     /**
1653      * Dump "hprof" data to the specified file.  This may cause a GC.
1654      *
1655      * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof").
1656      * @throws UnsupportedOperationException if the VM was built without
1657      *         HPROF support.
1658      * @throws IOException if an error occurs while opening or writing files.
1659      */
1660     public static void dumpHprofData(String fileName) throws IOException {
1661         VMDebug.dumpHprofData(fileName);
1662     }
1663
1664     /**
1665      * Like dumpHprofData(String), but takes an already-opened
1666      * FileDescriptor to which the trace is written.  The file name is also
1667      * supplied simply for logging.  Makes a dup of the file descriptor.
1668      *
1669      * Primarily for use by the "am" shell command.
1670      *
1671      * @hide
1672      */
1673     public static void dumpHprofData(String fileName, FileDescriptor fd)
1674             throws IOException {
1675         VMDebug.dumpHprofData(fileName, fd);
1676     }
1677
1678     /**
1679      * Collect "hprof" and send it to DDMS.  This may cause a GC.
1680      *
1681      * @throws UnsupportedOperationException if the VM was built without
1682      *         HPROF support.
1683      * @hide
1684      */
1685     public static void dumpHprofDataDdms() {
1686         VMDebug.dumpHprofDataDdms();
1687     }
1688
1689     /**
1690      * Writes native heap data to the specified file descriptor.
1691      *
1692      * @hide
1693      */
1694     public static native void dumpNativeHeap(FileDescriptor fd);
1695
1696     /**
1697       * Returns a count of the extant instances of a class.
1698      *
1699      * @hide
1700      */
1701     public static long countInstancesOfClass(Class cls) {
1702         return VMDebug.countInstancesOfClass(cls, true);
1703     }
1704
1705     /**
1706      * Returns the number of sent transactions from this process.
1707      * @return The number of sent transactions or -1 if it could not read t.
1708      */
1709     public static native int getBinderSentTransactions();
1710
1711     /**
1712      * Returns the number of received transactions from the binder driver.
1713      * @return The number of received transactions or -1 if it could not read the stats.
1714      */
1715     public static native int getBinderReceivedTransactions();
1716
1717     /**
1718      * Returns the number of active local Binder objects that exist in the
1719      * current process.
1720      */
1721     public static final native int getBinderLocalObjectCount();
1722
1723     /**
1724      * Returns the number of references to remote proxy Binder objects that
1725      * exist in the current process.
1726      */
1727     public static final native int getBinderProxyObjectCount();
1728
1729     /**
1730      * Returns the number of death notification links to Binder objects that
1731      * exist in the current process.
1732      */
1733     public static final native int getBinderDeathObjectCount();
1734
1735     /**
1736      * Primes the register map cache.
1737      *
1738      * Only works for classes in the bootstrap class loader.  Does not
1739      * cause classes to be loaded if they're not already present.
1740      *
1741      * The classAndMethodDesc argument is a concatentation of the VM-internal
1742      * class descriptor, method name, and method descriptor.  Examples:
1743      *     Landroid/os/Looper;.loop:()V
1744      *     Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V
1745      *
1746      * @param classAndMethodDesc the method to prepare
1747      *
1748      * @hide
1749      */
1750     public static final boolean cacheRegisterMap(String classAndMethodDesc) {
1751         return VMDebug.cacheRegisterMap(classAndMethodDesc);
1752     }
1753
1754     /**
1755      * Dumps the contents of VM reference tables (e.g. JNI locals and
1756      * globals) to the log file.
1757      *
1758      * @hide
1759      */
1760     public static final void dumpReferenceTables() {
1761         VMDebug.dumpReferenceTables();
1762     }
1763
1764     /**
1765      * API for gathering and querying instruction counts.
1766      *
1767      * Example usage:
1768      * <pre>
1769      *   Debug.InstructionCount icount = new Debug.InstructionCount();
1770      *   icount.resetAndStart();
1771      *    [... do lots of stuff ...]
1772      *   if (icount.collect()) {
1773      *       System.out.println("Total instructions executed: "
1774      *           + icount.globalTotal());
1775      *       System.out.println("Method invocations: "
1776      *           + icount.globalMethodInvocations());
1777      *   }
1778      * </pre>
1779      *
1780      * @deprecated Instruction counting is no longer supported.
1781      */
1782     @Deprecated
1783     public static class InstructionCount {
1784         private static final int NUM_INSTR =
1785             OpcodeInfo.MAXIMUM_PACKED_VALUE + 1;
1786
1787         private int[] mCounts;
1788
1789         public InstructionCount() {
1790             mCounts = new int[NUM_INSTR];
1791         }
1792
1793         /**
1794          * Reset counters and ensure counts are running.  Counts may
1795          * have already been running.
1796          *
1797          * @return true if counting was started
1798          */
1799         public boolean resetAndStart() {
1800             try {
1801                 VMDebug.startInstructionCounting();
1802                 VMDebug.resetInstructionCount();
1803             } catch (UnsupportedOperationException uoe) {
1804                 return false;
1805             }
1806             return true;
1807         }
1808
1809         /**
1810          * Collect instruction counts.  May or may not stop the
1811          * counting process.
1812          */
1813         public boolean collect() {
1814             try {
1815                 VMDebug.stopInstructionCounting();
1816                 VMDebug.getInstructionCount(mCounts);
1817             } catch (UnsupportedOperationException uoe) {
1818                 return false;
1819             }
1820             return true;
1821         }
1822
1823         /**
1824          * Return the total number of instructions executed globally (i.e. in
1825          * all threads).
1826          */
1827         public int globalTotal() {
1828             int count = 0;
1829
1830             for (int i = 0; i < NUM_INSTR; i++) {
1831                 count += mCounts[i];
1832             }
1833
1834             return count;
1835         }
1836
1837         /**
1838          * Return the total number of method-invocation instructions
1839          * executed globally.
1840          */
1841         public int globalMethodInvocations() {
1842             int count = 0;
1843
1844             for (int i = 0; i < NUM_INSTR; i++) {
1845                 if (OpcodeInfo.isInvoke(i)) {
1846                     count += mCounts[i];
1847                 }
1848             }
1849
1850             return count;
1851         }
1852     }
1853
1854     /**
1855      * A Map of typed debug properties.
1856      */
1857     private static final TypedProperties debugProperties;
1858
1859     /*
1860      * Load the debug properties from the standard files into debugProperties.
1861      */
1862     static {
1863         if (false) {
1864             final String TAG = "DebugProperties";
1865             final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" };
1866             final TypedProperties tp = new TypedProperties();
1867
1868             // Read the properties from each of the files, if present.
1869             for (String file : files) {
1870                 Reader r;
1871                 try {
1872                     r = new FileReader(file);
1873                 } catch (FileNotFoundException ex) {
1874                     // It's ok if a file is missing.
1875                     continue;
1876                 }
1877
1878                 try {
1879                     tp.load(r);
1880                 } catch (Exception ex) {
1881                     throw new RuntimeException("Problem loading " + file, ex);
1882                 } finally {
1883                     try {
1884                         r.close();
1885                     } catch (IOException ex) {
1886                         // Ignore this error.
1887                     }
1888                 }
1889             }
1890
1891             debugProperties = tp.isEmpty() ? null : tp;
1892         } else {
1893             debugProperties = null;
1894         }
1895     }
1896
1897
1898     /**
1899      * Returns true if the type of the field matches the specified class.
1900      * Handles the case where the class is, e.g., java.lang.Boolean, but
1901      * the field is of the primitive "boolean" type.  Also handles all of
1902      * the java.lang.Number subclasses.
1903      */
1904     private static boolean fieldTypeMatches(Field field, Class<?> cl) {
1905         Class<?> fieldClass = field.getType();
1906         if (fieldClass == cl) {
1907             return true;
1908         }
1909         Field primitiveTypeField;
1910         try {
1911             /* All of the classes we care about (Boolean, Integer, etc.)
1912              * have a Class field called "TYPE" that points to the corresponding
1913              * primitive class.
1914              */
1915             primitiveTypeField = cl.getField("TYPE");
1916         } catch (NoSuchFieldException ex) {
1917             return false;
1918         }
1919         try {
1920             return fieldClass == (Class<?>) primitiveTypeField.get(null);
1921         } catch (IllegalAccessException ex) {
1922             return false;
1923         }
1924     }
1925
1926
1927     /**
1928      * Looks up the property that corresponds to the field, and sets the field's value
1929      * if the types match.
1930      */
1931     private static void modifyFieldIfSet(final Field field, final TypedProperties properties,
1932                                          final String propertyName) {
1933         if (field.getType() == java.lang.String.class) {
1934             int stringInfo = properties.getStringInfo(propertyName);
1935             switch (stringInfo) {
1936                 case TypedProperties.STRING_SET:
1937                     // Handle as usual below.
1938                     break;
1939                 case TypedProperties.STRING_NULL:
1940                     try {
1941                         field.set(null, null);  // null object for static fields; null string
1942                     } catch (IllegalAccessException ex) {
1943                         throw new IllegalArgumentException(
1944                             "Cannot set field for " + propertyName, ex);
1945                     }
1946                     return;
1947                 case TypedProperties.STRING_NOT_SET:
1948                     return;
1949                 case TypedProperties.STRING_TYPE_MISMATCH:
1950                     throw new IllegalArgumentException(
1951                         "Type of " + propertyName + " " +
1952                         " does not match field type (" + field.getType() + ")");
1953                 default:
1954                     throw new IllegalStateException(
1955                         "Unexpected getStringInfo(" + propertyName + ") return value " +
1956                         stringInfo);
1957             }
1958         }
1959         Object value = properties.get(propertyName);
1960         if (value != null) {
1961             if (!fieldTypeMatches(field, value.getClass())) {
1962                 throw new IllegalArgumentException(
1963                     "Type of " + propertyName + " (" + value.getClass() + ") " +
1964                     " does not match field type (" + field.getType() + ")");
1965             }
1966             try {
1967                 field.set(null, value);  // null object for static fields
1968             } catch (IllegalAccessException ex) {
1969                 throw new IllegalArgumentException(
1970                     "Cannot set field for " + propertyName, ex);
1971             }
1972         }
1973     }
1974
1975
1976     /**
1977      * Equivalent to <code>setFieldsOn(cl, false)</code>.
1978      *
1979      * @see #setFieldsOn(Class, boolean)
1980      *
1981      * @hide
1982      */
1983     public static void setFieldsOn(Class<?> cl) {
1984         setFieldsOn(cl, false);
1985     }
1986
1987     /**
1988      * Reflectively sets static fields of a class based on internal debugging
1989      * properties.  This method is a no-op if false is
1990      * false.
1991      * <p>
1992      * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: false will
1993      * always be false in release builds.  This API is typically only useful
1994      * for platform developers.
1995      * </p>
1996      * Class setup: define a class whose only fields are non-final, static
1997      * primitive types (except for "char") or Strings.  In a static block
1998      * after the field definitions/initializations, pass the class to
1999      * this method, Debug.setFieldsOn(). Example:
2000      * <pre>
2001      * package com.example;
2002      *
2003      * import android.os.Debug;
2004      *
2005      * public class MyDebugVars {
2006      *    public static String s = "a string";
2007      *    public static String s2 = "second string";
2008      *    public static String ns = null;
2009      *    public static boolean b = false;
2010      *    public static int i = 5;
2011      *    @Debug.DebugProperty
2012      *    public static float f = 0.1f;
2013      *    @@Debug.DebugProperty
2014      *    public static double d = 0.5d;
2015      *
2016      *    // This MUST appear AFTER all fields are defined and initialized!
2017      *    static {
2018      *        // Sets all the fields
2019      *        Debug.setFieldsOn(MyDebugVars.class);
2020      *
2021      *        // Sets only the fields annotated with @Debug.DebugProperty
2022      *        // Debug.setFieldsOn(MyDebugVars.class, true);
2023      *    }
2024      * }
2025      * </pre>
2026      * setFieldsOn() may override the value of any field in the class based
2027      * on internal properties that are fixed at boot time.
2028      * <p>
2029      * These properties are only set during platform debugging, and are not
2030      * meant to be used as a general-purpose properties store.
2031      *
2032      * {@hide}
2033      *
2034      * @param cl The class to (possibly) modify
2035      * @param partial If false, sets all static fields, otherwise, only set
2036      *        fields with the {@link android.os.Debug.DebugProperty}
2037      *        annotation
2038      * @throws IllegalArgumentException if any fields are final or non-static,
2039      *         or if the type of the field does not match the type of
2040      *         the internal debugging property value.
2041      */
2042     public static void setFieldsOn(Class<?> cl, boolean partial) {
2043         if (false) {
2044             if (debugProperties != null) {
2045                 /* Only look for fields declared directly by the class,
2046                  * so we don't mysteriously change static fields in superclasses.
2047                  */
2048                 for (Field field : cl.getDeclaredFields()) {
2049                     if (!partial || field.getAnnotation(DebugProperty.class) != null) {
2050                         final String propertyName = cl.getName() + "." + field.getName();
2051                         boolean isStatic = Modifier.isStatic(field.getModifiers());
2052                         boolean isFinal = Modifier.isFinal(field.getModifiers());
2053
2054                         if (!isStatic || isFinal) {
2055                             throw new IllegalArgumentException(propertyName +
2056                                 " must be static and non-final");
2057                         }
2058                         modifyFieldIfSet(field, debugProperties, propertyName);
2059                     }
2060                 }
2061             }
2062         } else {
2063             Log.wtf(TAG,
2064                   "setFieldsOn(" + (cl == null ? "null" : cl.getName()) +
2065                   ") called in non-DEBUG build");
2066         }
2067     }
2068
2069     /**
2070      * Annotation to put on fields you want to set with
2071      * {@link Debug#setFieldsOn(Class, boolean)}.
2072      *
2073      * @hide
2074      */
2075     @Target({ ElementType.FIELD })
2076     @Retention(RetentionPolicy.RUNTIME)
2077     public @interface DebugProperty {
2078     }
2079
2080     /**
2081      * Get a debugging dump of a system service by name.
2082      *
2083      * <p>Most services require the caller to hold android.permission.DUMP.
2084      *
2085      * @param name of the service to dump
2086      * @param fd to write dump output to (usually an output log file)
2087      * @param args to pass to the service's dump method, may be null
2088      * @return true if the service was dumped successfully, false if
2089      *     the service could not be found or had an error while dumping
2090      */
2091     public static boolean dumpService(String name, FileDescriptor fd, String[] args) {
2092         IBinder service = ServiceManager.getService(name);
2093         if (service == null) {
2094             Log.e(TAG, "Can't find service to dump: " + name);
2095             return false;
2096         }
2097
2098         try {
2099             service.dump(fd, args);
2100             return true;
2101         } catch (RemoteException e) {
2102             Log.e(TAG, "Can't dump service: " + name, e);
2103             return false;
2104         }
2105     }
2106
2107     /**
2108      * Have the stack traces of the given native process dumped to the
2109      * specified file.  Will be appended to the file.
2110      * @hide
2111      */
2112     public static native void dumpNativeBacktraceToFile(int pid, String file);
2113
2114     /**
2115      * Return a String describing the calling method and location at a particular stack depth.
2116      * @param callStack the Thread stack
2117      * @param depth the depth of stack to return information for.
2118      * @return the String describing the caller at that depth.
2119      */
2120     private static String getCaller(StackTraceElement callStack[], int depth) {
2121         // callStack[4] is the caller of the method that called getCallers()
2122         if (4 + depth >= callStack.length) {
2123             return "<bottom of call stack>";
2124         }
2125         StackTraceElement caller = callStack[4 + depth];
2126         return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber();
2127     }
2128
2129     /**
2130      * Return a string consisting of methods and locations at multiple call stack levels.
2131      * @param depth the number of levels to return, starting with the immediate caller.
2132      * @return a string describing the call stack.
2133      * {@hide}
2134      */
2135     public static String getCallers(final int depth) {
2136         final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
2137         StringBuffer sb = new StringBuffer();
2138         for (int i = 0; i < depth; i++) {
2139             sb.append(getCaller(callStack, i)).append(" ");
2140         }
2141         return sb.toString();
2142     }
2143
2144     /**
2145      * Return a string consisting of methods and locations at multiple call stack levels.
2146      * @param depth the number of levels to return, starting with the immediate caller.
2147      * @return a string describing the call stack.
2148      * {@hide}
2149      */
2150     public static String getCallers(final int start, int depth) {
2151         final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
2152         StringBuffer sb = new StringBuffer();
2153         depth += start;
2154         for (int i = start; i < depth; i++) {
2155             sb.append(getCaller(callStack, i)).append(" ");
2156         }
2157         return sb.toString();
2158     }
2159
2160     /**
2161      * Like {@link #getCallers(int)}, but each location is append to the string
2162      * as a new line with <var>linePrefix</var> in front of it.
2163      * @param depth the number of levels to return, starting with the immediate caller.
2164      * @param linePrefix prefix to put in front of each location.
2165      * @return a string describing the call stack.
2166      * {@hide}
2167      */
2168     public static String getCallers(final int depth, String linePrefix) {
2169         final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
2170         StringBuffer sb = new StringBuffer();
2171         for (int i = 0; i < depth; i++) {
2172             sb.append(linePrefix).append(getCaller(callStack, i)).append("\n");
2173         }
2174         return sb.toString();
2175     }
2176
2177     /**
2178      * @return a String describing the immediate caller of the calling method.
2179      * {@hide}
2180      */
2181     public static String getCaller() {
2182         return getCaller(Thread.currentThread().getStackTrace(), 0);
2183     }
2184 }