blob: 87aeccb887e2a00f0a76a8bccd13f1aa6549809d [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
21import android.util.Config;
22import android.util.Log;
23
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070024import java.io.FileDescriptor;
Dave Bort1ce5bd32009-04-22 17:36:56 -070025import java.io.FileNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import java.io.FileOutputStream;
Dave Bort1ce5bd32009-04-22 17:36:56 -070027import java.io.FileReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import java.io.IOException;
29import java.io.OutputStreamWriter;
30import java.io.PrintWriter;
Dave Bort1ce5bd32009-04-22 17:36:56 -070031import java.io.Reader;
32import java.lang.reflect.Field;
33import java.lang.reflect.Modifier;
Romain Guyc4b11a72009-05-13 15:46:37 -070034import java.lang.annotation.Target;
35import java.lang.annotation.ElementType;
36import java.lang.annotation.Retention;
37import java.lang.annotation.RetentionPolicy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038
39import org.apache.harmony.dalvik.ddmc.Chunk;
40import org.apache.harmony.dalvik.ddmc.ChunkHandler;
41import org.apache.harmony.dalvik.ddmc.DdmServer;
42
Dan Bornstein9f315542010-11-19 18:12:55 -080043import dalvik.bytecode.OpcodeInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import dalvik.bytecode.Opcodes;
45import dalvik.system.VMDebug;
46
47
48/**
49 * Provides various debugging functions for Android applications, including
50 * tracing and allocation counts.
51 * <p><strong>Logging Trace Files</strong></p>
52 * <p>Debug can create log files that give details about an application, such as
53 * a call stack and start/stop times for any running methods. See <a
54href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
55 * information about reading trace files. To start logging trace files, call one
56 * of the startMethodTracing() methods. To stop tracing, call
57 * {@link #stopMethodTracing()}.
58 */
59public final class Debug
60{
Dan Egnor3eda9792010-03-05 13:28:36 -080061 private static final String TAG = "Debug";
62
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 /**
64 * Flags for startMethodTracing(). These can be ORed together.
65 *
66 * TRACE_COUNT_ALLOCS adds the results from startAllocCounting to the
67 * trace key file.
68 */
69 public static final int TRACE_COUNT_ALLOCS = VMDebug.TRACE_COUNT_ALLOCS;
70
71 /**
72 * Flags for printLoadedClasses(). Default behavior is to only show
73 * the class name.
74 */
75 public static final int SHOW_FULL_DETAIL = 1;
76 public static final int SHOW_CLASSLOADER = (1 << 1);
77 public static final int SHOW_INITIALIZED = (1 << 2);
78
79 // set/cleared by waitForDebugger()
80 private static volatile boolean mWaiting = false;
81
82 private Debug() {}
83
84 /*
85 * How long to wait for the debugger to finish sending requests. I've
86 * seen this hit 800msec on the device while waiting for a response
87 * to travel over USB and get processed, so we take that and add
88 * half a second.
89 */
90 private static final int MIN_DEBUGGER_IDLE = 1300; // msec
91
92 /* how long to sleep when polling for activity */
93 private static final int SPIN_DELAY = 200; // msec
94
95 /**
96 * Default trace file path and file
97 */
Christian Mehlmauer798e2d32010-06-17 18:24:07 +020098 private static final String DEFAULT_TRACE_PATH_PREFIX =
99 Environment.getExternalStorageDirectory().getPath() + "/";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 private static final String DEFAULT_TRACE_BODY = "dmtrace";
101 private static final String DEFAULT_TRACE_EXTENSION = ".trace";
102 private static final String DEFAULT_TRACE_FILE_PATH =
103 DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
104 + DEFAULT_TRACE_EXTENSION;
105
106
107 /**
108 * This class is used to retrieved various statistics about the memory mappings for this
109 * process. The returns info broken down by dalvik, native, and other. All results are in kB.
110 */
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700111 public static class MemoryInfo implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 /** The proportional set size for dalvik. */
113 public int dalvikPss;
114 /** The private dirty pages used by dalvik. */
115 public int dalvikPrivateDirty;
116 /** The shared dirty pages used by dalvik. */
117 public int dalvikSharedDirty;
118
119 /** The proportional set size for the native heap. */
120 public int nativePss;
121 /** The private dirty pages used by the native heap. */
122 public int nativePrivateDirty;
123 /** The shared dirty pages used by the native heap. */
124 public int nativeSharedDirty;
125
126 /** The proportional set size for everything else. */
127 public int otherPss;
128 /** The private dirty pages used by everything else. */
129 public int otherPrivateDirty;
130 /** The shared dirty pages used by everything else. */
131 public int otherSharedDirty;
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200132
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700133 public MemoryInfo() {
134 }
135
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700136 /**
137 * Return total PSS memory usage in kB.
138 */
139 public int getTotalPss() {
140 return dalvikPss + nativePss + otherPss;
141 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200142
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700143 /**
144 * Return total private dirty memory usage in kB.
145 */
146 public int getTotalPrivateDirty() {
147 return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty;
148 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200149
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700150 /**
151 * Return total shared dirty memory usage in kB.
152 */
153 public int getTotalSharedDirty() {
154 return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty;
155 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200156
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700157 public int describeContents() {
158 return 0;
159 }
160
161 public void writeToParcel(Parcel dest, int flags) {
162 dest.writeInt(dalvikPss);
163 dest.writeInt(dalvikPrivateDirty);
164 dest.writeInt(dalvikSharedDirty);
165 dest.writeInt(nativePss);
166 dest.writeInt(nativePrivateDirty);
167 dest.writeInt(nativeSharedDirty);
168 dest.writeInt(otherPss);
169 dest.writeInt(otherPrivateDirty);
170 dest.writeInt(otherSharedDirty);
171 }
172
173 public void readFromParcel(Parcel source) {
174 dalvikPss = source.readInt();
175 dalvikPrivateDirty = source.readInt();
176 dalvikSharedDirty = source.readInt();
177 nativePss = source.readInt();
178 nativePrivateDirty = source.readInt();
179 nativeSharedDirty = source.readInt();
180 otherPss = source.readInt();
181 otherPrivateDirty = source.readInt();
182 otherSharedDirty = source.readInt();
183 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200184
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700185 public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
186 public MemoryInfo createFromParcel(Parcel source) {
187 return new MemoryInfo(source);
188 }
189 public MemoryInfo[] newArray(int size) {
190 return new MemoryInfo[size];
191 }
192 };
193
194 private MemoryInfo(Parcel source) {
195 readFromParcel(source);
196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 }
198
199
200 /**
201 * Wait until a debugger attaches. As soon as the debugger attaches,
202 * this returns, so you will need to place a breakpoint after the
203 * waitForDebugger() call if you want to start tracing immediately.
204 */
205 public static void waitForDebugger() {
206 if (!VMDebug.isDebuggingEnabled()) {
207 //System.out.println("debugging not enabled, not waiting");
208 return;
209 }
210 if (isDebuggerConnected())
211 return;
212
213 // if DDMS is listening, inform them of our plight
214 System.out.println("Sending WAIT chunk");
215 byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger"
216 Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1);
217 DdmServer.sendChunk(waitChunk);
218
219 mWaiting = true;
220 while (!isDebuggerConnected()) {
221 try { Thread.sleep(SPIN_DELAY); }
222 catch (InterruptedException ie) {}
223 }
224 mWaiting = false;
225
226 System.out.println("Debugger has connected");
227
228 /*
229 * There is no "ready to go" signal from the debugger, and we're
230 * not allowed to suspend ourselves -- the debugger expects us to
231 * be running happily, and gets confused if we aren't. We need to
232 * allow the debugger a chance to set breakpoints before we start
233 * running again.
234 *
235 * Sit and spin until the debugger has been idle for a short while.
236 */
237 while (true) {
238 long delta = VMDebug.lastDebuggerActivity();
239 if (delta < 0) {
240 System.out.println("debugger detached?");
241 break;
242 }
243
244 if (delta < MIN_DEBUGGER_IDLE) {
245 System.out.println("waiting for debugger to settle...");
246 try { Thread.sleep(SPIN_DELAY); }
247 catch (InterruptedException ie) {}
248 } else {
249 System.out.println("debugger has settled (" + delta + ")");
250 break;
251 }
252 }
253 }
254
255 /**
256 * Returns "true" if one or more threads is waiting for a debugger
257 * to attach.
258 */
259 public static boolean waitingForDebugger() {
260 return mWaiting;
261 }
262
263 /**
264 * Determine if a debugger is currently attached.
265 */
266 public static boolean isDebuggerConnected() {
267 return VMDebug.isDebuggerConnected();
268 }
269
270 /**
Andy McFaddene5772322010-01-22 07:23:31 -0800271 * Returns an array of strings that identify VM features. This is
272 * used by DDMS to determine what sorts of operations the VM can
273 * perform.
274 *
275 * @hide
276 */
277 public static String[] getVmFeatureList() {
278 return VMDebug.getVmFeatureList();
279 }
280
281 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 * Change the JDWP port.
283 *
284 * @deprecated no longer needed or useful
285 */
286 @Deprecated
287 public static void changeDebugPort(int port) {}
288
289 /**
290 * This is the pathname to the sysfs file that enables and disables
291 * tracing on the qemu emulator.
292 */
293 private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state";
294
295 /**
296 * Enable qemu tracing. For this to work requires running everything inside
297 * the qemu emulator; otherwise, this method will have no effect. The trace
298 * file is specified on the command line when the emulator is started. For
299 * example, the following command line <br />
300 * <code>emulator -trace foo</code><br />
301 * will start running the emulator and create a trace file named "foo". This
302 * method simply enables writing the trace records to the trace file.
303 *
304 * <p>
305 * The main differences between this and {@link #startMethodTracing()} are
306 * that tracing in the qemu emulator traces every cpu instruction of every
307 * process, including kernel code, so we have more complete information,
308 * including all context switches. We can also get more detailed information
309 * such as cache misses. The sequence of calls is determined by
310 * post-processing the instruction trace. The qemu tracing is also done
311 * without modifying the application or perturbing the timing of calls
312 * because no instrumentation is added to the application being traced.
313 * </p>
314 *
315 * <p>
316 * One limitation of using this method compared to using
317 * {@link #startMethodTracing()} on the real device is that the emulator
318 * does not model all of the real hardware effects such as memory and
319 * bus contention. The emulator also has a simple cache model and cannot
320 * capture all the complexities of a real cache.
321 * </p>
322 */
323 public static void startNativeTracing() {
324 // Open the sysfs file for writing and write "1" to it.
325 PrintWriter outStream = null;
326 try {
327 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
328 outStream = new PrintWriter(new OutputStreamWriter(fos));
329 outStream.println("1");
330 } catch (Exception e) {
331 } finally {
332 if (outStream != null)
333 outStream.close();
334 }
335
336 VMDebug.startEmulatorTracing();
337 }
338
339 /**
340 * Stop qemu tracing. See {@link #startNativeTracing()} to start tracing.
341 *
342 * <p>Tracing can be started and stopped as many times as desired. When
343 * the qemu emulator itself is stopped then the buffered trace records
344 * are flushed and written to the trace file. In fact, it is not necessary
345 * to call this method at all; simply killing qemu is sufficient. But
346 * starting and stopping a trace is useful for examining a specific
347 * region of code.</p>
348 */
349 public static void stopNativeTracing() {
350 VMDebug.stopEmulatorTracing();
351
352 // Open the sysfs file for writing and write "0" to it.
353 PrintWriter outStream = null;
354 try {
355 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
356 outStream = new PrintWriter(new OutputStreamWriter(fos));
357 outStream.println("0");
358 } catch (Exception e) {
359 // We could print an error message here but we probably want
360 // to quietly ignore errors if we are not running in the emulator.
361 } finally {
362 if (outStream != null)
363 outStream.close();
364 }
365 }
366
367 /**
368 * Enable "emulator traces", in which information about the current
369 * method is made available to the "emulator -trace" feature. There
370 * is no corresponding "disable" call -- this is intended for use by
371 * the framework when tracing should be turned on and left that way, so
372 * that traces captured with F9/F10 will include the necessary data.
373 *
374 * This puts the VM into "profile" mode, which has performance
375 * consequences.
376 *
377 * To temporarily enable tracing, use {@link #startNativeTracing()}.
378 */
379 public static void enableEmulatorTraceOutput() {
380 VMDebug.startEmulatorTracing();
381 }
382
383 /**
384 * Start method tracing with default log name and buffer size. See <a
385href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
386 * information about reading these files. Call stopMethodTracing() to stop
387 * tracing.
388 */
389 public static void startMethodTracing() {
390 VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0);
391 }
392
393 /**
394 * Start method tracing, specifying the trace log file name. The trace
395 * file will be put under "/sdcard" unless an absolute path is given.
396 * See <a
397 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
398 * information about reading trace files.
399 *
400 * @param traceName Name for the trace log file to create.
401 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
402 * If the files already exist, they will be truncated.
403 * If the trace file given does not end in ".trace", it will be appended for you.
404 */
405 public static void startMethodTracing(String traceName) {
406 startMethodTracing(traceName, 0, 0);
407 }
408
409 /**
410 * Start method tracing, specifying the trace log file name and the
411 * buffer size. The trace files will be put under "/sdcard" unless an
412 * absolute path is given. See <a
413 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
414 * information about reading trace files.
415 * @param traceName Name for the trace log file to create.
416 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
417 * If the files already exist, they will be truncated.
418 * If the trace file given does not end in ".trace", it will be appended for you.
419 *
420 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
421 */
422 public static void startMethodTracing(String traceName, int bufferSize) {
423 startMethodTracing(traceName, bufferSize, 0);
424 }
425
426 /**
427 * Start method tracing, specifying the trace log file name and the
428 * buffer size. The trace files will be put under "/sdcard" unless an
429 * absolute path is given. See <a
430 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
431 * information about reading trace files.
432 *
433 * <p>
434 * When method tracing is enabled, the VM will run more slowly than
435 * usual, so the timings from the trace files should only be considered
436 * in relative terms (e.g. was run #1 faster than run #2). The times
437 * for native methods will not change, so don't try to use this to
438 * compare the performance of interpreted and native implementations of the
439 * same method. As an alternative, consider using "native" tracing
440 * in the emulator via {@link #startNativeTracing()}.
441 * </p>
442 *
443 * @param traceName Name for the trace log file to create.
444 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
445 * If the files already exist, they will be truncated.
446 * If the trace file given does not end in ".trace", it will be appended for you.
447 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
448 */
449 public static void startMethodTracing(String traceName, int bufferSize,
450 int flags) {
451
452 String pathName = traceName;
453 if (pathName.charAt(0) != '/')
454 pathName = DEFAULT_TRACE_PATH_PREFIX + pathName;
455 if (!pathName.endsWith(DEFAULT_TRACE_EXTENSION))
456 pathName = pathName + DEFAULT_TRACE_EXTENSION;
457
458 VMDebug.startMethodTracing(pathName, bufferSize, flags);
459 }
460
461 /**
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700462 * Like startMethodTracing(String, int, int), but taking an already-opened
463 * FileDescriptor in which the trace is written. The file name is also
464 * supplied simply for logging. Makes a dup of the file descriptor.
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200465 *
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700466 * Not exposed in the SDK unless we are really comfortable with supporting
467 * this and find it would be useful.
468 * @hide
469 */
470 public static void startMethodTracing(String traceName, FileDescriptor fd,
471 int bufferSize, int flags) {
472 VMDebug.startMethodTracing(traceName, fd, bufferSize, flags);
473 }
474
475 /**
Andy McFadden72a20db0c2010-01-22 12:20:41 -0800476 * Starts method tracing without a backing file. When stopMethodTracing
477 * is called, the result is sent directly to DDMS. (If DDMS is not
478 * attached when tracing ends, the profiling data will be discarded.)
479 *
480 * @hide
481 */
482 public static void startMethodTracingDdms(int bufferSize, int flags) {
483 VMDebug.startMethodTracingDdms(bufferSize, flags);
484 }
485
486 /**
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700487 * Determine whether method tracing is currently active.
488 * @hide
489 */
490 public static boolean isMethodTracingActive() {
491 return VMDebug.isMethodTracingActive();
492 }
493
494 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 * Stop method tracing.
496 */
497 public static void stopMethodTracing() {
498 VMDebug.stopMethodTracing();
499 }
500
501 /**
502 * Get an indication of thread CPU usage. The value returned
503 * indicates the amount of time that the current thread has spent
504 * executing code or waiting for certain types of I/O.
505 *
506 * The time is expressed in nanoseconds, and is only meaningful
507 * when compared to the result from an earlier call. Note that
508 * nanosecond resolution does not imply nanosecond accuracy.
509 *
510 * On system which don't support this operation, the call returns -1.
511 */
512 public static long threadCpuTimeNanos() {
513 return VMDebug.threadCpuTimeNanos();
514 }
515
516 /**
Chet Haase2970c492010-11-09 13:58:04 -0800517 * Start counting the number and aggregate size of memory allocations.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 *
Chet Haase2970c492010-11-09 13:58:04 -0800519 * <p>The {@link #startAllocCounting() start} function resets the counts and enables counting.
520 * The {@link #stopAllocCounting() stop} function disables the counting so that the analysis
521 * code doesn't cause additional allocations. The various <code>get</code> functions return
522 * the specified value. And the various <code>reset</code> functions reset the specified
523 * count.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 *
Chet Haase2970c492010-11-09 13:58:04 -0800525 * <p>Counts are kept for the system as a whole and for each thread.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 * The per-thread counts for threads other than the current thread
Chet Haase2970c492010-11-09 13:58:04 -0800527 * are not cleared by the "reset" or "start" calls.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 */
529 public static void startAllocCounting() {
530 VMDebug.startAllocCounting();
531 }
Chet Haase2970c492010-11-09 13:58:04 -0800532
533 /**
534 * Stop counting the number and aggregate size of memory allocations.
535 *
536 * @see #startAllocCounting()
537 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 public static void stopAllocCounting() {
539 VMDebug.stopAllocCounting();
540 }
541
542 public static int getGlobalAllocCount() {
543 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
544 }
545 public static int getGlobalAllocSize() {
546 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
547 }
548 public static int getGlobalFreedCount() {
549 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
550 }
551 public static int getGlobalFreedSize() {
552 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
553 }
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800554 public static int getGlobalClassInitCount() {
555 /* number of classes that have been successfully initialized */
556 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
557 }
558 public static int getGlobalClassInitTime() {
559 /* cumulative elapsed time for class initialization, in usec */
560 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
561 }
Carl Shapirob5961982010-12-22 15:54:53 -0800562
563 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800564 * Returns the global count of external allocation requests. The
565 * external allocation tracking feature was removed in Honeycomb.
566 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800567 *
568 * @deprecated This method is now obsolete.
569 */
570 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 public static int getGlobalExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800572 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 }
Carl Shapirob5961982010-12-22 15:54:53 -0800574
575 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800576 * Returns the global count of bytes externally allocated. The
577 * external allocation tracking feature was removed in Honeycomb.
578 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800579 *
580 * @deprecated This method is now obsolete.
581 */
582 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 public static int getGlobalExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800584 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 }
Carl Shapirob5961982010-12-22 15:54:53 -0800586
587 /**
588 * Returns the global count of freed external allocation requests.
Carl Shapiro7e942842011-01-12 17:17:45 -0800589 * The external allocation tracking feature was removed in
590 * Honeycomb. This method exists for compatibility and always
591 * returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800592 *
593 * @deprecated This method is now obsolete.
594 */
595 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 public static int getGlobalExternalFreedCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800597 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 }
Carl Shapirob5961982010-12-22 15:54:53 -0800599
600 /**
601 * Returns the global count of freed bytes from external
Carl Shapiro7e942842011-01-12 17:17:45 -0800602 * allocation requests. The external allocation tracking feature
603 * was removed in Honeycomb. This method exists for compatibility
604 * 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 getGlobalExternalFreedSize() {
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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 public static int getGlobalGcInvocationCount() {
614 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
615 }
616 public static int getThreadAllocCount() {
617 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
618 }
619 public static int getThreadAllocSize() {
620 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
621 }
Carl Shapirob5961982010-12-22 15:54:53 -0800622
623 /**
624 * Returns the count of external allocation requests made by the
Carl Shapiro7e942842011-01-12 17:17:45 -0800625 * current thread. The external allocation tracking feature was
626 * removed in Honeycomb. This method exists for compatibility and
627 * always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800628 *
629 * @deprecated This method is now obsolete.
630 */
631 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 public static int getThreadExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800633 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 }
Carl Shapirob5961982010-12-22 15:54:53 -0800635
636 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800637 * Returns the global count of bytes externally allocated. The
638 * external allocation tracking feature was removed in Honeycomb.
639 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800640 *
641 * @deprecated This method is now obsolete.
642 */
643 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 public static int getThreadExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800645 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 }
Carl Shapirob5961982010-12-22 15:54:53 -0800647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 public static int getThreadGcInvocationCount() {
649 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
650 }
651
652 public static void resetGlobalAllocCount() {
653 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
654 }
655 public static void resetGlobalAllocSize() {
656 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
657 }
658 public static void resetGlobalFreedCount() {
659 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
660 }
661 public static void resetGlobalFreedSize() {
662 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
663 }
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800664 public static void resetGlobalClassInitCount() {
665 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
666 }
667 public static void resetGlobalClassInitTime() {
668 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
669 }
Carl Shapirob5961982010-12-22 15:54:53 -0800670
671 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800672 * Resets the global count of external allocation requests. The
673 * external allocation tracking feature was removed in Honeycomb.
674 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800675 *
676 * @deprecated This method is now obsolete.
677 */
678 @Deprecated
679 public static void resetGlobalExternalAllocCount() {}
680
681 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800682 * Resets the global count of bytes externally allocated. The
683 * external allocation tracking feature was removed in Honeycomb.
684 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800685 *
686 * @deprecated This method is now obsolete.
687 */
688 @Deprecated
689 public static void resetGlobalExternalAllocSize() {}
690
691 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800692 * Resets the global count of freed external allocations. The
693 * external allocation tracking feature was removed in Honeycomb.
694 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800695 *
696 * @deprecated This method is now obsolete.
697 */
698 @Deprecated
699 public static void resetGlobalExternalFreedCount() {}
700
701 /**
702 * Resets the global count counter of freed bytes from external
Carl Shapiro7e942842011-01-12 17:17:45 -0800703 * allocations. The external allocation tracking feature was
704 * removed in Honeycomb. This method exists for compatibility and
705 * has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800706 *
707 * @deprecated This method is now obsolete.
708 */
709 @Deprecated
710 public static void resetGlobalExternalFreedSize() {}
711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 public static void resetGlobalGcInvocationCount() {
713 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
714 }
715 public static void resetThreadAllocCount() {
716 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
717 }
718 public static void resetThreadAllocSize() {
719 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
720 }
Carl Shapirob5961982010-12-22 15:54:53 -0800721
722 /**
723 * Resets the count of external allocation requests made by the
Carl Shapiro7e942842011-01-12 17:17:45 -0800724 * current thread. The external allocation tracking feature was
725 * removed in Honeycomb. This method exists for compatibility and
726 * has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800727 *
728 * @deprecated This method is now obsolete.
729 */
730 @Deprecated
731 public static void resetThreadExternalAllocCount() {}
732
733 /**
734 * Resets the count of bytes externally allocated by the current
Carl Shapiro7e942842011-01-12 17:17:45 -0800735 * thread. The external allocation tracking feature was removed
736 * in Honeycomb. This method exists for compatibility and has no
737 * effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800738 *
739 * @deprecated This method is now obsolete.
740 */
741 @Deprecated
742 public static void resetThreadExternalAllocSize() {}
743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 public static void resetThreadGcInvocationCount() {
745 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
746 }
747 public static void resetAllCounts() {
748 VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
749 }
750
751 /**
752 * Returns the size of the native heap.
753 * @return The size of the native heap in bytes.
754 */
755 public static native long getNativeHeapSize();
756
757 /**
758 * Returns the amount of allocated memory in the native heap.
759 * @return The allocated size in bytes.
760 */
761 public static native long getNativeHeapAllocatedSize();
762
763 /**
764 * Returns the amount of free memory in the native heap.
765 * @return The freed size in bytes.
766 */
767 public static native long getNativeHeapFreeSize();
768
769 /**
770 * Retrieves information about this processes memory usages. This information is broken down by
771 * how much is in use by dalivk, the native heap, and everything else.
772 */
773 public static native void getMemoryInfo(MemoryInfo memoryInfo);
774
775 /**
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700776 * Note: currently only works when the requested pid has the same UID
777 * as the caller.
778 * @hide
779 */
780 public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
781
782 /**
Carl Shapiro11073832011-01-12 16:28:57 -0800783 * Establish an object allocation limit in the current thread.
Carl Shapiro7e942842011-01-12 17:17:45 -0800784 * This feature was never enabled in release builds. The
785 * allocation limits feature was removed in Honeycomb. This
786 * method exists for compatibility and always returns -1 and has
787 * no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 *
Carl Shapiro11073832011-01-12 16:28:57 -0800789 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 */
Carl Shapiro11073832011-01-12 16:28:57 -0800791 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 public static int setAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -0800793 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 }
795
796 /**
Carl Shapiro11073832011-01-12 16:28:57 -0800797 * Establish a global object allocation limit. This feature was
Carl Shapiro7e942842011-01-12 17:17:45 -0800798 * never enabled in release builds. The allocation limits feature
799 * was removed in Honeycomb. This method exists for compatibility
800 * and always returns -1 and has no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 *
Carl Shapiro11073832011-01-12 16:28:57 -0800802 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 */
Carl Shapiro11073832011-01-12 16:28:57 -0800804 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 public static int setGlobalAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -0800806 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 }
808
809 /**
810 * Dump a list of all currently loaded class to the log file.
811 *
812 * @param flags See constants above.
813 */
814 public static void printLoadedClasses(int flags) {
815 VMDebug.printLoadedClasses(flags);
816 }
817
818 /**
819 * Get the number of loaded classes.
820 * @return the number of loaded classes.
821 */
822 public static int getLoadedClassCount() {
823 return VMDebug.getLoadedClassCount();
824 }
825
826 /**
Andy McFadden824c5102010-07-09 16:26:57 -0700827 * Dump "hprof" data to the specified file. This may cause a GC.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 *
829 * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof").
830 * @throws UnsupportedOperationException if the VM was built without
831 * HPROF support.
832 * @throws IOException if an error occurs while opening or writing files.
833 */
834 public static void dumpHprofData(String fileName) throws IOException {
835 VMDebug.dumpHprofData(fileName);
836 }
837
838 /**
Andy McFadden824c5102010-07-09 16:26:57 -0700839 * Like dumpHprofData(String), but takes an already-opened
840 * FileDescriptor to which the trace is written. The file name is also
841 * supplied simply for logging. Makes a dup of the file descriptor.
842 *
843 * Primarily for use by the "am" shell command.
844 *
845 * @hide
846 */
847 public static void dumpHprofData(String fileName, FileDescriptor fd)
848 throws IOException {
849 VMDebug.dumpHprofData(fileName, fd);
850 }
851
852 /**
853 * Collect "hprof" and send it to DDMS. This may cause a GC.
Andy McFadden07a96612010-01-28 16:54:37 -0800854 *
855 * @throws UnsupportedOperationException if the VM was built without
856 * HPROF support.
Andy McFadden07a96612010-01-28 16:54:37 -0800857 * @hide
858 */
859 public static void dumpHprofDataDdms() {
860 VMDebug.dumpHprofDataDdms();
861 }
862
863 /**
Andy McFadden06a6b552010-07-13 16:28:09 -0700864 * Writes native heap data to the specified file descriptor.
865 *
866 * @hide
867 */
868 public static native void dumpNativeHeap(FileDescriptor fd);
869
870 /**
Brian Carlstromc21550a2010-10-05 21:34:06 -0700871 * Returns a count of the extant instances of a class.
872 *
873 * @hide
874 */
875 public static long countInstancesOfClass(Class cls) {
Brian Carlstrom7495cfa2010-11-30 18:06:00 -0800876 return VMDebug.countInstancesOfClass(cls, true);
Brian Carlstromc21550a2010-10-05 21:34:06 -0700877 }
878
879 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 * Returns the number of sent transactions from this process.
881 * @return The number of sent transactions or -1 if it could not read t.
882 */
883 public static native int getBinderSentTransactions();
884
885 /**
886 * Returns the number of received transactions from the binder driver.
887 * @return The number of received transactions or -1 if it could not read the stats.
888 */
889 public static native int getBinderReceivedTransactions();
890
891 /**
892 * Returns the number of active local Binder objects that exist in the
893 * current process.
894 */
895 public static final native int getBinderLocalObjectCount();
896
897 /**
898 * Returns the number of references to remote proxy Binder objects that
899 * exist in the current process.
900 */
901 public static final native int getBinderProxyObjectCount();
902
903 /**
904 * Returns the number of death notification links to Binder objects that
905 * exist in the current process.
906 */
907 public static final native int getBinderDeathObjectCount();
908
909 /**
Andy McFadden599c9182009-04-08 00:35:56 -0700910 * Primes the register map cache.
911 *
912 * Only works for classes in the bootstrap class loader. Does not
913 * cause classes to be loaded if they're not already present.
914 *
915 * The classAndMethodDesc argument is a concatentation of the VM-internal
916 * class descriptor, method name, and method descriptor. Examples:
917 * Landroid/os/Looper;.loop:()V
918 * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V
919 *
920 * @param classAndMethodDesc the method to prepare
921 *
922 * @hide
923 */
924 public static final boolean cacheRegisterMap(String classAndMethodDesc) {
925 return VMDebug.cacheRegisterMap(classAndMethodDesc);
926 }
927
928 /**
Andy McFaddenbfd6d482009-10-22 17:25:57 -0700929 * Dumps the contents of VM reference tables (e.g. JNI locals and
930 * globals) to the log file.
931 *
932 * @hide
933 */
934 public static final void dumpReferenceTables() {
935 VMDebug.dumpReferenceTables();
936 }
937
938 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 * API for gathering and querying instruction counts.
940 *
941 * Example usage:
Chet Haase2970c492010-11-09 13:58:04 -0800942 * <pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943 * Debug.InstructionCount icount = new Debug.InstructionCount();
944 * icount.resetAndStart();
945 * [... do lots of stuff ...]
946 * if (icount.collect()) {
947 * System.out.println("Total instructions executed: "
948 * + icount.globalTotal());
949 * System.out.println("Method invocations: "
950 * + icount.globalMethodInvocations());
951 * }
Chet Haase2970c492010-11-09 13:58:04 -0800952 * </pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 */
954 public static class InstructionCount {
Dan Bornsteinb96f5892010-12-02 17:19:53 -0800955 private static final int NUM_INSTR =
956 OpcodeInfo.MAXIMUM_PACKED_VALUE + 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957
958 private int[] mCounts;
959
960 public InstructionCount() {
961 mCounts = new int[NUM_INSTR];
962 }
963
964 /**
965 * Reset counters and ensure counts are running. Counts may
966 * have already been running.
967 *
968 * @return true if counting was started
969 */
970 public boolean resetAndStart() {
971 try {
972 VMDebug.startInstructionCounting();
973 VMDebug.resetInstructionCount();
974 } catch (UnsupportedOperationException uoe) {
975 return false;
976 }
977 return true;
978 }
979
980 /**
981 * Collect instruction counts. May or may not stop the
982 * counting process.
983 */
984 public boolean collect() {
985 try {
986 VMDebug.stopInstructionCounting();
987 VMDebug.getInstructionCount(mCounts);
988 } catch (UnsupportedOperationException uoe) {
989 return false;
990 }
991 return true;
992 }
993
994 /**
995 * Return the total number of instructions executed globally (i.e. in
996 * all threads).
997 */
998 public int globalTotal() {
999 int count = 0;
Dan Bornstein1d99b062010-11-30 12:26:52 -08001000
1001 for (int i = 0; i < NUM_INSTR; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 count += mCounts[i];
Dan Bornstein1d99b062010-11-30 12:26:52 -08001003 }
1004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 return count;
1006 }
1007
1008 /**
1009 * Return the total number of method-invocation instructions
1010 * executed globally.
1011 */
1012 public int globalMethodInvocations() {
1013 int count = 0;
1014
Dan Bornstein1d99b062010-11-30 12:26:52 -08001015 for (int i = 0; i < NUM_INSTR; i++) {
1016 if (OpcodeInfo.isInvoke(i)) {
1017 count += mCounts[i];
1018 }
1019 }
1020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 return count;
1022 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001023 }
1024
Dave Bort1ce5bd32009-04-22 17:36:56 -07001025 /**
1026 * A Map of typed debug properties.
1027 */
1028 private static final TypedProperties debugProperties;
1029
1030 /*
1031 * Load the debug properties from the standard files into debugProperties.
1032 */
1033 static {
1034 if (Config.DEBUG) {
1035 final String TAG = "DebugProperties";
1036 final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" };
1037 final TypedProperties tp = new TypedProperties();
1038
1039 // Read the properties from each of the files, if present.
Dave Borte9bfd9b2009-05-04 14:35:23 -07001040 for (String file : files) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001041 Reader r;
1042 try {
1043 r = new FileReader(file);
1044 } catch (FileNotFoundException ex) {
1045 // It's ok if a file is missing.
1046 continue;
1047 }
1048
Dave Bort1ce5bd32009-04-22 17:36:56 -07001049 try {
1050 tp.load(r);
Dave Borte9bfd9b2009-05-04 14:35:23 -07001051 } catch (Exception ex) {
1052 throw new RuntimeException("Problem loading " + file, ex);
1053 } finally {
1054 try {
1055 r.close();
1056 } catch (IOException ex) {
1057 // Ignore this error.
1058 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001059 }
1060 }
1061
1062 debugProperties = tp.isEmpty() ? null : tp;
1063 } else {
1064 debugProperties = null;
1065 }
1066 }
1067
1068
1069 /**
1070 * Returns true if the type of the field matches the specified class.
1071 * Handles the case where the class is, e.g., java.lang.Boolean, but
1072 * the field is of the primitive "boolean" type. Also handles all of
1073 * the java.lang.Number subclasses.
1074 */
1075 private static boolean fieldTypeMatches(Field field, Class<?> cl) {
1076 Class<?> fieldClass = field.getType();
1077 if (fieldClass == cl) {
1078 return true;
1079 }
1080 Field primitiveTypeField;
1081 try {
1082 /* All of the classes we care about (Boolean, Integer, etc.)
1083 * have a Class field called "TYPE" that points to the corresponding
1084 * primitive class.
1085 */
1086 primitiveTypeField = cl.getField("TYPE");
1087 } catch (NoSuchFieldException ex) {
1088 return false;
1089 }
1090 try {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001091 return fieldClass == (Class<?>) primitiveTypeField.get(null);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001092 } catch (IllegalAccessException ex) {
1093 return false;
1094 }
1095 }
1096
1097
1098 /**
1099 * Looks up the property that corresponds to the field, and sets the field's value
1100 * if the types match.
1101 */
Dave Borte9bfd9b2009-05-04 14:35:23 -07001102 private static void modifyFieldIfSet(final Field field, final TypedProperties properties,
1103 final String propertyName) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001104 if (field.getType() == java.lang.String.class) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001105 int stringInfo = properties.getStringInfo(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001106 switch (stringInfo) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001107 case TypedProperties.STRING_SET:
1108 // Handle as usual below.
1109 break;
1110 case TypedProperties.STRING_NULL:
1111 try {
1112 field.set(null, null); // null object for static fields; null string
1113 } catch (IllegalAccessException ex) {
1114 throw new IllegalArgumentException(
1115 "Cannot set field for " + propertyName, ex);
1116 }
1117 return;
1118 case TypedProperties.STRING_NOT_SET:
1119 return;
1120 case TypedProperties.STRING_TYPE_MISMATCH:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001121 throw new IllegalArgumentException(
Dave Borte9bfd9b2009-05-04 14:35:23 -07001122 "Type of " + propertyName + " " +
1123 " does not match field type (" + field.getType() + ")");
1124 default:
1125 throw new IllegalStateException(
1126 "Unexpected getStringInfo(" + propertyName + ") return value " +
1127 stringInfo);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001128 }
1129 }
Dave Borte9bfd9b2009-05-04 14:35:23 -07001130 Object value = properties.get(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001131 if (value != null) {
1132 if (!fieldTypeMatches(field, value.getClass())) {
1133 throw new IllegalArgumentException(
1134 "Type of " + propertyName + " (" + value.getClass() + ") " +
1135 " does not match field type (" + field.getType() + ")");
1136 }
1137 try {
1138 field.set(null, value); // null object for static fields
1139 } catch (IllegalAccessException ex) {
1140 throw new IllegalArgumentException(
1141 "Cannot set field for " + propertyName, ex);
1142 }
1143 }
1144 }
1145
1146
1147 /**
Romain Guyc4b11a72009-05-13 15:46:37 -07001148 * Equivalent to <code>setFieldsOn(cl, false)</code>.
1149 *
1150 * @see #setFieldsOn(Class, boolean)
Romain Guyd4103d02009-05-14 12:24:21 -07001151 *
1152 * @hide
Romain Guyc4b11a72009-05-13 15:46:37 -07001153 */
1154 public static void setFieldsOn(Class<?> cl) {
1155 setFieldsOn(cl, false);
1156 }
1157
1158 /**
Dave Bort1ce5bd32009-04-22 17:36:56 -07001159 * Reflectively sets static fields of a class based on internal debugging
1160 * properties. This method is a no-op if android.util.Config.DEBUG is
1161 * false.
1162 * <p>
1163 * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: Config.DEBUG will
1164 * always be false in release builds. This API is typically only useful
1165 * for platform developers.
1166 * </p>
1167 * Class setup: define a class whose only fields are non-final, static
1168 * primitive types (except for "char") or Strings. In a static block
1169 * after the field definitions/initializations, pass the class to
Romain Guyc4b11a72009-05-13 15:46:37 -07001170 * this method, Debug.setFieldsOn(). Example:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001171 * <pre>
1172 * package com.example;
1173 *
1174 * import android.os.Debug;
1175 *
1176 * public class MyDebugVars {
1177 * public static String s = "a string";
1178 * public static String s2 = "second string";
1179 * public static String ns = null;
1180 * public static boolean b = false;
1181 * public static int i = 5;
Romain Guyc4b11a72009-05-13 15:46:37 -07001182 * @Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001183 * public static float f = 0.1f;
Romain Guyc4b11a72009-05-13 15:46:37 -07001184 * @@Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001185 * public static double d = 0.5d;
1186 *
1187 * // This MUST appear AFTER all fields are defined and initialized!
1188 * static {
Romain Guyc4b11a72009-05-13 15:46:37 -07001189 * // Sets all the fields
Dave Borte9bfd9b2009-05-04 14:35:23 -07001190 * Debug.setFieldsOn(MyDebugVars.class);
Christian Mehlmauer798e2d32010-06-17 18:24:07 +02001191 *
Romain Guyc4b11a72009-05-13 15:46:37 -07001192 * // Sets only the fields annotated with @Debug.DebugProperty
1193 * // Debug.setFieldsOn(MyDebugVars.class, true);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001194 * }
1195 * }
1196 * </pre>
Dave Borte9bfd9b2009-05-04 14:35:23 -07001197 * setFieldsOn() may override the value of any field in the class based
Dave Bort1ce5bd32009-04-22 17:36:56 -07001198 * on internal properties that are fixed at boot time.
1199 * <p>
1200 * These properties are only set during platform debugging, and are not
1201 * meant to be used as a general-purpose properties store.
1202 *
1203 * {@hide}
1204 *
1205 * @param cl The class to (possibly) modify
Romain Guyc4b11a72009-05-13 15:46:37 -07001206 * @param partial If false, sets all static fields, otherwise, only set
1207 * fields with the {@link android.os.Debug.DebugProperty}
1208 * annotation
Dave Bort1ce5bd32009-04-22 17:36:56 -07001209 * @throws IllegalArgumentException if any fields are final or non-static,
1210 * or if the type of the field does not match the type of
1211 * the internal debugging property value.
1212 */
Romain Guyc4b11a72009-05-13 15:46:37 -07001213 public static void setFieldsOn(Class<?> cl, boolean partial) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001214 if (Config.DEBUG) {
1215 if (debugProperties != null) {
1216 /* Only look for fields declared directly by the class,
1217 * so we don't mysteriously change static fields in superclasses.
1218 */
1219 for (Field field : cl.getDeclaredFields()) {
Romain Guyc4b11a72009-05-13 15:46:37 -07001220 if (!partial || field.getAnnotation(DebugProperty.class) != null) {
1221 final String propertyName = cl.getName() + "." + field.getName();
1222 boolean isStatic = Modifier.isStatic(field.getModifiers());
1223 boolean isFinal = Modifier.isFinal(field.getModifiers());
1224
1225 if (!isStatic || isFinal) {
1226 throw new IllegalArgumentException(propertyName +
1227 " must be static and non-final");
1228 }
1229 modifyFieldIfSet(field, debugProperties, propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001230 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001231 }
1232 }
1233 } else {
Dan Egnor3eda9792010-03-05 13:28:36 -08001234 Log.wtf(TAG,
Dave Borte9bfd9b2009-05-04 14:35:23 -07001235 "setFieldsOn(" + (cl == null ? "null" : cl.getName()) +
Dave Bort1ce5bd32009-04-22 17:36:56 -07001236 ") called in non-DEBUG build");
1237 }
1238 }
Romain Guyc4b11a72009-05-13 15:46:37 -07001239
1240 /**
1241 * Annotation to put on fields you want to set with
1242 * {@link Debug#setFieldsOn(Class, boolean)}.
1243 *
1244 * @hide
1245 */
1246 @Target({ ElementType.FIELD })
1247 @Retention(RetentionPolicy.RUNTIME)
1248 public @interface DebugProperty {
1249 }
Dan Egnor3eda9792010-03-05 13:28:36 -08001250
1251 /**
1252 * Get a debugging dump of a system service by name.
1253 *
1254 * <p>Most services require the caller to hold android.permission.DUMP.
1255 *
1256 * @param name of the service to dump
1257 * @param fd to write dump output to (usually an output log file)
1258 * @param args to pass to the service's dump method, may be null
1259 * @return true if the service was dumped successfully, false if
1260 * the service could not be found or had an error while dumping
1261 */
1262 public static boolean dumpService(String name, FileDescriptor fd, String[] args) {
1263 IBinder service = ServiceManager.getService(name);
1264 if (service == null) {
1265 Log.e(TAG, "Can't find service to dump: " + name);
1266 return false;
1267 }
1268
1269 try {
1270 service.dump(fd, args);
1271 return true;
1272 } catch (RemoteException e) {
1273 Log.e(TAG, "Can't dump service: " + name, e);
1274 return false;
1275 }
1276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277}