blob: fd01da9f8afaf7520b421769cb132aa1a937d1b4 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Dave Bort1ce5bd32009-04-22 17:36:56 -070019import com.android.internal.util.TypedProperties;
20
Dave Bort1ce5bd32009-04-22 17:36:56 -070021import android.util.Log;
22
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070023import java.io.FileDescriptor;
Dave Bort1ce5bd32009-04-22 17:36:56 -070024import java.io.FileNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import java.io.FileOutputStream;
Dave Bort1ce5bd32009-04-22 17:36:56 -070026import java.io.FileReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import java.io.IOException;
28import java.io.OutputStreamWriter;
29import java.io.PrintWriter;
Dave Bort1ce5bd32009-04-22 17:36:56 -070030import java.io.Reader;
31import java.lang.reflect.Field;
32import java.lang.reflect.Modifier;
Romain Guyc4b11a72009-05-13 15:46:37 -070033import java.lang.annotation.Target;
34import java.lang.annotation.ElementType;
35import java.lang.annotation.Retention;
36import java.lang.annotation.RetentionPolicy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
38import org.apache.harmony.dalvik.ddmc.Chunk;
39import org.apache.harmony.dalvik.ddmc.ChunkHandler;
40import org.apache.harmony.dalvik.ddmc.DdmServer;
41
Dan Bornstein9f315542010-11-19 18:12:55 -080042import dalvik.bytecode.OpcodeInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import dalvik.bytecode.Opcodes;
44import dalvik.system.VMDebug;
45
46
47/**
Ian Rogersfe067a42013-02-22 19:59:23 -080048 * Provides various debugging methods for Android applications, including
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 * tracing and allocation counts.
50 * <p><strong>Logging Trace Files</strong></p>
51 * <p>Debug can create log files that give details about an application, such as
52 * a call stack and start/stop times for any running methods. See <a
53href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
54 * information about reading trace files. To start logging trace files, call one
55 * of the startMethodTracing() methods. To stop tracing, call
56 * {@link #stopMethodTracing()}.
57 */
58public final class Debug
59{
Dan Egnor3eda9792010-03-05 13:28:36 -080060 private static final String TAG = "Debug";
61
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 /**
63 * Flags for startMethodTracing(). These can be ORed together.
64 *
65 * TRACE_COUNT_ALLOCS adds the results from startAllocCounting to the
66 * trace key file.
67 */
68 public static final int TRACE_COUNT_ALLOCS = VMDebug.TRACE_COUNT_ALLOCS;
69
70 /**
71 * Flags for printLoadedClasses(). Default behavior is to only show
72 * the class name.
73 */
74 public static final int SHOW_FULL_DETAIL = 1;
75 public static final int SHOW_CLASSLOADER = (1 << 1);
76 public static final int SHOW_INITIALIZED = (1 << 2);
77
78 // set/cleared by waitForDebugger()
79 private static volatile boolean mWaiting = false;
80
81 private Debug() {}
82
83 /*
84 * How long to wait for the debugger to finish sending requests. I've
85 * seen this hit 800msec on the device while waiting for a response
86 * to travel over USB and get processed, so we take that and add
87 * half a second.
88 */
89 private static final int MIN_DEBUGGER_IDLE = 1300; // msec
90
91 /* how long to sleep when polling for activity */
92 private static final int SPIN_DELAY = 200; // msec
93
94 /**
95 * Default trace file path and file
96 */
Christian Mehlmauer798e2d32010-06-17 18:24:07 +020097 private static final String DEFAULT_TRACE_PATH_PREFIX =
Jeff Sharkeyb049e212012-09-07 23:16:01 -070098 Environment.getLegacyExternalStorageDirectory().getPath() + "/";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 private static final String DEFAULT_TRACE_BODY = "dmtrace";
100 private static final String DEFAULT_TRACE_EXTENSION = ".trace";
101 private static final String DEFAULT_TRACE_FILE_PATH =
102 DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
103 + DEFAULT_TRACE_EXTENSION;
104
105
106 /**
107 * This class is used to retrieved various statistics about the memory mappings for this
108 * process. The returns info broken down by dalvik, native, and other. All results are in kB.
109 */
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700110 public static class MemoryInfo implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 /** The proportional set size for dalvik. */
112 public int dalvikPss;
113 /** The private dirty pages used by dalvik. */
114 public int dalvikPrivateDirty;
115 /** The shared dirty pages used by dalvik. */
116 public int dalvikSharedDirty;
117
118 /** The proportional set size for the native heap. */
119 public int nativePss;
120 /** The private dirty pages used by the native heap. */
121 public int nativePrivateDirty;
122 /** The shared dirty pages used by the native heap. */
123 public int nativeSharedDirty;
124
125 /** The proportional set size for everything else. */
126 public int otherPss;
127 /** The private dirty pages used by everything else. */
128 public int otherPrivateDirty;
129 /** The shared dirty pages used by everything else. */
130 public int otherSharedDirty;
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200131
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700132 /** @hide */
Ian Rogers7c9f30b2013-02-27 10:57:13 -0800133 public static final int NUM_OTHER_STATS = 10;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700134
135 private int[] otherStats = new int[NUM_OTHER_STATS*3];
136
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700137 public MemoryInfo() {
138 }
139
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700140 /**
141 * Return total PSS memory usage in kB.
142 */
143 public int getTotalPss() {
144 return dalvikPss + nativePss + otherPss;
145 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200146
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700147 /**
148 * Return total private dirty memory usage in kB.
149 */
150 public int getTotalPrivateDirty() {
151 return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty;
152 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200153
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700154 /**
155 * Return total shared dirty memory usage in kB.
156 */
157 public int getTotalSharedDirty() {
158 return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty;
159 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200160
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700161 /* @hide */
162 public int getOtherPss(int which) {
163 return otherStats[which*3];
164 }
165
166 /* @hide */
167 public int getOtherPrivateDirty(int which) {
168 return otherStats[which*3 + 1];
169 }
170
171 /* @hide */
172 public int getOtherSharedDirty(int which) {
173 return otherStats[which*3 + 2];
174 }
175
176
177 /* @hide */
178 public static String getOtherLabel(int which) {
179 switch (which) {
Ian Rogers7c9f30b2013-02-27 10:57:13 -0800180 case 0: return "Stack";
181 case 1: return "Cursor";
182 case 2: return "Ashmem";
183 case 3: return "Other dev";
184 case 4: return ".so mmap";
185 case 5: return ".jar mmap";
186 case 6: return ".apk mmap";
187 case 7: return ".ttf mmap";
188 case 8: return ".dex mmap";
189 case 9: return "Other mmap";
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700190 default: return "????";
191 }
192 }
193
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700194 public int describeContents() {
195 return 0;
196 }
197
198 public void writeToParcel(Parcel dest, int flags) {
199 dest.writeInt(dalvikPss);
200 dest.writeInt(dalvikPrivateDirty);
201 dest.writeInt(dalvikSharedDirty);
202 dest.writeInt(nativePss);
203 dest.writeInt(nativePrivateDirty);
204 dest.writeInt(nativeSharedDirty);
205 dest.writeInt(otherPss);
206 dest.writeInt(otherPrivateDirty);
207 dest.writeInt(otherSharedDirty);
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700208 dest.writeIntArray(otherStats);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700209 }
210
211 public void readFromParcel(Parcel source) {
212 dalvikPss = source.readInt();
213 dalvikPrivateDirty = source.readInt();
214 dalvikSharedDirty = source.readInt();
215 nativePss = source.readInt();
216 nativePrivateDirty = source.readInt();
217 nativeSharedDirty = source.readInt();
218 otherPss = source.readInt();
219 otherPrivateDirty = source.readInt();
220 otherSharedDirty = source.readInt();
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700221 otherStats = source.createIntArray();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700222 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200223
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700224 public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
225 public MemoryInfo createFromParcel(Parcel source) {
226 return new MemoryInfo(source);
227 }
228 public MemoryInfo[] newArray(int size) {
229 return new MemoryInfo[size];
230 }
231 };
232
233 private MemoryInfo(Parcel source) {
234 readFromParcel(source);
235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 }
237
238
239 /**
240 * Wait until a debugger attaches. As soon as the debugger attaches,
241 * this returns, so you will need to place a breakpoint after the
242 * waitForDebugger() call if you want to start tracing immediately.
243 */
244 public static void waitForDebugger() {
245 if (!VMDebug.isDebuggingEnabled()) {
246 //System.out.println("debugging not enabled, not waiting");
247 return;
248 }
249 if (isDebuggerConnected())
250 return;
251
252 // if DDMS is listening, inform them of our plight
253 System.out.println("Sending WAIT chunk");
254 byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger"
255 Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1);
256 DdmServer.sendChunk(waitChunk);
257
258 mWaiting = true;
259 while (!isDebuggerConnected()) {
260 try { Thread.sleep(SPIN_DELAY); }
261 catch (InterruptedException ie) {}
262 }
263 mWaiting = false;
264
265 System.out.println("Debugger has connected");
266
267 /*
268 * There is no "ready to go" signal from the debugger, and we're
269 * not allowed to suspend ourselves -- the debugger expects us to
270 * be running happily, and gets confused if we aren't. We need to
271 * allow the debugger a chance to set breakpoints before we start
272 * running again.
273 *
274 * Sit and spin until the debugger has been idle for a short while.
275 */
276 while (true) {
277 long delta = VMDebug.lastDebuggerActivity();
278 if (delta < 0) {
279 System.out.println("debugger detached?");
280 break;
281 }
282
283 if (delta < MIN_DEBUGGER_IDLE) {
284 System.out.println("waiting for debugger to settle...");
285 try { Thread.sleep(SPIN_DELAY); }
286 catch (InterruptedException ie) {}
287 } else {
288 System.out.println("debugger has settled (" + delta + ")");
289 break;
290 }
291 }
292 }
293
294 /**
295 * Returns "true" if one or more threads is waiting for a debugger
296 * to attach.
297 */
298 public static boolean waitingForDebugger() {
299 return mWaiting;
300 }
301
302 /**
303 * Determine if a debugger is currently attached.
304 */
305 public static boolean isDebuggerConnected() {
306 return VMDebug.isDebuggerConnected();
307 }
308
309 /**
Andy McFaddene5772322010-01-22 07:23:31 -0800310 * Returns an array of strings that identify VM features. This is
311 * used by DDMS to determine what sorts of operations the VM can
312 * perform.
313 *
314 * @hide
315 */
316 public static String[] getVmFeatureList() {
317 return VMDebug.getVmFeatureList();
318 }
319
320 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 * Change the JDWP port.
322 *
323 * @deprecated no longer needed or useful
324 */
325 @Deprecated
326 public static void changeDebugPort(int port) {}
327
328 /**
329 * This is the pathname to the sysfs file that enables and disables
330 * tracing on the qemu emulator.
331 */
332 private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state";
333
334 /**
335 * Enable qemu tracing. For this to work requires running everything inside
336 * the qemu emulator; otherwise, this method will have no effect. The trace
337 * file is specified on the command line when the emulator is started. For
338 * example, the following command line <br />
339 * <code>emulator -trace foo</code><br />
340 * will start running the emulator and create a trace file named "foo". This
341 * method simply enables writing the trace records to the trace file.
342 *
343 * <p>
344 * The main differences between this and {@link #startMethodTracing()} are
345 * that tracing in the qemu emulator traces every cpu instruction of every
346 * process, including kernel code, so we have more complete information,
347 * including all context switches. We can also get more detailed information
348 * such as cache misses. The sequence of calls is determined by
349 * post-processing the instruction trace. The qemu tracing is also done
350 * without modifying the application or perturbing the timing of calls
351 * because no instrumentation is added to the application being traced.
352 * </p>
353 *
354 * <p>
355 * One limitation of using this method compared to using
356 * {@link #startMethodTracing()} on the real device is that the emulator
357 * does not model all of the real hardware effects such as memory and
358 * bus contention. The emulator also has a simple cache model and cannot
359 * capture all the complexities of a real cache.
360 * </p>
361 */
362 public static void startNativeTracing() {
363 // Open the sysfs file for writing and write "1" to it.
364 PrintWriter outStream = null;
365 try {
366 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
367 outStream = new PrintWriter(new OutputStreamWriter(fos));
368 outStream.println("1");
369 } catch (Exception e) {
370 } finally {
371 if (outStream != null)
372 outStream.close();
373 }
374
375 VMDebug.startEmulatorTracing();
376 }
377
378 /**
379 * Stop qemu tracing. See {@link #startNativeTracing()} to start tracing.
380 *
381 * <p>Tracing can be started and stopped as many times as desired. When
382 * the qemu emulator itself is stopped then the buffered trace records
383 * are flushed and written to the trace file. In fact, it is not necessary
384 * to call this method at all; simply killing qemu is sufficient. But
385 * starting and stopping a trace is useful for examining a specific
386 * region of code.</p>
387 */
388 public static void stopNativeTracing() {
389 VMDebug.stopEmulatorTracing();
390
391 // Open the sysfs file for writing and write "0" to it.
392 PrintWriter outStream = null;
393 try {
394 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
395 outStream = new PrintWriter(new OutputStreamWriter(fos));
396 outStream.println("0");
397 } catch (Exception e) {
398 // We could print an error message here but we probably want
399 // to quietly ignore errors if we are not running in the emulator.
400 } finally {
401 if (outStream != null)
402 outStream.close();
403 }
404 }
405
406 /**
407 * Enable "emulator traces", in which information about the current
408 * method is made available to the "emulator -trace" feature. There
409 * is no corresponding "disable" call -- this is intended for use by
410 * the framework when tracing should be turned on and left that way, so
411 * that traces captured with F9/F10 will include the necessary data.
412 *
413 * This puts the VM into "profile" mode, which has performance
414 * consequences.
415 *
416 * To temporarily enable tracing, use {@link #startNativeTracing()}.
417 */
418 public static void enableEmulatorTraceOutput() {
419 VMDebug.startEmulatorTracing();
420 }
421
422 /**
423 * Start method tracing with default log name and buffer size. See <a
424href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
425 * information about reading these files. Call stopMethodTracing() to stop
426 * tracing.
427 */
428 public static void startMethodTracing() {
429 VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0);
430 }
431
432 /**
433 * Start method tracing, specifying the trace log file name. The trace
434 * file will be put under "/sdcard" unless an absolute path is given.
435 * See <a
436 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
437 * information about reading trace files.
438 *
439 * @param traceName Name for the trace log file to create.
440 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
441 * If the files already exist, they will be truncated.
442 * If the trace file given does not end in ".trace", it will be appended for you.
443 */
444 public static void startMethodTracing(String traceName) {
445 startMethodTracing(traceName, 0, 0);
446 }
447
448 /**
449 * Start method tracing, specifying the trace log file name and the
450 * buffer size. The trace files will be put under "/sdcard" unless an
451 * absolute path is given. See <a
452 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
453 * information about reading trace files.
454 * @param traceName Name for the trace log file to create.
455 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
456 * If the files already exist, they will be truncated.
457 * If the trace file given does not end in ".trace", it will be appended for you.
458 *
459 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
460 */
461 public static void startMethodTracing(String traceName, int bufferSize) {
462 startMethodTracing(traceName, bufferSize, 0);
463 }
464
465 /**
466 * Start method tracing, specifying the trace log file name and the
467 * buffer size. The trace files will be put under "/sdcard" unless an
468 * absolute path is given. See <a
469 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
470 * information about reading trace files.
471 *
472 * <p>
473 * When method tracing is enabled, the VM will run more slowly than
474 * usual, so the timings from the trace files should only be considered
475 * in relative terms (e.g. was run #1 faster than run #2). The times
476 * for native methods will not change, so don't try to use this to
477 * compare the performance of interpreted and native implementations of the
478 * same method. As an alternative, consider using "native" tracing
479 * in the emulator via {@link #startNativeTracing()}.
480 * </p>
481 *
482 * @param traceName Name for the trace log file to create.
483 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
484 * If the files already exist, they will be truncated.
485 * If the trace file given does not end in ".trace", it will be appended for you.
486 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
487 */
488 public static void startMethodTracing(String traceName, int bufferSize,
489 int flags) {
490
491 String pathName = traceName;
492 if (pathName.charAt(0) != '/')
493 pathName = DEFAULT_TRACE_PATH_PREFIX + pathName;
494 if (!pathName.endsWith(DEFAULT_TRACE_EXTENSION))
495 pathName = pathName + DEFAULT_TRACE_EXTENSION;
496
497 VMDebug.startMethodTracing(pathName, bufferSize, flags);
498 }
499
500 /**
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700501 * Like startMethodTracing(String, int, int), but taking an already-opened
502 * FileDescriptor in which the trace is written. The file name is also
503 * supplied simply for logging. Makes a dup of the file descriptor.
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200504 *
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700505 * Not exposed in the SDK unless we are really comfortable with supporting
506 * this and find it would be useful.
507 * @hide
508 */
509 public static void startMethodTracing(String traceName, FileDescriptor fd,
510 int bufferSize, int flags) {
511 VMDebug.startMethodTracing(traceName, fd, bufferSize, flags);
512 }
513
514 /**
Andy McFadden72a20db0c2010-01-22 12:20:41 -0800515 * Starts method tracing without a backing file. When stopMethodTracing
516 * is called, the result is sent directly to DDMS. (If DDMS is not
517 * attached when tracing ends, the profiling data will be discarded.)
518 *
519 * @hide
520 */
521 public static void startMethodTracingDdms(int bufferSize, int flags) {
522 VMDebug.startMethodTracingDdms(bufferSize, flags);
523 }
524
525 /**
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700526 * Determine whether method tracing is currently active.
527 * @hide
528 */
529 public static boolean isMethodTracingActive() {
530 return VMDebug.isMethodTracingActive();
531 }
532
533 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 * Stop method tracing.
535 */
536 public static void stopMethodTracing() {
537 VMDebug.stopMethodTracing();
538 }
539
540 /**
541 * Get an indication of thread CPU usage. The value returned
542 * indicates the amount of time that the current thread has spent
543 * executing code or waiting for certain types of I/O.
544 *
545 * The time is expressed in nanoseconds, and is only meaningful
546 * when compared to the result from an earlier call. Note that
547 * nanosecond resolution does not imply nanosecond accuracy.
548 *
549 * On system which don't support this operation, the call returns -1.
550 */
551 public static long threadCpuTimeNanos() {
552 return VMDebug.threadCpuTimeNanos();
553 }
554
555 /**
Chet Haase2970c492010-11-09 13:58:04 -0800556 * Start counting the number and aggregate size of memory allocations.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 *
Ian Rogersfe067a42013-02-22 19:59:23 -0800558 * <p>The {@link #startAllocCounting() start} method resets the counts and enables counting.
559 * The {@link #stopAllocCounting() stop} method disables the counting so that the analysis
560 * code doesn't cause additional allocations. The various <code>get</code> methods return
561 * the specified value. And the various <code>reset</code> methods reset the specified
Chet Haase2970c492010-11-09 13:58:04 -0800562 * count.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 *
Ian Rogersfe067a42013-02-22 19:59:23 -0800564 * <p>Counts are kept for the system as a whole (global) and for each thread.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 * The per-thread counts for threads other than the current thread
Chet Haase2970c492010-11-09 13:58:04 -0800566 * are not cleared by the "reset" or "start" calls.</p>
Ian Rogersfe067a42013-02-22 19:59:23 -0800567 *
568 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569 */
Ian Rogersfe067a42013-02-22 19:59:23 -0800570 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 public static void startAllocCounting() {
572 VMDebug.startAllocCounting();
573 }
Chet Haase2970c492010-11-09 13:58:04 -0800574
575 /**
576 * Stop counting the number and aggregate size of memory allocations.
577 *
578 * @see #startAllocCounting()
579 */
Ian Rogersc2a3adb2013-04-19 11:31:48 -0700580 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 public static void stopAllocCounting() {
582 VMDebug.stopAllocCounting();
583 }
584
Ian Rogersfe067a42013-02-22 19:59:23 -0800585 /**
586 * Returns the global count of objects allocated by the runtime between a
587 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
588 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 public static int getGlobalAllocCount() {
590 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
591 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800592
593 /**
594 * Clears the global count of objects allocated.
595 * @see #getGlobalAllocCount()
596 */
597 public static void resetGlobalAllocCount() {
598 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
599 }
600
601 /**
602 * Returns the global size, in bytes, of objects allocated by the runtime between a
603 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
604 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 public static int getGlobalAllocSize() {
606 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
607 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800608
609 /**
610 * Clears the global size of objects allocated.
611 * @see #getGlobalAllocCountSize()
612 */
613 public static void resetGlobalAllocSize() {
614 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
615 }
616
617 /**
618 * Returns the global count of objects freed by the runtime between a
619 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
620 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 public static int getGlobalFreedCount() {
622 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
623 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800624
625 /**
626 * Clears the global count of objects freed.
627 * @see #getGlobalFreedCount()
628 */
629 public static void resetGlobalFreedCount() {
630 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
631 }
632
633 /**
634 * Returns the global size, in bytes, of objects freed by the runtime between a
635 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
636 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 public static int getGlobalFreedSize() {
638 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
639 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800640
641 /**
642 * Clears the global size of objects freed.
643 * @see #getGlobalFreedSize()
644 */
645 public static void resetGlobalFreedSize() {
646 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
647 }
648
649 /**
650 * Returns the number of non-concurrent GC invocations between a
651 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
652 */
653 public static int getGlobalGcInvocationCount() {
654 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
655 }
656
657 /**
658 * Clears the count of non-concurrent GC invocations.
659 * @see #getGlobalGcInvocationCount()
660 */
661 public static void resetGlobalGcInvocationCount() {
662 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
663 }
664
665 /**
666 * Returns the number of classes successfully initialized (ie those that executed without
667 * throwing an exception) between a {@link #startAllocCounting() start} and
668 * {@link #stopAllocCounting() stop}.
669 */
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800670 public static int getGlobalClassInitCount() {
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800671 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
672 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800673
674 /**
675 * Clears the count of classes initialized.
676 * @see #getGlobalClassInitCount()
677 */
678 public static void resetGlobalClassInitCount() {
679 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
680 }
681
682 /**
683 * Returns the time spent successfully initializing classes between a
684 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
685 */
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800686 public static int getGlobalClassInitTime() {
687 /* cumulative elapsed time for class initialization, in usec */
688 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
689 }
Carl Shapirob5961982010-12-22 15:54:53 -0800690
691 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800692 * Clears the count of time spent initializing classes.
693 * @see #getGlobalClassInitTime()
694 */
695 public static void resetGlobalClassInitTime() {
696 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
697 }
698
699 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800700 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800701 * @deprecated This method is now obsolete.
702 */
703 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 public static int getGlobalExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800705 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 }
Carl Shapirob5961982010-12-22 15:54:53 -0800707
708 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800709 * This method exists for compatibility and has no effect.
710 * @deprecated This method is now obsolete.
711 */
712 @Deprecated
713 public static void resetGlobalExternalAllocSize() {}
714
715 /**
716 * This method exists for compatibility and has no effect.
717 * @deprecated This method is now obsolete.
718 */
719 @Deprecated
720 public static void resetGlobalExternalAllocCount() {}
721
722 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800723 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800724 * @deprecated This method is now obsolete.
725 */
726 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 public static int getGlobalExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800728 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 }
Carl Shapirob5961982010-12-22 15:54:53 -0800730
731 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800732 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800733 * @deprecated This method is now obsolete.
734 */
735 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 public static int getGlobalExternalFreedCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800737 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 }
Carl Shapirob5961982010-12-22 15:54:53 -0800739
740 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800741 * This method exists for compatibility and has no effect.
742 * @deprecated This method is now obsolete.
743 */
744 @Deprecated
745 public static void resetGlobalExternalFreedCount() {}
746
747 /**
748 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800749 * @deprecated This method is now obsolete.
750 */
751 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 public static int getGlobalExternalFreedSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800753 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 }
Carl Shapirob5961982010-12-22 15:54:53 -0800755
Ian Rogersfe067a42013-02-22 19:59:23 -0800756 /**
757 * This method exists for compatibility and has no effect.
758 * @deprecated This method is now obsolete.
759 */
760 @Deprecated
761 public static void resetGlobalExternalFreedSize() {}
762
763 /**
764 * Returns the thread-local count of objects allocated by the runtime between a
765 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
766 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 public static int getThreadAllocCount() {
768 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
769 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800770
771 /**
772 * Clears the thread-local count of objects allocated.
773 * @see #getThreadAllocCount()
774 */
775 public static void resetThreadAllocCount() {
776 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
777 }
778
779 /**
780 * Returns the thread-local size of objects allocated by the runtime between a
781 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
782 * @return The allocated size in bytes.
783 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 public static int getThreadAllocSize() {
785 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
786 }
Carl Shapirob5961982010-12-22 15:54:53 -0800787
788 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800789 * Clears the thread-local count of objects allocated.
790 * @see #getThreadAllocSize()
791 */
792 public static void resetThreadAllocSize() {
793 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
794 }
795
796 /**
797 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800798 * @deprecated This method is now obsolete.
799 */
800 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 public static int getThreadExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800802 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 }
Carl Shapirob5961982010-12-22 15:54:53 -0800804
805 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800806 * This method exists for compatibility and has no effect.
807 * @deprecated This method is now obsolete.
808 */
809 @Deprecated
810 public static void resetThreadExternalAllocCount() {}
811
812 /**
813 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800814 * @deprecated This method is now obsolete.
815 */
816 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 public static int getThreadExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800818 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 }
Carl Shapirob5961982010-12-22 15:54:53 -0800820
Carl Shapirob5961982010-12-22 15:54:53 -0800821 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800822 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800823 * @deprecated This method is now obsolete.
824 */
825 @Deprecated
826 public static void resetThreadExternalAllocSize() {}
827
Ian Rogersfe067a42013-02-22 19:59:23 -0800828 /**
829 * Returns the number of thread-local non-concurrent GC invocations between a
830 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
831 */
832 public static int getThreadGcInvocationCount() {
833 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
834 }
835
836 /**
837 * Clears the thread-local count of non-concurrent GC invocations.
838 * @see #getThreadGcInvocationCount()
839 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 public static void resetThreadGcInvocationCount() {
841 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
842 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800843
844 /**
845 * Clears all the global and thread-local memory allocation counters.
846 * @see #startAllocCounting()
847 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 public static void resetAllCounts() {
849 VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
850 }
851
852 /**
853 * Returns the size of the native heap.
854 * @return The size of the native heap in bytes.
855 */
856 public static native long getNativeHeapSize();
857
858 /**
859 * Returns the amount of allocated memory in the native heap.
860 * @return The allocated size in bytes.
861 */
862 public static native long getNativeHeapAllocatedSize();
863
864 /**
865 * Returns the amount of free memory in the native heap.
866 * @return The freed size in bytes.
867 */
868 public static native long getNativeHeapFreeSize();
869
870 /**
871 * Retrieves information about this processes memory usages. This information is broken down by
872 * how much is in use by dalivk, the native heap, and everything else.
873 */
874 public static native void getMemoryInfo(MemoryInfo memoryInfo);
875
876 /**
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700877 * Note: currently only works when the requested pid has the same UID
878 * as the caller.
879 * @hide
880 */
881 public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
882
883 /**
Dianne Hackbornb437e092011-08-05 17:50:29 -0700884 * Retrieves the PSS memory used by the process as given by the
885 * smaps.
886 */
887 public static native long getPss();
888
889 /**
890 * Retrieves the PSS memory used by the process as given by the
891 * smaps. @hide
892 */
893 public static native long getPss(int pid);
894
895 /**
Carl Shapiro11073832011-01-12 16:28:57 -0800896 * Establish an object allocation limit in the current thread.
Carl Shapiro7e942842011-01-12 17:17:45 -0800897 * This feature was never enabled in release builds. The
898 * allocation limits feature was removed in Honeycomb. This
899 * method exists for compatibility and always returns -1 and has
900 * no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 *
Carl Shapiro11073832011-01-12 16:28:57 -0800902 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 */
Carl Shapiro11073832011-01-12 16:28:57 -0800904 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 public static int setAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -0800906 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 }
908
909 /**
Carl Shapiro11073832011-01-12 16:28:57 -0800910 * Establish a global object allocation limit. This feature was
Carl Shapiro7e942842011-01-12 17:17:45 -0800911 * never enabled in release builds. The allocation limits feature
912 * was removed in Honeycomb. This method exists for compatibility
913 * and always returns -1 and has no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 *
Carl Shapiro11073832011-01-12 16:28:57 -0800915 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 */
Carl Shapiro11073832011-01-12 16:28:57 -0800917 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 public static int setGlobalAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -0800919 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 }
921
922 /**
923 * Dump a list of all currently loaded class to the log file.
924 *
925 * @param flags See constants above.
926 */
927 public static void printLoadedClasses(int flags) {
928 VMDebug.printLoadedClasses(flags);
929 }
930
931 /**
932 * Get the number of loaded classes.
933 * @return the number of loaded classes.
934 */
935 public static int getLoadedClassCount() {
936 return VMDebug.getLoadedClassCount();
937 }
938
939 /**
Andy McFadden824c5102010-07-09 16:26:57 -0700940 * Dump "hprof" data to the specified file. This may cause a GC.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 *
942 * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof").
943 * @throws UnsupportedOperationException if the VM was built without
944 * HPROF support.
945 * @throws IOException if an error occurs while opening or writing files.
946 */
947 public static void dumpHprofData(String fileName) throws IOException {
948 VMDebug.dumpHprofData(fileName);
949 }
950
951 /**
Andy McFadden824c5102010-07-09 16:26:57 -0700952 * Like dumpHprofData(String), but takes an already-opened
953 * FileDescriptor to which the trace is written. The file name is also
954 * supplied simply for logging. Makes a dup of the file descriptor.
955 *
956 * Primarily for use by the "am" shell command.
957 *
958 * @hide
959 */
960 public static void dumpHprofData(String fileName, FileDescriptor fd)
961 throws IOException {
962 VMDebug.dumpHprofData(fileName, fd);
963 }
964
965 /**
966 * Collect "hprof" and send it to DDMS. This may cause a GC.
Andy McFadden07a96612010-01-28 16:54:37 -0800967 *
968 * @throws UnsupportedOperationException if the VM was built without
969 * HPROF support.
Andy McFadden07a96612010-01-28 16:54:37 -0800970 * @hide
971 */
972 public static void dumpHprofDataDdms() {
973 VMDebug.dumpHprofDataDdms();
974 }
975
976 /**
Andy McFadden06a6b552010-07-13 16:28:09 -0700977 * Writes native heap data to the specified file descriptor.
978 *
979 * @hide
980 */
981 public static native void dumpNativeHeap(FileDescriptor fd);
982
983 /**
Brian Carlstromc21550a2010-10-05 21:34:06 -0700984 * Returns a count of the extant instances of a class.
985 *
986 * @hide
987 */
988 public static long countInstancesOfClass(Class cls) {
Brian Carlstrom7495cfa2010-11-30 18:06:00 -0800989 return VMDebug.countInstancesOfClass(cls, true);
Brian Carlstromc21550a2010-10-05 21:34:06 -0700990 }
991
992 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 * Returns the number of sent transactions from this process.
994 * @return The number of sent transactions or -1 if it could not read t.
995 */
996 public static native int getBinderSentTransactions();
997
998 /**
999 * Returns the number of received transactions from the binder driver.
1000 * @return The number of received transactions or -1 if it could not read the stats.
1001 */
1002 public static native int getBinderReceivedTransactions();
1003
1004 /**
1005 * Returns the number of active local Binder objects that exist in the
1006 * current process.
1007 */
1008 public static final native int getBinderLocalObjectCount();
1009
1010 /**
1011 * Returns the number of references to remote proxy Binder objects that
1012 * exist in the current process.
1013 */
1014 public static final native int getBinderProxyObjectCount();
1015
1016 /**
1017 * Returns the number of death notification links to Binder objects that
1018 * exist in the current process.
1019 */
1020 public static final native int getBinderDeathObjectCount();
1021
1022 /**
Andy McFadden599c9182009-04-08 00:35:56 -07001023 * Primes the register map cache.
1024 *
1025 * Only works for classes in the bootstrap class loader. Does not
1026 * cause classes to be loaded if they're not already present.
1027 *
1028 * The classAndMethodDesc argument is a concatentation of the VM-internal
1029 * class descriptor, method name, and method descriptor. Examples:
1030 * Landroid/os/Looper;.loop:()V
1031 * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V
1032 *
1033 * @param classAndMethodDesc the method to prepare
1034 *
1035 * @hide
1036 */
1037 public static final boolean cacheRegisterMap(String classAndMethodDesc) {
1038 return VMDebug.cacheRegisterMap(classAndMethodDesc);
1039 }
1040
1041 /**
Andy McFaddenbfd6d482009-10-22 17:25:57 -07001042 * Dumps the contents of VM reference tables (e.g. JNI locals and
1043 * globals) to the log file.
1044 *
1045 * @hide
1046 */
1047 public static final void dumpReferenceTables() {
1048 VMDebug.dumpReferenceTables();
1049 }
1050
1051 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 * API for gathering and querying instruction counts.
1053 *
1054 * Example usage:
Chet Haase2970c492010-11-09 13:58:04 -08001055 * <pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 * Debug.InstructionCount icount = new Debug.InstructionCount();
1057 * icount.resetAndStart();
1058 * [... do lots of stuff ...]
1059 * if (icount.collect()) {
1060 * System.out.println("Total instructions executed: "
1061 * + icount.globalTotal());
1062 * System.out.println("Method invocations: "
1063 * + icount.globalMethodInvocations());
1064 * }
Chet Haase2970c492010-11-09 13:58:04 -08001065 * </pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 */
1067 public static class InstructionCount {
Dan Bornsteinb96f5892010-12-02 17:19:53 -08001068 private static final int NUM_INSTR =
1069 OpcodeInfo.MAXIMUM_PACKED_VALUE + 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070
1071 private int[] mCounts;
1072
1073 public InstructionCount() {
1074 mCounts = new int[NUM_INSTR];
1075 }
1076
1077 /**
1078 * Reset counters and ensure counts are running. Counts may
1079 * have already been running.
1080 *
1081 * @return true if counting was started
1082 */
1083 public boolean resetAndStart() {
1084 try {
1085 VMDebug.startInstructionCounting();
1086 VMDebug.resetInstructionCount();
1087 } catch (UnsupportedOperationException uoe) {
1088 return false;
1089 }
1090 return true;
1091 }
1092
1093 /**
1094 * Collect instruction counts. May or may not stop the
1095 * counting process.
1096 */
1097 public boolean collect() {
1098 try {
1099 VMDebug.stopInstructionCounting();
1100 VMDebug.getInstructionCount(mCounts);
1101 } catch (UnsupportedOperationException uoe) {
1102 return false;
1103 }
1104 return true;
1105 }
1106
1107 /**
1108 * Return the total number of instructions executed globally (i.e. in
1109 * all threads).
1110 */
1111 public int globalTotal() {
1112 int count = 0;
Dan Bornstein1d99b062010-11-30 12:26:52 -08001113
1114 for (int i = 0; i < NUM_INSTR; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 count += mCounts[i];
Dan Bornstein1d99b062010-11-30 12:26:52 -08001116 }
1117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 return count;
1119 }
1120
1121 /**
1122 * Return the total number of method-invocation instructions
1123 * executed globally.
1124 */
1125 public int globalMethodInvocations() {
1126 int count = 0;
1127
Dan Bornstein1d99b062010-11-30 12:26:52 -08001128 for (int i = 0; i < NUM_INSTR; i++) {
1129 if (OpcodeInfo.isInvoke(i)) {
1130 count += mCounts[i];
1131 }
1132 }
1133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001134 return count;
1135 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001136 }
1137
Dave Bort1ce5bd32009-04-22 17:36:56 -07001138 /**
1139 * A Map of typed debug properties.
1140 */
1141 private static final TypedProperties debugProperties;
1142
1143 /*
1144 * Load the debug properties from the standard files into debugProperties.
1145 */
1146 static {
Joe Onorato43a17652011-04-06 19:22:23 -07001147 if (false) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001148 final String TAG = "DebugProperties";
1149 final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" };
1150 final TypedProperties tp = new TypedProperties();
1151
1152 // Read the properties from each of the files, if present.
Dave Borte9bfd9b2009-05-04 14:35:23 -07001153 for (String file : files) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001154 Reader r;
1155 try {
1156 r = new FileReader(file);
1157 } catch (FileNotFoundException ex) {
1158 // It's ok if a file is missing.
1159 continue;
1160 }
1161
Dave Bort1ce5bd32009-04-22 17:36:56 -07001162 try {
1163 tp.load(r);
Dave Borte9bfd9b2009-05-04 14:35:23 -07001164 } catch (Exception ex) {
1165 throw new RuntimeException("Problem loading " + file, ex);
1166 } finally {
1167 try {
1168 r.close();
1169 } catch (IOException ex) {
1170 // Ignore this error.
1171 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001172 }
1173 }
1174
1175 debugProperties = tp.isEmpty() ? null : tp;
1176 } else {
1177 debugProperties = null;
1178 }
1179 }
1180
1181
1182 /**
1183 * Returns true if the type of the field matches the specified class.
1184 * Handles the case where the class is, e.g., java.lang.Boolean, but
1185 * the field is of the primitive "boolean" type. Also handles all of
1186 * the java.lang.Number subclasses.
1187 */
1188 private static boolean fieldTypeMatches(Field field, Class<?> cl) {
1189 Class<?> fieldClass = field.getType();
1190 if (fieldClass == cl) {
1191 return true;
1192 }
1193 Field primitiveTypeField;
1194 try {
1195 /* All of the classes we care about (Boolean, Integer, etc.)
1196 * have a Class field called "TYPE" that points to the corresponding
1197 * primitive class.
1198 */
1199 primitiveTypeField = cl.getField("TYPE");
1200 } catch (NoSuchFieldException ex) {
1201 return false;
1202 }
1203 try {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001204 return fieldClass == (Class<?>) primitiveTypeField.get(null);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001205 } catch (IllegalAccessException ex) {
1206 return false;
1207 }
1208 }
1209
1210
1211 /**
1212 * Looks up the property that corresponds to the field, and sets the field's value
1213 * if the types match.
1214 */
Dave Borte9bfd9b2009-05-04 14:35:23 -07001215 private static void modifyFieldIfSet(final Field field, final TypedProperties properties,
1216 final String propertyName) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001217 if (field.getType() == java.lang.String.class) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001218 int stringInfo = properties.getStringInfo(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001219 switch (stringInfo) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001220 case TypedProperties.STRING_SET:
1221 // Handle as usual below.
1222 break;
1223 case TypedProperties.STRING_NULL:
1224 try {
1225 field.set(null, null); // null object for static fields; null string
1226 } catch (IllegalAccessException ex) {
1227 throw new IllegalArgumentException(
1228 "Cannot set field for " + propertyName, ex);
1229 }
1230 return;
1231 case TypedProperties.STRING_NOT_SET:
1232 return;
1233 case TypedProperties.STRING_TYPE_MISMATCH:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001234 throw new IllegalArgumentException(
Dave Borte9bfd9b2009-05-04 14:35:23 -07001235 "Type of " + propertyName + " " +
1236 " does not match field type (" + field.getType() + ")");
1237 default:
1238 throw new IllegalStateException(
1239 "Unexpected getStringInfo(" + propertyName + ") return value " +
1240 stringInfo);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001241 }
1242 }
Dave Borte9bfd9b2009-05-04 14:35:23 -07001243 Object value = properties.get(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001244 if (value != null) {
1245 if (!fieldTypeMatches(field, value.getClass())) {
1246 throw new IllegalArgumentException(
1247 "Type of " + propertyName + " (" + value.getClass() + ") " +
1248 " does not match field type (" + field.getType() + ")");
1249 }
1250 try {
1251 field.set(null, value); // null object for static fields
1252 } catch (IllegalAccessException ex) {
1253 throw new IllegalArgumentException(
1254 "Cannot set field for " + propertyName, ex);
1255 }
1256 }
1257 }
1258
1259
1260 /**
Romain Guyc4b11a72009-05-13 15:46:37 -07001261 * Equivalent to <code>setFieldsOn(cl, false)</code>.
1262 *
1263 * @see #setFieldsOn(Class, boolean)
Romain Guyd4103d02009-05-14 12:24:21 -07001264 *
1265 * @hide
Romain Guyc4b11a72009-05-13 15:46:37 -07001266 */
1267 public static void setFieldsOn(Class<?> cl) {
1268 setFieldsOn(cl, false);
1269 }
1270
1271 /**
Dave Bort1ce5bd32009-04-22 17:36:56 -07001272 * Reflectively sets static fields of a class based on internal debugging
Joe Onorato43a17652011-04-06 19:22:23 -07001273 * properties. This method is a no-op if false is
Dave Bort1ce5bd32009-04-22 17:36:56 -07001274 * false.
1275 * <p>
Joe Onorato43a17652011-04-06 19:22:23 -07001276 * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: false will
Dave Bort1ce5bd32009-04-22 17:36:56 -07001277 * always be false in release builds. This API is typically only useful
1278 * for platform developers.
1279 * </p>
1280 * Class setup: define a class whose only fields are non-final, static
1281 * primitive types (except for "char") or Strings. In a static block
1282 * after the field definitions/initializations, pass the class to
Romain Guyc4b11a72009-05-13 15:46:37 -07001283 * this method, Debug.setFieldsOn(). Example:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001284 * <pre>
1285 * package com.example;
1286 *
1287 * import android.os.Debug;
1288 *
1289 * public class MyDebugVars {
1290 * public static String s = "a string";
1291 * public static String s2 = "second string";
1292 * public static String ns = null;
1293 * public static boolean b = false;
1294 * public static int i = 5;
Romain Guyc4b11a72009-05-13 15:46:37 -07001295 * @Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001296 * public static float f = 0.1f;
Romain Guyc4b11a72009-05-13 15:46:37 -07001297 * @@Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001298 * public static double d = 0.5d;
1299 *
1300 * // This MUST appear AFTER all fields are defined and initialized!
1301 * static {
Romain Guyc4b11a72009-05-13 15:46:37 -07001302 * // Sets all the fields
Dave Borte9bfd9b2009-05-04 14:35:23 -07001303 * Debug.setFieldsOn(MyDebugVars.class);
Christian Mehlmauer798e2d32010-06-17 18:24:07 +02001304 *
Romain Guyc4b11a72009-05-13 15:46:37 -07001305 * // Sets only the fields annotated with @Debug.DebugProperty
1306 * // Debug.setFieldsOn(MyDebugVars.class, true);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001307 * }
1308 * }
1309 * </pre>
Dave Borte9bfd9b2009-05-04 14:35:23 -07001310 * setFieldsOn() may override the value of any field in the class based
Dave Bort1ce5bd32009-04-22 17:36:56 -07001311 * on internal properties that are fixed at boot time.
1312 * <p>
1313 * These properties are only set during platform debugging, and are not
1314 * meant to be used as a general-purpose properties store.
1315 *
1316 * {@hide}
1317 *
1318 * @param cl The class to (possibly) modify
Romain Guyc4b11a72009-05-13 15:46:37 -07001319 * @param partial If false, sets all static fields, otherwise, only set
1320 * fields with the {@link android.os.Debug.DebugProperty}
1321 * annotation
Dave Bort1ce5bd32009-04-22 17:36:56 -07001322 * @throws IllegalArgumentException if any fields are final or non-static,
1323 * or if the type of the field does not match the type of
1324 * the internal debugging property value.
1325 */
Romain Guyc4b11a72009-05-13 15:46:37 -07001326 public static void setFieldsOn(Class<?> cl, boolean partial) {
Joe Onorato43a17652011-04-06 19:22:23 -07001327 if (false) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001328 if (debugProperties != null) {
1329 /* Only look for fields declared directly by the class,
1330 * so we don't mysteriously change static fields in superclasses.
1331 */
1332 for (Field field : cl.getDeclaredFields()) {
Romain Guyc4b11a72009-05-13 15:46:37 -07001333 if (!partial || field.getAnnotation(DebugProperty.class) != null) {
1334 final String propertyName = cl.getName() + "." + field.getName();
1335 boolean isStatic = Modifier.isStatic(field.getModifiers());
1336 boolean isFinal = Modifier.isFinal(field.getModifiers());
1337
1338 if (!isStatic || isFinal) {
1339 throw new IllegalArgumentException(propertyName +
1340 " must be static and non-final");
1341 }
1342 modifyFieldIfSet(field, debugProperties, propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001343 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001344 }
1345 }
1346 } else {
Dan Egnor3eda9792010-03-05 13:28:36 -08001347 Log.wtf(TAG,
Dave Borte9bfd9b2009-05-04 14:35:23 -07001348 "setFieldsOn(" + (cl == null ? "null" : cl.getName()) +
Dave Bort1ce5bd32009-04-22 17:36:56 -07001349 ") called in non-DEBUG build");
1350 }
1351 }
Romain Guyc4b11a72009-05-13 15:46:37 -07001352
1353 /**
1354 * Annotation to put on fields you want to set with
1355 * {@link Debug#setFieldsOn(Class, boolean)}.
1356 *
1357 * @hide
1358 */
1359 @Target({ ElementType.FIELD })
1360 @Retention(RetentionPolicy.RUNTIME)
1361 public @interface DebugProperty {
1362 }
Dan Egnor3eda9792010-03-05 13:28:36 -08001363
1364 /**
1365 * Get a debugging dump of a system service by name.
1366 *
1367 * <p>Most services require the caller to hold android.permission.DUMP.
1368 *
1369 * @param name of the service to dump
1370 * @param fd to write dump output to (usually an output log file)
1371 * @param args to pass to the service's dump method, may be null
1372 * @return true if the service was dumped successfully, false if
1373 * the service could not be found or had an error while dumping
1374 */
1375 public static boolean dumpService(String name, FileDescriptor fd, String[] args) {
1376 IBinder service = ServiceManager.getService(name);
1377 if (service == null) {
1378 Log.e(TAG, "Can't find service to dump: " + name);
1379 return false;
1380 }
1381
1382 try {
1383 service.dump(fd, args);
1384 return true;
1385 } catch (RemoteException e) {
1386 Log.e(TAG, "Can't dump service: " + name, e);
1387 return false;
1388 }
1389 }
Craig Mautnera51a9562012-04-17 17:05:26 -07001390
1391 /**
Dianne Hackbornf72467a2012-06-08 17:23:59 -07001392 * Have the stack traces of the given native process dumped to the
1393 * specified file. Will be appended to the file.
1394 * @hide
1395 */
1396 public static native void dumpNativeBacktraceToFile(int pid, String file);
1397
1398 /**
Craig Mautnera51a9562012-04-17 17:05:26 -07001399 * Return a String describing the calling method and location at a particular stack depth.
1400 * @param callStack the Thread stack
1401 * @param depth the depth of stack to return information for.
1402 * @return the String describing the caller at that depth.
1403 */
1404 private static String getCaller(StackTraceElement callStack[], int depth) {
1405 // callStack[4] is the caller of the method that called getCallers()
1406 if (4 + depth >= callStack.length) {
1407 return "<bottom of call stack>";
1408 }
1409 StackTraceElement caller = callStack[4 + depth];
1410 return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber();
1411 }
1412
1413 /**
1414 * Return a string consisting of methods and locations at multiple call stack levels.
1415 * @param depth the number of levels to return, starting with the immediate caller.
1416 * @return a string describing the call stack.
1417 * {@hide}
1418 */
1419 public static String getCallers(final int depth) {
1420 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
1421 StringBuffer sb = new StringBuffer();
1422 for (int i = 0; i < depth; i++) {
1423 sb.append(getCaller(callStack, i)).append(" ");
1424 }
1425 return sb.toString();
1426 }
1427
1428 /**
Dianne Hackbornef03a7f2012-10-29 18:46:52 -07001429 * Like {@link #getCallers(int)}, but each location is append to the string
1430 * as a new line with <var>linePrefix</var> in front of it.
1431 * @param depth the number of levels to return, starting with the immediate caller.
1432 * @param linePrefix prefix to put in front of each location.
1433 * @return a string describing the call stack.
1434 * {@hide}
1435 */
1436 public static String getCallers(final int depth, String linePrefix) {
1437 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
1438 StringBuffer sb = new StringBuffer();
1439 for (int i = 0; i < depth; i++) {
1440 sb.append(linePrefix).append(getCaller(callStack, i)).append("\n");
1441 }
1442 return sb.toString();
1443 }
1444
1445 /**
Ian Rogersfe067a42013-02-22 19:59:23 -08001446 * @return a String describing the immediate caller of the calling method.
Craig Mautnera51a9562012-04-17 17:05:26 -07001447 * {@hide}
1448 */
1449 public static String getCaller() {
1450 return getCaller(Thread.currentThread().getStackTrace(), 0);
1451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452}