blob: 20a731e068dba2222c654975cfc5041e070bc2cc [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/**
48 * Provides various debugging functions for Android applications, including
49 * 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 =
98 Environment.getExternalStorageDirectory().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 */
133 public static final int NUM_OTHER_STATS = 9;
134
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) {
180 case 0: return "Cursor";
181 case 1: return "Ashmem";
182 case 2: return "Other dev";
183 case 3: return ".so mmap";
184 case 4: return ".jar mmap";
185 case 5: return ".apk mmap";
186 case 6: return ".ttf mmap";
187 case 7: return ".dex mmap";
188 case 8: return "Other mmap";
189 default: return "????";
190 }
191 }
192
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700193 public int describeContents() {
194 return 0;
195 }
196
197 public void writeToParcel(Parcel dest, int flags) {
198 dest.writeInt(dalvikPss);
199 dest.writeInt(dalvikPrivateDirty);
200 dest.writeInt(dalvikSharedDirty);
201 dest.writeInt(nativePss);
202 dest.writeInt(nativePrivateDirty);
203 dest.writeInt(nativeSharedDirty);
204 dest.writeInt(otherPss);
205 dest.writeInt(otherPrivateDirty);
206 dest.writeInt(otherSharedDirty);
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700207 dest.writeIntArray(otherStats);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700208 }
209
210 public void readFromParcel(Parcel source) {
211 dalvikPss = source.readInt();
212 dalvikPrivateDirty = source.readInt();
213 dalvikSharedDirty = source.readInt();
214 nativePss = source.readInt();
215 nativePrivateDirty = source.readInt();
216 nativeSharedDirty = source.readInt();
217 otherPss = source.readInt();
218 otherPrivateDirty = source.readInt();
219 otherSharedDirty = source.readInt();
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700220 otherStats = source.createIntArray();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700221 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200222
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700223 public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
224 public MemoryInfo createFromParcel(Parcel source) {
225 return new MemoryInfo(source);
226 }
227 public MemoryInfo[] newArray(int size) {
228 return new MemoryInfo[size];
229 }
230 };
231
232 private MemoryInfo(Parcel source) {
233 readFromParcel(source);
234 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 }
236
237
238 /**
239 * Wait until a debugger attaches. As soon as the debugger attaches,
240 * this returns, so you will need to place a breakpoint after the
241 * waitForDebugger() call if you want to start tracing immediately.
242 */
243 public static void waitForDebugger() {
244 if (!VMDebug.isDebuggingEnabled()) {
245 //System.out.println("debugging not enabled, not waiting");
246 return;
247 }
248 if (isDebuggerConnected())
249 return;
250
251 // if DDMS is listening, inform them of our plight
252 System.out.println("Sending WAIT chunk");
253 byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger"
254 Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1);
255 DdmServer.sendChunk(waitChunk);
256
257 mWaiting = true;
258 while (!isDebuggerConnected()) {
259 try { Thread.sleep(SPIN_DELAY); }
260 catch (InterruptedException ie) {}
261 }
262 mWaiting = false;
263
264 System.out.println("Debugger has connected");
265
266 /*
267 * There is no "ready to go" signal from the debugger, and we're
268 * not allowed to suspend ourselves -- the debugger expects us to
269 * be running happily, and gets confused if we aren't. We need to
270 * allow the debugger a chance to set breakpoints before we start
271 * running again.
272 *
273 * Sit and spin until the debugger has been idle for a short while.
274 */
275 while (true) {
276 long delta = VMDebug.lastDebuggerActivity();
277 if (delta < 0) {
278 System.out.println("debugger detached?");
279 break;
280 }
281
282 if (delta < MIN_DEBUGGER_IDLE) {
283 System.out.println("waiting for debugger to settle...");
284 try { Thread.sleep(SPIN_DELAY); }
285 catch (InterruptedException ie) {}
286 } else {
287 System.out.println("debugger has settled (" + delta + ")");
288 break;
289 }
290 }
291 }
292
293 /**
294 * Returns "true" if one or more threads is waiting for a debugger
295 * to attach.
296 */
297 public static boolean waitingForDebugger() {
298 return mWaiting;
299 }
300
301 /**
302 * Determine if a debugger is currently attached.
303 */
304 public static boolean isDebuggerConnected() {
305 return VMDebug.isDebuggerConnected();
306 }
307
308 /**
Andy McFaddene5772322010-01-22 07:23:31 -0800309 * Returns an array of strings that identify VM features. This is
310 * used by DDMS to determine what sorts of operations the VM can
311 * perform.
312 *
313 * @hide
314 */
315 public static String[] getVmFeatureList() {
316 return VMDebug.getVmFeatureList();
317 }
318
319 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 * Change the JDWP port.
321 *
322 * @deprecated no longer needed or useful
323 */
324 @Deprecated
325 public static void changeDebugPort(int port) {}
326
327 /**
328 * This is the pathname to the sysfs file that enables and disables
329 * tracing on the qemu emulator.
330 */
331 private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state";
332
333 /**
334 * Enable qemu tracing. For this to work requires running everything inside
335 * the qemu emulator; otherwise, this method will have no effect. The trace
336 * file is specified on the command line when the emulator is started. For
337 * example, the following command line <br />
338 * <code>emulator -trace foo</code><br />
339 * will start running the emulator and create a trace file named "foo". This
340 * method simply enables writing the trace records to the trace file.
341 *
342 * <p>
343 * The main differences between this and {@link #startMethodTracing()} are
344 * that tracing in the qemu emulator traces every cpu instruction of every
345 * process, including kernel code, so we have more complete information,
346 * including all context switches. We can also get more detailed information
347 * such as cache misses. The sequence of calls is determined by
348 * post-processing the instruction trace. The qemu tracing is also done
349 * without modifying the application or perturbing the timing of calls
350 * because no instrumentation is added to the application being traced.
351 * </p>
352 *
353 * <p>
354 * One limitation of using this method compared to using
355 * {@link #startMethodTracing()} on the real device is that the emulator
356 * does not model all of the real hardware effects such as memory and
357 * bus contention. The emulator also has a simple cache model and cannot
358 * capture all the complexities of a real cache.
359 * </p>
360 */
361 public static void startNativeTracing() {
362 // Open the sysfs file for writing and write "1" to it.
363 PrintWriter outStream = null;
364 try {
365 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
366 outStream = new PrintWriter(new OutputStreamWriter(fos));
367 outStream.println("1");
368 } catch (Exception e) {
369 } finally {
370 if (outStream != null)
371 outStream.close();
372 }
373
374 VMDebug.startEmulatorTracing();
375 }
376
377 /**
378 * Stop qemu tracing. See {@link #startNativeTracing()} to start tracing.
379 *
380 * <p>Tracing can be started and stopped as many times as desired. When
381 * the qemu emulator itself is stopped then the buffered trace records
382 * are flushed and written to the trace file. In fact, it is not necessary
383 * to call this method at all; simply killing qemu is sufficient. But
384 * starting and stopping a trace is useful for examining a specific
385 * region of code.</p>
386 */
387 public static void stopNativeTracing() {
388 VMDebug.stopEmulatorTracing();
389
390 // Open the sysfs file for writing and write "0" to it.
391 PrintWriter outStream = null;
392 try {
393 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
394 outStream = new PrintWriter(new OutputStreamWriter(fos));
395 outStream.println("0");
396 } catch (Exception e) {
397 // We could print an error message here but we probably want
398 // to quietly ignore errors if we are not running in the emulator.
399 } finally {
400 if (outStream != null)
401 outStream.close();
402 }
403 }
404
405 /**
406 * Enable "emulator traces", in which information about the current
407 * method is made available to the "emulator -trace" feature. There
408 * is no corresponding "disable" call -- this is intended for use by
409 * the framework when tracing should be turned on and left that way, so
410 * that traces captured with F9/F10 will include the necessary data.
411 *
412 * This puts the VM into "profile" mode, which has performance
413 * consequences.
414 *
415 * To temporarily enable tracing, use {@link #startNativeTracing()}.
416 */
417 public static void enableEmulatorTraceOutput() {
418 VMDebug.startEmulatorTracing();
419 }
420
421 /**
422 * Start method tracing with default log name and buffer size. See <a
423href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
424 * information about reading these files. Call stopMethodTracing() to stop
425 * tracing.
426 */
427 public static void startMethodTracing() {
428 VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0);
429 }
430
431 /**
432 * Start method tracing, specifying the trace log file name. The trace
433 * file will be put under "/sdcard" unless an absolute path is given.
434 * See <a
435 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
436 * information about reading trace files.
437 *
438 * @param traceName Name for the trace log file to create.
439 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
440 * If the files already exist, they will be truncated.
441 * If the trace file given does not end in ".trace", it will be appended for you.
442 */
443 public static void startMethodTracing(String traceName) {
444 startMethodTracing(traceName, 0, 0);
445 }
446
447 /**
448 * Start method tracing, specifying the trace log file name and the
449 * buffer size. The trace files will be put under "/sdcard" unless an
450 * absolute path is given. See <a
451 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
452 * information about reading trace files.
453 * @param traceName Name for the trace log file to create.
454 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
455 * If the files already exist, they will be truncated.
456 * If the trace file given does not end in ".trace", it will be appended for you.
457 *
458 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
459 */
460 public static void startMethodTracing(String traceName, int bufferSize) {
461 startMethodTracing(traceName, bufferSize, 0);
462 }
463
464 /**
465 * Start method tracing, specifying the trace log file name and the
466 * buffer size. The trace files will be put under "/sdcard" unless an
467 * absolute path is given. See <a
468 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
469 * information about reading trace files.
470 *
471 * <p>
472 * When method tracing is enabled, the VM will run more slowly than
473 * usual, so the timings from the trace files should only be considered
474 * in relative terms (e.g. was run #1 faster than run #2). The times
475 * for native methods will not change, so don't try to use this to
476 * compare the performance of interpreted and native implementations of the
477 * same method. As an alternative, consider using "native" tracing
478 * in the emulator via {@link #startNativeTracing()}.
479 * </p>
480 *
481 * @param traceName Name for the trace log file to create.
482 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
483 * If the files already exist, they will be truncated.
484 * If the trace file given does not end in ".trace", it will be appended for you.
485 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
486 */
487 public static void startMethodTracing(String traceName, int bufferSize,
488 int flags) {
489
490 String pathName = traceName;
491 if (pathName.charAt(0) != '/')
492 pathName = DEFAULT_TRACE_PATH_PREFIX + pathName;
493 if (!pathName.endsWith(DEFAULT_TRACE_EXTENSION))
494 pathName = pathName + DEFAULT_TRACE_EXTENSION;
495
496 VMDebug.startMethodTracing(pathName, bufferSize, flags);
497 }
498
499 /**
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700500 * Like startMethodTracing(String, int, int), but taking an already-opened
501 * FileDescriptor in which the trace is written. The file name is also
502 * supplied simply for logging. Makes a dup of the file descriptor.
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200503 *
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700504 * Not exposed in the SDK unless we are really comfortable with supporting
505 * this and find it would be useful.
506 * @hide
507 */
508 public static void startMethodTracing(String traceName, FileDescriptor fd,
509 int bufferSize, int flags) {
510 VMDebug.startMethodTracing(traceName, fd, bufferSize, flags);
511 }
512
513 /**
Andy McFadden72a20db0c2010-01-22 12:20:41 -0800514 * Starts method tracing without a backing file. When stopMethodTracing
515 * is called, the result is sent directly to DDMS. (If DDMS is not
516 * attached when tracing ends, the profiling data will be discarded.)
517 *
518 * @hide
519 */
520 public static void startMethodTracingDdms(int bufferSize, int flags) {
521 VMDebug.startMethodTracingDdms(bufferSize, flags);
522 }
523
524 /**
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700525 * Determine whether method tracing is currently active.
526 * @hide
527 */
528 public static boolean isMethodTracingActive() {
529 return VMDebug.isMethodTracingActive();
530 }
531
532 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 * Stop method tracing.
534 */
535 public static void stopMethodTracing() {
536 VMDebug.stopMethodTracing();
537 }
538
539 /**
540 * Get an indication of thread CPU usage. The value returned
541 * indicates the amount of time that the current thread has spent
542 * executing code or waiting for certain types of I/O.
543 *
544 * The time is expressed in nanoseconds, and is only meaningful
545 * when compared to the result from an earlier call. Note that
546 * nanosecond resolution does not imply nanosecond accuracy.
547 *
548 * On system which don't support this operation, the call returns -1.
549 */
550 public static long threadCpuTimeNanos() {
551 return VMDebug.threadCpuTimeNanos();
552 }
553
554 /**
Chet Haase2970c492010-11-09 13:58:04 -0800555 * Start counting the number and aggregate size of memory allocations.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 *
Chet Haase2970c492010-11-09 13:58:04 -0800557 * <p>The {@link #startAllocCounting() start} function resets the counts and enables counting.
558 * The {@link #stopAllocCounting() stop} function disables the counting so that the analysis
559 * code doesn't cause additional allocations. The various <code>get</code> functions return
560 * the specified value. And the various <code>reset</code> functions reset the specified
561 * count.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562 *
Chet Haase2970c492010-11-09 13:58:04 -0800563 * <p>Counts are kept for the system as a whole and for each thread.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 * The per-thread counts for threads other than the current thread
Chet Haase2970c492010-11-09 13:58:04 -0800565 * are not cleared by the "reset" or "start" calls.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 */
567 public static void startAllocCounting() {
568 VMDebug.startAllocCounting();
569 }
Chet Haase2970c492010-11-09 13:58:04 -0800570
571 /**
572 * Stop counting the number and aggregate size of memory allocations.
573 *
574 * @see #startAllocCounting()
575 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576 public static void stopAllocCounting() {
577 VMDebug.stopAllocCounting();
578 }
579
580 public static int getGlobalAllocCount() {
581 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
582 }
583 public static int getGlobalAllocSize() {
584 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
585 }
586 public static int getGlobalFreedCount() {
587 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
588 }
589 public static int getGlobalFreedSize() {
590 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
591 }
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800592 public static int getGlobalClassInitCount() {
593 /* number of classes that have been successfully initialized */
594 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
595 }
596 public static int getGlobalClassInitTime() {
597 /* cumulative elapsed time for class initialization, in usec */
598 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
599 }
Carl Shapirob5961982010-12-22 15:54:53 -0800600
601 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800602 * Returns the global count of external allocation requests. The
603 * external allocation tracking feature was removed in Honeycomb.
604 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800605 *
606 * @deprecated This method is now obsolete.
607 */
608 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609 public static int getGlobalExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800610 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800611 }
Carl Shapirob5961982010-12-22 15:54:53 -0800612
613 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800614 * Returns the global count of bytes externally allocated. The
615 * external allocation tracking feature was removed in Honeycomb.
616 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800617 *
618 * @deprecated This method is now obsolete.
619 */
620 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 public static int getGlobalExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800622 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 }
Carl Shapirob5961982010-12-22 15:54:53 -0800624
625 /**
626 * Returns the global count of freed external allocation requests.
Carl Shapiro7e942842011-01-12 17:17:45 -0800627 * The external allocation tracking feature was removed in
628 * Honeycomb. This method exists for compatibility and always
629 * returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800630 *
631 * @deprecated This method is now obsolete.
632 */
633 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 public static int getGlobalExternalFreedCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800635 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 }
Carl Shapirob5961982010-12-22 15:54:53 -0800637
638 /**
639 * Returns the global count of freed bytes from external
Carl Shapiro7e942842011-01-12 17:17:45 -0800640 * allocation requests. The external allocation tracking feature
641 * was removed in Honeycomb. This method exists for compatibility
642 * and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800643 *
644 * @deprecated This method is now obsolete.
645 */
646 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 public static int getGlobalExternalFreedSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800648 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 }
Carl Shapirob5961982010-12-22 15:54:53 -0800650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 public static int getGlobalGcInvocationCount() {
652 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
653 }
654 public static int getThreadAllocCount() {
655 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
656 }
657 public static int getThreadAllocSize() {
658 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
659 }
Carl Shapirob5961982010-12-22 15:54:53 -0800660
661 /**
662 * Returns the count of external allocation requests made by the
Carl Shapiro7e942842011-01-12 17:17:45 -0800663 * current thread. The external allocation tracking feature was
664 * removed in Honeycomb. This method exists for compatibility and
665 * always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800666 *
667 * @deprecated This method is now obsolete.
668 */
669 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 public static int getThreadExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800671 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 }
Carl Shapirob5961982010-12-22 15:54:53 -0800673
674 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800675 * Returns the global count of bytes externally allocated. The
676 * external allocation tracking feature was removed in Honeycomb.
677 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800678 *
679 * @deprecated This method is now obsolete.
680 */
681 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 public static int getThreadExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800683 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 }
Carl Shapirob5961982010-12-22 15:54:53 -0800685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 public static int getThreadGcInvocationCount() {
687 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
688 }
689
690 public static void resetGlobalAllocCount() {
691 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
692 }
693 public static void resetGlobalAllocSize() {
694 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
695 }
696 public static void resetGlobalFreedCount() {
697 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
698 }
699 public static void resetGlobalFreedSize() {
700 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
701 }
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800702 public static void resetGlobalClassInitCount() {
703 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
704 }
705 public static void resetGlobalClassInitTime() {
706 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
707 }
Carl Shapirob5961982010-12-22 15:54:53 -0800708
709 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800710 * Resets the global count of external allocation requests. The
711 * external allocation tracking feature was removed in Honeycomb.
712 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800713 *
714 * @deprecated This method is now obsolete.
715 */
716 @Deprecated
717 public static void resetGlobalExternalAllocCount() {}
718
719 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800720 * Resets the global count of bytes externally allocated. The
721 * external allocation tracking feature was removed in Honeycomb.
722 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800723 *
724 * @deprecated This method is now obsolete.
725 */
726 @Deprecated
727 public static void resetGlobalExternalAllocSize() {}
728
729 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800730 * Resets the global count of freed external allocations. The
731 * external allocation tracking feature was removed in Honeycomb.
732 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800733 *
734 * @deprecated This method is now obsolete.
735 */
736 @Deprecated
737 public static void resetGlobalExternalFreedCount() {}
738
739 /**
740 * Resets the global count counter of freed bytes from external
Carl Shapiro7e942842011-01-12 17:17:45 -0800741 * allocations. The external allocation tracking feature was
742 * removed in Honeycomb. This method exists for compatibility and
743 * has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800744 *
745 * @deprecated This method is now obsolete.
746 */
747 @Deprecated
748 public static void resetGlobalExternalFreedSize() {}
749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 public static void resetGlobalGcInvocationCount() {
751 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
752 }
753 public static void resetThreadAllocCount() {
754 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
755 }
756 public static void resetThreadAllocSize() {
757 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
758 }
Carl Shapirob5961982010-12-22 15:54:53 -0800759
760 /**
761 * Resets the count of external allocation requests made by the
Carl Shapiro7e942842011-01-12 17:17:45 -0800762 * current thread. The external allocation tracking feature was
763 * removed in Honeycomb. This method exists for compatibility and
764 * has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800765 *
766 * @deprecated This method is now obsolete.
767 */
768 @Deprecated
769 public static void resetThreadExternalAllocCount() {}
770
771 /**
772 * Resets the count of bytes externally allocated by the current
Carl Shapiro7e942842011-01-12 17:17:45 -0800773 * thread. The external allocation tracking feature was removed
774 * in Honeycomb. This method exists for compatibility and has no
775 * effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800776 *
777 * @deprecated This method is now obsolete.
778 */
779 @Deprecated
780 public static void resetThreadExternalAllocSize() {}
781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 public static void resetThreadGcInvocationCount() {
783 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
784 }
785 public static void resetAllCounts() {
786 VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
787 }
788
789 /**
790 * Returns the size of the native heap.
791 * @return The size of the native heap in bytes.
792 */
793 public static native long getNativeHeapSize();
794
795 /**
796 * Returns the amount of allocated memory in the native heap.
797 * @return The allocated size in bytes.
798 */
799 public static native long getNativeHeapAllocatedSize();
800
801 /**
802 * Returns the amount of free memory in the native heap.
803 * @return The freed size in bytes.
804 */
805 public static native long getNativeHeapFreeSize();
806
807 /**
808 * Retrieves information about this processes memory usages. This information is broken down by
809 * how much is in use by dalivk, the native heap, and everything else.
810 */
811 public static native void getMemoryInfo(MemoryInfo memoryInfo);
812
813 /**
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700814 * Note: currently only works when the requested pid has the same UID
815 * as the caller.
816 * @hide
817 */
818 public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
819
820 /**
Dianne Hackbornb437e092011-08-05 17:50:29 -0700821 * Retrieves the PSS memory used by the process as given by the
822 * smaps.
823 */
824 public static native long getPss();
825
826 /**
827 * Retrieves the PSS memory used by the process as given by the
828 * smaps. @hide
829 */
830 public static native long getPss(int pid);
831
832 /**
Carl Shapiro11073832011-01-12 16:28:57 -0800833 * Establish an object allocation limit in the current thread.
Carl Shapiro7e942842011-01-12 17:17:45 -0800834 * This feature was never enabled in release builds. The
835 * allocation limits feature was removed in Honeycomb. This
836 * method exists for compatibility and always returns -1 and has
837 * no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 *
Carl Shapiro11073832011-01-12 16:28:57 -0800839 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 */
Carl Shapiro11073832011-01-12 16:28:57 -0800841 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842 public static int setAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -0800843 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 }
845
846 /**
Carl Shapiro11073832011-01-12 16:28:57 -0800847 * Establish a global object allocation limit. This feature was
Carl Shapiro7e942842011-01-12 17:17:45 -0800848 * never enabled in release builds. The allocation limits feature
849 * was removed in Honeycomb. This method exists for compatibility
850 * and always returns -1 and has no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 *
Carl Shapiro11073832011-01-12 16:28:57 -0800852 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 */
Carl Shapiro11073832011-01-12 16:28:57 -0800854 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 public static int setGlobalAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -0800856 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857 }
858
859 /**
860 * Dump a list of all currently loaded class to the log file.
861 *
862 * @param flags See constants above.
863 */
864 public static void printLoadedClasses(int flags) {
865 VMDebug.printLoadedClasses(flags);
866 }
867
868 /**
869 * Get the number of loaded classes.
870 * @return the number of loaded classes.
871 */
872 public static int getLoadedClassCount() {
873 return VMDebug.getLoadedClassCount();
874 }
875
876 /**
Andy McFadden824c5102010-07-09 16:26:57 -0700877 * Dump "hprof" data to the specified file. This may cause a GC.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 *
879 * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof").
880 * @throws UnsupportedOperationException if the VM was built without
881 * HPROF support.
882 * @throws IOException if an error occurs while opening or writing files.
883 */
884 public static void dumpHprofData(String fileName) throws IOException {
885 VMDebug.dumpHprofData(fileName);
886 }
887
888 /**
Andy McFadden824c5102010-07-09 16:26:57 -0700889 * Like dumpHprofData(String), but takes an already-opened
890 * FileDescriptor to which the trace is written. The file name is also
891 * supplied simply for logging. Makes a dup of the file descriptor.
892 *
893 * Primarily for use by the "am" shell command.
894 *
895 * @hide
896 */
897 public static void dumpHprofData(String fileName, FileDescriptor fd)
898 throws IOException {
899 VMDebug.dumpHprofData(fileName, fd);
900 }
901
902 /**
903 * Collect "hprof" and send it to DDMS. This may cause a GC.
Andy McFadden07a96612010-01-28 16:54:37 -0800904 *
905 * @throws UnsupportedOperationException if the VM was built without
906 * HPROF support.
Andy McFadden07a96612010-01-28 16:54:37 -0800907 * @hide
908 */
909 public static void dumpHprofDataDdms() {
910 VMDebug.dumpHprofDataDdms();
911 }
912
913 /**
Andy McFadden06a6b552010-07-13 16:28:09 -0700914 * Writes native heap data to the specified file descriptor.
915 *
916 * @hide
917 */
918 public static native void dumpNativeHeap(FileDescriptor fd);
919
920 /**
Brian Carlstromc21550a2010-10-05 21:34:06 -0700921 * Returns a count of the extant instances of a class.
922 *
923 * @hide
924 */
925 public static long countInstancesOfClass(Class cls) {
Brian Carlstrom7495cfa2010-11-30 18:06:00 -0800926 return VMDebug.countInstancesOfClass(cls, true);
Brian Carlstromc21550a2010-10-05 21:34:06 -0700927 }
928
929 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 * Returns the number of sent transactions from this process.
931 * @return The number of sent transactions or -1 if it could not read t.
932 */
933 public static native int getBinderSentTransactions();
934
935 /**
936 * Returns the number of received transactions from the binder driver.
937 * @return The number of received transactions or -1 if it could not read the stats.
938 */
939 public static native int getBinderReceivedTransactions();
940
941 /**
942 * Returns the number of active local Binder objects that exist in the
943 * current process.
944 */
945 public static final native int getBinderLocalObjectCount();
946
947 /**
948 * Returns the number of references to remote proxy Binder objects that
949 * exist in the current process.
950 */
951 public static final native int getBinderProxyObjectCount();
952
953 /**
954 * Returns the number of death notification links to Binder objects that
955 * exist in the current process.
956 */
957 public static final native int getBinderDeathObjectCount();
958
959 /**
Andy McFadden599c9182009-04-08 00:35:56 -0700960 * Primes the register map cache.
961 *
962 * Only works for classes in the bootstrap class loader. Does not
963 * cause classes to be loaded if they're not already present.
964 *
965 * The classAndMethodDesc argument is a concatentation of the VM-internal
966 * class descriptor, method name, and method descriptor. Examples:
967 * Landroid/os/Looper;.loop:()V
968 * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V
969 *
970 * @param classAndMethodDesc the method to prepare
971 *
972 * @hide
973 */
974 public static final boolean cacheRegisterMap(String classAndMethodDesc) {
975 return VMDebug.cacheRegisterMap(classAndMethodDesc);
976 }
977
978 /**
Andy McFaddenbfd6d482009-10-22 17:25:57 -0700979 * Dumps the contents of VM reference tables (e.g. JNI locals and
980 * globals) to the log file.
981 *
982 * @hide
983 */
984 public static final void dumpReferenceTables() {
985 VMDebug.dumpReferenceTables();
986 }
987
988 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 * API for gathering and querying instruction counts.
990 *
991 * Example usage:
Chet Haase2970c492010-11-09 13:58:04 -0800992 * <pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 * Debug.InstructionCount icount = new Debug.InstructionCount();
994 * icount.resetAndStart();
995 * [... do lots of stuff ...]
996 * if (icount.collect()) {
997 * System.out.println("Total instructions executed: "
998 * + icount.globalTotal());
999 * System.out.println("Method invocations: "
1000 * + icount.globalMethodInvocations());
1001 * }
Chet Haase2970c492010-11-09 13:58:04 -08001002 * </pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 */
1004 public static class InstructionCount {
Dan Bornsteinb96f5892010-12-02 17:19:53 -08001005 private static final int NUM_INSTR =
1006 OpcodeInfo.MAXIMUM_PACKED_VALUE + 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007
1008 private int[] mCounts;
1009
1010 public InstructionCount() {
1011 mCounts = new int[NUM_INSTR];
1012 }
1013
1014 /**
1015 * Reset counters and ensure counts are running. Counts may
1016 * have already been running.
1017 *
1018 * @return true if counting was started
1019 */
1020 public boolean resetAndStart() {
1021 try {
1022 VMDebug.startInstructionCounting();
1023 VMDebug.resetInstructionCount();
1024 } catch (UnsupportedOperationException uoe) {
1025 return false;
1026 }
1027 return true;
1028 }
1029
1030 /**
1031 * Collect instruction counts. May or may not stop the
1032 * counting process.
1033 */
1034 public boolean collect() {
1035 try {
1036 VMDebug.stopInstructionCounting();
1037 VMDebug.getInstructionCount(mCounts);
1038 } catch (UnsupportedOperationException uoe) {
1039 return false;
1040 }
1041 return true;
1042 }
1043
1044 /**
1045 * Return the total number of instructions executed globally (i.e. in
1046 * all threads).
1047 */
1048 public int globalTotal() {
1049 int count = 0;
Dan Bornstein1d99b062010-11-30 12:26:52 -08001050
1051 for (int i = 0; i < NUM_INSTR; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 count += mCounts[i];
Dan Bornstein1d99b062010-11-30 12:26:52 -08001053 }
1054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 return count;
1056 }
1057
1058 /**
1059 * Return the total number of method-invocation instructions
1060 * executed globally.
1061 */
1062 public int globalMethodInvocations() {
1063 int count = 0;
1064
Dan Bornstein1d99b062010-11-30 12:26:52 -08001065 for (int i = 0; i < NUM_INSTR; i++) {
1066 if (OpcodeInfo.isInvoke(i)) {
1067 count += mCounts[i];
1068 }
1069 }
1070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 return count;
1072 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001073 }
1074
Dave Bort1ce5bd32009-04-22 17:36:56 -07001075 /**
1076 * A Map of typed debug properties.
1077 */
1078 private static final TypedProperties debugProperties;
1079
1080 /*
1081 * Load the debug properties from the standard files into debugProperties.
1082 */
1083 static {
Joe Onorato43a17652011-04-06 19:22:23 -07001084 if (false) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001085 final String TAG = "DebugProperties";
1086 final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" };
1087 final TypedProperties tp = new TypedProperties();
1088
1089 // Read the properties from each of the files, if present.
Dave Borte9bfd9b2009-05-04 14:35:23 -07001090 for (String file : files) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001091 Reader r;
1092 try {
1093 r = new FileReader(file);
1094 } catch (FileNotFoundException ex) {
1095 // It's ok if a file is missing.
1096 continue;
1097 }
1098
Dave Bort1ce5bd32009-04-22 17:36:56 -07001099 try {
1100 tp.load(r);
Dave Borte9bfd9b2009-05-04 14:35:23 -07001101 } catch (Exception ex) {
1102 throw new RuntimeException("Problem loading " + file, ex);
1103 } finally {
1104 try {
1105 r.close();
1106 } catch (IOException ex) {
1107 // Ignore this error.
1108 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001109 }
1110 }
1111
1112 debugProperties = tp.isEmpty() ? null : tp;
1113 } else {
1114 debugProperties = null;
1115 }
1116 }
1117
1118
1119 /**
1120 * Returns true if the type of the field matches the specified class.
1121 * Handles the case where the class is, e.g., java.lang.Boolean, but
1122 * the field is of the primitive "boolean" type. Also handles all of
1123 * the java.lang.Number subclasses.
1124 */
1125 private static boolean fieldTypeMatches(Field field, Class<?> cl) {
1126 Class<?> fieldClass = field.getType();
1127 if (fieldClass == cl) {
1128 return true;
1129 }
1130 Field primitiveTypeField;
1131 try {
1132 /* All of the classes we care about (Boolean, Integer, etc.)
1133 * have a Class field called "TYPE" that points to the corresponding
1134 * primitive class.
1135 */
1136 primitiveTypeField = cl.getField("TYPE");
1137 } catch (NoSuchFieldException ex) {
1138 return false;
1139 }
1140 try {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001141 return fieldClass == (Class<?>) primitiveTypeField.get(null);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001142 } catch (IllegalAccessException ex) {
1143 return false;
1144 }
1145 }
1146
1147
1148 /**
1149 * Looks up the property that corresponds to the field, and sets the field's value
1150 * if the types match.
1151 */
Dave Borte9bfd9b2009-05-04 14:35:23 -07001152 private static void modifyFieldIfSet(final Field field, final TypedProperties properties,
1153 final String propertyName) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001154 if (field.getType() == java.lang.String.class) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001155 int stringInfo = properties.getStringInfo(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001156 switch (stringInfo) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001157 case TypedProperties.STRING_SET:
1158 // Handle as usual below.
1159 break;
1160 case TypedProperties.STRING_NULL:
1161 try {
1162 field.set(null, null); // null object for static fields; null string
1163 } catch (IllegalAccessException ex) {
1164 throw new IllegalArgumentException(
1165 "Cannot set field for " + propertyName, ex);
1166 }
1167 return;
1168 case TypedProperties.STRING_NOT_SET:
1169 return;
1170 case TypedProperties.STRING_TYPE_MISMATCH:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001171 throw new IllegalArgumentException(
Dave Borte9bfd9b2009-05-04 14:35:23 -07001172 "Type of " + propertyName + " " +
1173 " does not match field type (" + field.getType() + ")");
1174 default:
1175 throw new IllegalStateException(
1176 "Unexpected getStringInfo(" + propertyName + ") return value " +
1177 stringInfo);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001178 }
1179 }
Dave Borte9bfd9b2009-05-04 14:35:23 -07001180 Object value = properties.get(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001181 if (value != null) {
1182 if (!fieldTypeMatches(field, value.getClass())) {
1183 throw new IllegalArgumentException(
1184 "Type of " + propertyName + " (" + value.getClass() + ") " +
1185 " does not match field type (" + field.getType() + ")");
1186 }
1187 try {
1188 field.set(null, value); // null object for static fields
1189 } catch (IllegalAccessException ex) {
1190 throw new IllegalArgumentException(
1191 "Cannot set field for " + propertyName, ex);
1192 }
1193 }
1194 }
1195
1196
1197 /**
Romain Guyc4b11a72009-05-13 15:46:37 -07001198 * Equivalent to <code>setFieldsOn(cl, false)</code>.
1199 *
1200 * @see #setFieldsOn(Class, boolean)
Romain Guyd4103d02009-05-14 12:24:21 -07001201 *
1202 * @hide
Romain Guyc4b11a72009-05-13 15:46:37 -07001203 */
1204 public static void setFieldsOn(Class<?> cl) {
1205 setFieldsOn(cl, false);
1206 }
1207
1208 /**
Dave Bort1ce5bd32009-04-22 17:36:56 -07001209 * Reflectively sets static fields of a class based on internal debugging
Joe Onorato43a17652011-04-06 19:22:23 -07001210 * properties. This method is a no-op if false is
Dave Bort1ce5bd32009-04-22 17:36:56 -07001211 * false.
1212 * <p>
Joe Onorato43a17652011-04-06 19:22:23 -07001213 * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: false will
Dave Bort1ce5bd32009-04-22 17:36:56 -07001214 * always be false in release builds. This API is typically only useful
1215 * for platform developers.
1216 * </p>
1217 * Class setup: define a class whose only fields are non-final, static
1218 * primitive types (except for "char") or Strings. In a static block
1219 * after the field definitions/initializations, pass the class to
Romain Guyc4b11a72009-05-13 15:46:37 -07001220 * this method, Debug.setFieldsOn(). Example:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001221 * <pre>
1222 * package com.example;
1223 *
1224 * import android.os.Debug;
1225 *
1226 * public class MyDebugVars {
1227 * public static String s = "a string";
1228 * public static String s2 = "second string";
1229 * public static String ns = null;
1230 * public static boolean b = false;
1231 * public static int i = 5;
Romain Guyc4b11a72009-05-13 15:46:37 -07001232 * @Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001233 * public static float f = 0.1f;
Romain Guyc4b11a72009-05-13 15:46:37 -07001234 * @@Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001235 * public static double d = 0.5d;
1236 *
1237 * // This MUST appear AFTER all fields are defined and initialized!
1238 * static {
Romain Guyc4b11a72009-05-13 15:46:37 -07001239 * // Sets all the fields
Dave Borte9bfd9b2009-05-04 14:35:23 -07001240 * Debug.setFieldsOn(MyDebugVars.class);
Christian Mehlmauer798e2d32010-06-17 18:24:07 +02001241 *
Romain Guyc4b11a72009-05-13 15:46:37 -07001242 * // Sets only the fields annotated with @Debug.DebugProperty
1243 * // Debug.setFieldsOn(MyDebugVars.class, true);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001244 * }
1245 * }
1246 * </pre>
Dave Borte9bfd9b2009-05-04 14:35:23 -07001247 * setFieldsOn() may override the value of any field in the class based
Dave Bort1ce5bd32009-04-22 17:36:56 -07001248 * on internal properties that are fixed at boot time.
1249 * <p>
1250 * These properties are only set during platform debugging, and are not
1251 * meant to be used as a general-purpose properties store.
1252 *
1253 * {@hide}
1254 *
1255 * @param cl The class to (possibly) modify
Romain Guyc4b11a72009-05-13 15:46:37 -07001256 * @param partial If false, sets all static fields, otherwise, only set
1257 * fields with the {@link android.os.Debug.DebugProperty}
1258 * annotation
Dave Bort1ce5bd32009-04-22 17:36:56 -07001259 * @throws IllegalArgumentException if any fields are final or non-static,
1260 * or if the type of the field does not match the type of
1261 * the internal debugging property value.
1262 */
Romain Guyc4b11a72009-05-13 15:46:37 -07001263 public static void setFieldsOn(Class<?> cl, boolean partial) {
Joe Onorato43a17652011-04-06 19:22:23 -07001264 if (false) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001265 if (debugProperties != null) {
1266 /* Only look for fields declared directly by the class,
1267 * so we don't mysteriously change static fields in superclasses.
1268 */
1269 for (Field field : cl.getDeclaredFields()) {
Romain Guyc4b11a72009-05-13 15:46:37 -07001270 if (!partial || field.getAnnotation(DebugProperty.class) != null) {
1271 final String propertyName = cl.getName() + "." + field.getName();
1272 boolean isStatic = Modifier.isStatic(field.getModifiers());
1273 boolean isFinal = Modifier.isFinal(field.getModifiers());
1274
1275 if (!isStatic || isFinal) {
1276 throw new IllegalArgumentException(propertyName +
1277 " must be static and non-final");
1278 }
1279 modifyFieldIfSet(field, debugProperties, propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001280 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001281 }
1282 }
1283 } else {
Dan Egnor3eda9792010-03-05 13:28:36 -08001284 Log.wtf(TAG,
Dave Borte9bfd9b2009-05-04 14:35:23 -07001285 "setFieldsOn(" + (cl == null ? "null" : cl.getName()) +
Dave Bort1ce5bd32009-04-22 17:36:56 -07001286 ") called in non-DEBUG build");
1287 }
1288 }
Romain Guyc4b11a72009-05-13 15:46:37 -07001289
1290 /**
1291 * Annotation to put on fields you want to set with
1292 * {@link Debug#setFieldsOn(Class, boolean)}.
1293 *
1294 * @hide
1295 */
1296 @Target({ ElementType.FIELD })
1297 @Retention(RetentionPolicy.RUNTIME)
1298 public @interface DebugProperty {
1299 }
Dan Egnor3eda9792010-03-05 13:28:36 -08001300
1301 /**
1302 * Get a debugging dump of a system service by name.
1303 *
1304 * <p>Most services require the caller to hold android.permission.DUMP.
1305 *
1306 * @param name of the service to dump
1307 * @param fd to write dump output to (usually an output log file)
1308 * @param args to pass to the service's dump method, may be null
1309 * @return true if the service was dumped successfully, false if
1310 * the service could not be found or had an error while dumping
1311 */
1312 public static boolean dumpService(String name, FileDescriptor fd, String[] args) {
1313 IBinder service = ServiceManager.getService(name);
1314 if (service == null) {
1315 Log.e(TAG, "Can't find service to dump: " + name);
1316 return false;
1317 }
1318
1319 try {
1320 service.dump(fd, args);
1321 return true;
1322 } catch (RemoteException e) {
1323 Log.e(TAG, "Can't dump service: " + name, e);
1324 return false;
1325 }
1326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327}