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