blob: ba692469d9f5a600b45ca63c8682c19cec24cbf8 [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 Hackborn3025ef32009-08-31 21:31:47 -0700132 public MemoryInfo() {
133 }
134
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700135 /**
136 * Return total PSS memory usage in kB.
137 */
138 public int getTotalPss() {
139 return dalvikPss + nativePss + otherPss;
140 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200141
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700142 /**
143 * Return total private dirty memory usage in kB.
144 */
145 public int getTotalPrivateDirty() {
146 return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty;
147 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200148
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700149 /**
150 * Return total shared dirty memory usage in kB.
151 */
152 public int getTotalSharedDirty() {
153 return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty;
154 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200155
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700156 public int describeContents() {
157 return 0;
158 }
159
160 public void writeToParcel(Parcel dest, int flags) {
161 dest.writeInt(dalvikPss);
162 dest.writeInt(dalvikPrivateDirty);
163 dest.writeInt(dalvikSharedDirty);
164 dest.writeInt(nativePss);
165 dest.writeInt(nativePrivateDirty);
166 dest.writeInt(nativeSharedDirty);
167 dest.writeInt(otherPss);
168 dest.writeInt(otherPrivateDirty);
169 dest.writeInt(otherSharedDirty);
170 }
171
172 public void readFromParcel(Parcel source) {
173 dalvikPss = source.readInt();
174 dalvikPrivateDirty = source.readInt();
175 dalvikSharedDirty = source.readInt();
176 nativePss = source.readInt();
177 nativePrivateDirty = source.readInt();
178 nativeSharedDirty = source.readInt();
179 otherPss = source.readInt();
180 otherPrivateDirty = source.readInt();
181 otherSharedDirty = source.readInt();
182 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200183
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700184 public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
185 public MemoryInfo createFromParcel(Parcel source) {
186 return new MemoryInfo(source);
187 }
188 public MemoryInfo[] newArray(int size) {
189 return new MemoryInfo[size];
190 }
191 };
192
193 private MemoryInfo(Parcel source) {
194 readFromParcel(source);
195 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 }
197
198
199 /**
200 * Wait until a debugger attaches. As soon as the debugger attaches,
201 * this returns, so you will need to place a breakpoint after the
202 * waitForDebugger() call if you want to start tracing immediately.
203 */
204 public static void waitForDebugger() {
205 if (!VMDebug.isDebuggingEnabled()) {
206 //System.out.println("debugging not enabled, not waiting");
207 return;
208 }
209 if (isDebuggerConnected())
210 return;
211
212 // if DDMS is listening, inform them of our plight
213 System.out.println("Sending WAIT chunk");
214 byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger"
215 Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1);
216 DdmServer.sendChunk(waitChunk);
217
218 mWaiting = true;
219 while (!isDebuggerConnected()) {
220 try { Thread.sleep(SPIN_DELAY); }
221 catch (InterruptedException ie) {}
222 }
223 mWaiting = false;
224
225 System.out.println("Debugger has connected");
226
227 /*
228 * There is no "ready to go" signal from the debugger, and we're
229 * not allowed to suspend ourselves -- the debugger expects us to
230 * be running happily, and gets confused if we aren't. We need to
231 * allow the debugger a chance to set breakpoints before we start
232 * running again.
233 *
234 * Sit and spin until the debugger has been idle for a short while.
235 */
236 while (true) {
237 long delta = VMDebug.lastDebuggerActivity();
238 if (delta < 0) {
239 System.out.println("debugger detached?");
240 break;
241 }
242
243 if (delta < MIN_DEBUGGER_IDLE) {
244 System.out.println("waiting for debugger to settle...");
245 try { Thread.sleep(SPIN_DELAY); }
246 catch (InterruptedException ie) {}
247 } else {
248 System.out.println("debugger has settled (" + delta + ")");
249 break;
250 }
251 }
252 }
253
254 /**
255 * Returns "true" if one or more threads is waiting for a debugger
256 * to attach.
257 */
258 public static boolean waitingForDebugger() {
259 return mWaiting;
260 }
261
262 /**
263 * Determine if a debugger is currently attached.
264 */
265 public static boolean isDebuggerConnected() {
266 return VMDebug.isDebuggerConnected();
267 }
268
269 /**
Andy McFaddene5772322010-01-22 07:23:31 -0800270 * Returns an array of strings that identify VM features. This is
271 * used by DDMS to determine what sorts of operations the VM can
272 * perform.
273 *
274 * @hide
275 */
276 public static String[] getVmFeatureList() {
277 return VMDebug.getVmFeatureList();
278 }
279
280 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 * Change the JDWP port.
282 *
283 * @deprecated no longer needed or useful
284 */
285 @Deprecated
286 public static void changeDebugPort(int port) {}
287
288 /**
289 * This is the pathname to the sysfs file that enables and disables
290 * tracing on the qemu emulator.
291 */
292 private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state";
293
294 /**
295 * Enable qemu tracing. For this to work requires running everything inside
296 * the qemu emulator; otherwise, this method will have no effect. The trace
297 * file is specified on the command line when the emulator is started. For
298 * example, the following command line <br />
299 * <code>emulator -trace foo</code><br />
300 * will start running the emulator and create a trace file named "foo". This
301 * method simply enables writing the trace records to the trace file.
302 *
303 * <p>
304 * The main differences between this and {@link #startMethodTracing()} are
305 * that tracing in the qemu emulator traces every cpu instruction of every
306 * process, including kernel code, so we have more complete information,
307 * including all context switches. We can also get more detailed information
308 * such as cache misses. The sequence of calls is determined by
309 * post-processing the instruction trace. The qemu tracing is also done
310 * without modifying the application or perturbing the timing of calls
311 * because no instrumentation is added to the application being traced.
312 * </p>
313 *
314 * <p>
315 * One limitation of using this method compared to using
316 * {@link #startMethodTracing()} on the real device is that the emulator
317 * does not model all of the real hardware effects such as memory and
318 * bus contention. The emulator also has a simple cache model and cannot
319 * capture all the complexities of a real cache.
320 * </p>
321 */
322 public static void startNativeTracing() {
323 // Open the sysfs file for writing and write "1" to it.
324 PrintWriter outStream = null;
325 try {
326 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
327 outStream = new PrintWriter(new OutputStreamWriter(fos));
328 outStream.println("1");
329 } catch (Exception e) {
330 } finally {
331 if (outStream != null)
332 outStream.close();
333 }
334
335 VMDebug.startEmulatorTracing();
336 }
337
338 /**
339 * Stop qemu tracing. See {@link #startNativeTracing()} to start tracing.
340 *
341 * <p>Tracing can be started and stopped as many times as desired. When
342 * the qemu emulator itself is stopped then the buffered trace records
343 * are flushed and written to the trace file. In fact, it is not necessary
344 * to call this method at all; simply killing qemu is sufficient. But
345 * starting and stopping a trace is useful for examining a specific
346 * region of code.</p>
347 */
348 public static void stopNativeTracing() {
349 VMDebug.stopEmulatorTracing();
350
351 // Open the sysfs file for writing and write "0" to it.
352 PrintWriter outStream = null;
353 try {
354 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
355 outStream = new PrintWriter(new OutputStreamWriter(fos));
356 outStream.println("0");
357 } catch (Exception e) {
358 // We could print an error message here but we probably want
359 // to quietly ignore errors if we are not running in the emulator.
360 } finally {
361 if (outStream != null)
362 outStream.close();
363 }
364 }
365
366 /**
367 * Enable "emulator traces", in which information about the current
368 * method is made available to the "emulator -trace" feature. There
369 * is no corresponding "disable" call -- this is intended for use by
370 * the framework when tracing should be turned on and left that way, so
371 * that traces captured with F9/F10 will include the necessary data.
372 *
373 * This puts the VM into "profile" mode, which has performance
374 * consequences.
375 *
376 * To temporarily enable tracing, use {@link #startNativeTracing()}.
377 */
378 public static void enableEmulatorTraceOutput() {
379 VMDebug.startEmulatorTracing();
380 }
381
382 /**
383 * Start method tracing with default log name and buffer size. See <a
384href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
385 * information about reading these files. Call stopMethodTracing() to stop
386 * tracing.
387 */
388 public static void startMethodTracing() {
389 VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0);
390 }
391
392 /**
393 * Start method tracing, specifying the trace log file name. The trace
394 * file will be put under "/sdcard" unless an absolute path is given.
395 * See <a
396 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
397 * information about reading trace files.
398 *
399 * @param traceName Name for the trace log file to create.
400 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
401 * If the files already exist, they will be truncated.
402 * If the trace file given does not end in ".trace", it will be appended for you.
403 */
404 public static void startMethodTracing(String traceName) {
405 startMethodTracing(traceName, 0, 0);
406 }
407
408 /**
409 * Start method tracing, specifying the trace log file name and the
410 * buffer size. The trace files will be put under "/sdcard" unless an
411 * absolute path is given. See <a
412 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
413 * information about reading trace files.
414 * @param traceName Name for the trace log file to create.
415 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
416 * If the files already exist, they will be truncated.
417 * If the trace file given does not end in ".trace", it will be appended for you.
418 *
419 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
420 */
421 public static void startMethodTracing(String traceName, int bufferSize) {
422 startMethodTracing(traceName, bufferSize, 0);
423 }
424
425 /**
426 * Start method tracing, specifying the trace log file name and the
427 * buffer size. The trace files will be put under "/sdcard" unless an
428 * absolute path is given. See <a
429 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
430 * information about reading trace files.
431 *
432 * <p>
433 * When method tracing is enabled, the VM will run more slowly than
434 * usual, so the timings from the trace files should only be considered
435 * in relative terms (e.g. was run #1 faster than run #2). The times
436 * for native methods will not change, so don't try to use this to
437 * compare the performance of interpreted and native implementations of the
438 * same method. As an alternative, consider using "native" tracing
439 * in the emulator via {@link #startNativeTracing()}.
440 * </p>
441 *
442 * @param traceName Name for the trace log file to create.
443 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
444 * If the files already exist, they will be truncated.
445 * If the trace file given does not end in ".trace", it will be appended for you.
446 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
447 */
448 public static void startMethodTracing(String traceName, int bufferSize,
449 int flags) {
450
451 String pathName = traceName;
452 if (pathName.charAt(0) != '/')
453 pathName = DEFAULT_TRACE_PATH_PREFIX + pathName;
454 if (!pathName.endsWith(DEFAULT_TRACE_EXTENSION))
455 pathName = pathName + DEFAULT_TRACE_EXTENSION;
456
457 VMDebug.startMethodTracing(pathName, bufferSize, flags);
458 }
459
460 /**
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700461 * Like startMethodTracing(String, int, int), but taking an already-opened
462 * FileDescriptor in which the trace is written. The file name is also
463 * supplied simply for logging. Makes a dup of the file descriptor.
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200464 *
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700465 * Not exposed in the SDK unless we are really comfortable with supporting
466 * this and find it would be useful.
467 * @hide
468 */
469 public static void startMethodTracing(String traceName, FileDescriptor fd,
470 int bufferSize, int flags) {
471 VMDebug.startMethodTracing(traceName, fd, bufferSize, flags);
472 }
473
474 /**
Andy McFadden72a20db0c2010-01-22 12:20:41 -0800475 * Starts method tracing without a backing file. When stopMethodTracing
476 * is called, the result is sent directly to DDMS. (If DDMS is not
477 * attached when tracing ends, the profiling data will be discarded.)
478 *
479 * @hide
480 */
481 public static void startMethodTracingDdms(int bufferSize, int flags) {
482 VMDebug.startMethodTracingDdms(bufferSize, flags);
483 }
484
485 /**
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700486 * Determine whether method tracing is currently active.
487 * @hide
488 */
489 public static boolean isMethodTracingActive() {
490 return VMDebug.isMethodTracingActive();
491 }
492
493 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 * Stop method tracing.
495 */
496 public static void stopMethodTracing() {
497 VMDebug.stopMethodTracing();
498 }
499
500 /**
501 * Get an indication of thread CPU usage. The value returned
502 * indicates the amount of time that the current thread has spent
503 * executing code or waiting for certain types of I/O.
504 *
505 * The time is expressed in nanoseconds, and is only meaningful
506 * when compared to the result from an earlier call. Note that
507 * nanosecond resolution does not imply nanosecond accuracy.
508 *
509 * On system which don't support this operation, the call returns -1.
510 */
511 public static long threadCpuTimeNanos() {
512 return VMDebug.threadCpuTimeNanos();
513 }
514
515 /**
Chet Haase2970c492010-11-09 13:58:04 -0800516 * Start counting the number and aggregate size of memory allocations.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 *
Chet Haase2970c492010-11-09 13:58:04 -0800518 * <p>The {@link #startAllocCounting() start} function resets the counts and enables counting.
519 * The {@link #stopAllocCounting() stop} function disables the counting so that the analysis
520 * code doesn't cause additional allocations. The various <code>get</code> functions return
521 * the specified value. And the various <code>reset</code> functions reset the specified
522 * count.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 *
Chet Haase2970c492010-11-09 13:58:04 -0800524 * <p>Counts are kept for the system as a whole and for each thread.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 * The per-thread counts for threads other than the current thread
Chet Haase2970c492010-11-09 13:58:04 -0800526 * are not cleared by the "reset" or "start" calls.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527 */
528 public static void startAllocCounting() {
529 VMDebug.startAllocCounting();
530 }
Chet Haase2970c492010-11-09 13:58:04 -0800531
532 /**
533 * Stop counting the number and aggregate size of memory allocations.
534 *
535 * @see #startAllocCounting()
536 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 public static void stopAllocCounting() {
538 VMDebug.stopAllocCounting();
539 }
540
541 public static int getGlobalAllocCount() {
542 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
543 }
544 public static int getGlobalAllocSize() {
545 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
546 }
547 public static int getGlobalFreedCount() {
548 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
549 }
550 public static int getGlobalFreedSize() {
551 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
552 }
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800553 public static int getGlobalClassInitCount() {
554 /* number of classes that have been successfully initialized */
555 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
556 }
557 public static int getGlobalClassInitTime() {
558 /* cumulative elapsed time for class initialization, in usec */
559 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
560 }
Carl Shapirob5961982010-12-22 15:54:53 -0800561
562 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800563 * Returns the global count of external allocation requests. The
564 * external allocation tracking feature was removed in Honeycomb.
565 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800566 *
567 * @deprecated This method is now obsolete.
568 */
569 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 public static int getGlobalExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800571 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 }
Carl Shapirob5961982010-12-22 15:54:53 -0800573
574 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800575 * Returns the global count of bytes externally allocated. The
576 * external allocation tracking feature was removed in Honeycomb.
577 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800578 *
579 * @deprecated This method is now obsolete.
580 */
581 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 public static int getGlobalExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800583 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 }
Carl Shapirob5961982010-12-22 15:54:53 -0800585
586 /**
587 * Returns the global count of freed external allocation requests.
Carl Shapiro7e942842011-01-12 17:17:45 -0800588 * The external allocation tracking feature was removed in
589 * Honeycomb. This method exists for compatibility and always
590 * returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800591 *
592 * @deprecated This method is now obsolete.
593 */
594 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 public static int getGlobalExternalFreedCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800596 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 }
Carl Shapirob5961982010-12-22 15:54:53 -0800598
599 /**
600 * Returns the global count of freed bytes from external
Carl Shapiro7e942842011-01-12 17:17:45 -0800601 * allocation requests. The external allocation tracking feature
602 * was removed in Honeycomb. This method exists for compatibility
603 * and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800604 *
605 * @deprecated This method is now obsolete.
606 */
607 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 public static int getGlobalExternalFreedSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800609 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 }
Carl Shapirob5961982010-12-22 15:54:53 -0800611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 public static int getGlobalGcInvocationCount() {
613 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
614 }
615 public static int getThreadAllocCount() {
616 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
617 }
618 public static int getThreadAllocSize() {
619 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
620 }
Carl Shapirob5961982010-12-22 15:54:53 -0800621
622 /**
623 * Returns the count of external allocation requests made by the
Carl Shapiro7e942842011-01-12 17:17:45 -0800624 * current thread. The external allocation tracking feature was
625 * removed in Honeycomb. This method exists for compatibility and
626 * always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800627 *
628 * @deprecated This method is now obsolete.
629 */
630 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 public static int getThreadExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800632 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 }
Carl Shapirob5961982010-12-22 15:54:53 -0800634
635 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800636 * Returns the global count of bytes externally allocated. The
637 * external allocation tracking feature was removed in Honeycomb.
638 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800639 *
640 * @deprecated This method is now obsolete.
641 */
642 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 public static int getThreadExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800644 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 }
Carl Shapirob5961982010-12-22 15:54:53 -0800646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 public static int getThreadGcInvocationCount() {
648 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
649 }
650
651 public static void resetGlobalAllocCount() {
652 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
653 }
654 public static void resetGlobalAllocSize() {
655 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
656 }
657 public static void resetGlobalFreedCount() {
658 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
659 }
660 public static void resetGlobalFreedSize() {
661 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
662 }
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800663 public static void resetGlobalClassInitCount() {
664 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
665 }
666 public static void resetGlobalClassInitTime() {
667 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
668 }
Carl Shapirob5961982010-12-22 15:54:53 -0800669
670 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800671 * Resets the global count of external allocation requests. The
672 * external allocation tracking feature was removed in Honeycomb.
673 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800674 *
675 * @deprecated This method is now obsolete.
676 */
677 @Deprecated
678 public static void resetGlobalExternalAllocCount() {}
679
680 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800681 * Resets the global count of bytes externally allocated. The
682 * external allocation tracking feature was removed in Honeycomb.
683 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800684 *
685 * @deprecated This method is now obsolete.
686 */
687 @Deprecated
688 public static void resetGlobalExternalAllocSize() {}
689
690 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800691 * Resets the global count of freed external allocations. The
692 * external allocation tracking feature was removed in Honeycomb.
693 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800694 *
695 * @deprecated This method is now obsolete.
696 */
697 @Deprecated
698 public static void resetGlobalExternalFreedCount() {}
699
700 /**
701 * Resets the global count counter of freed bytes from external
Carl Shapiro7e942842011-01-12 17:17:45 -0800702 * allocations. The external allocation tracking feature was
703 * removed in Honeycomb. This method exists for compatibility and
704 * has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800705 *
706 * @deprecated This method is now obsolete.
707 */
708 @Deprecated
709 public static void resetGlobalExternalFreedSize() {}
710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 public static void resetGlobalGcInvocationCount() {
712 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
713 }
714 public static void resetThreadAllocCount() {
715 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
716 }
717 public static void resetThreadAllocSize() {
718 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
719 }
Carl Shapirob5961982010-12-22 15:54:53 -0800720
721 /**
722 * Resets the count of external allocation requests made by the
Carl Shapiro7e942842011-01-12 17:17:45 -0800723 * current thread. The external allocation tracking feature was
724 * removed in Honeycomb. This method exists for compatibility and
725 * has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800726 *
727 * @deprecated This method is now obsolete.
728 */
729 @Deprecated
730 public static void resetThreadExternalAllocCount() {}
731
732 /**
733 * Resets the count of bytes externally allocated by the current
Carl Shapiro7e942842011-01-12 17:17:45 -0800734 * thread. The external allocation tracking feature was removed
735 * in Honeycomb. This method exists for compatibility and has no
736 * effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800737 *
738 * @deprecated This method is now obsolete.
739 */
740 @Deprecated
741 public static void resetThreadExternalAllocSize() {}
742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 public static void resetThreadGcInvocationCount() {
744 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
745 }
746 public static void resetAllCounts() {
747 VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
748 }
749
750 /**
751 * Returns the size of the native heap.
752 * @return The size of the native heap in bytes.
753 */
754 public static native long getNativeHeapSize();
755
756 /**
757 * Returns the amount of allocated memory in the native heap.
758 * @return The allocated size in bytes.
759 */
760 public static native long getNativeHeapAllocatedSize();
761
762 /**
763 * Returns the amount of free memory in the native heap.
764 * @return The freed size in bytes.
765 */
766 public static native long getNativeHeapFreeSize();
767
768 /**
769 * Retrieves information about this processes memory usages. This information is broken down by
770 * how much is in use by dalivk, the native heap, and everything else.
771 */
772 public static native void getMemoryInfo(MemoryInfo memoryInfo);
773
774 /**
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700775 * Note: currently only works when the requested pid has the same UID
776 * as the caller.
777 * @hide
778 */
779 public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
780
781 /**
Carl Shapiro11073832011-01-12 16:28:57 -0800782 * Establish an object allocation limit in the current thread.
Carl Shapiro7e942842011-01-12 17:17:45 -0800783 * This feature was never enabled in release builds. The
784 * allocation limits feature was removed in Honeycomb. This
785 * method exists for compatibility and always returns -1 and has
786 * no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 *
Carl Shapiro11073832011-01-12 16:28:57 -0800788 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 */
Carl Shapiro11073832011-01-12 16:28:57 -0800790 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 public static int setAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -0800792 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 }
794
795 /**
Carl Shapiro11073832011-01-12 16:28:57 -0800796 * Establish a global object allocation limit. This feature was
Carl Shapiro7e942842011-01-12 17:17:45 -0800797 * never enabled in release builds. The allocation limits feature
798 * was removed in Honeycomb. This method exists for compatibility
799 * and always returns -1 and has no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800 *
Carl Shapiro11073832011-01-12 16:28:57 -0800801 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 */
Carl Shapiro11073832011-01-12 16:28:57 -0800803 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 public static int setGlobalAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -0800805 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 }
807
808 /**
809 * Dump a list of all currently loaded class to the log file.
810 *
811 * @param flags See constants above.
812 */
813 public static void printLoadedClasses(int flags) {
814 VMDebug.printLoadedClasses(flags);
815 }
816
817 /**
818 * Get the number of loaded classes.
819 * @return the number of loaded classes.
820 */
821 public static int getLoadedClassCount() {
822 return VMDebug.getLoadedClassCount();
823 }
824
825 /**
Andy McFadden824c5102010-07-09 16:26:57 -0700826 * Dump "hprof" data to the specified file. This may cause a GC.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 *
828 * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof").
829 * @throws UnsupportedOperationException if the VM was built without
830 * HPROF support.
831 * @throws IOException if an error occurs while opening or writing files.
832 */
833 public static void dumpHprofData(String fileName) throws IOException {
834 VMDebug.dumpHprofData(fileName);
835 }
836
837 /**
Andy McFadden824c5102010-07-09 16:26:57 -0700838 * Like dumpHprofData(String), but takes an already-opened
839 * FileDescriptor to which the trace is written. The file name is also
840 * supplied simply for logging. Makes a dup of the file descriptor.
841 *
842 * Primarily for use by the "am" shell command.
843 *
844 * @hide
845 */
846 public static void dumpHprofData(String fileName, FileDescriptor fd)
847 throws IOException {
848 VMDebug.dumpHprofData(fileName, fd);
849 }
850
851 /**
852 * Collect "hprof" and send it to DDMS. This may cause a GC.
Andy McFadden07a96612010-01-28 16:54:37 -0800853 *
854 * @throws UnsupportedOperationException if the VM was built without
855 * HPROF support.
Andy McFadden07a96612010-01-28 16:54:37 -0800856 * @hide
857 */
858 public static void dumpHprofDataDdms() {
859 VMDebug.dumpHprofDataDdms();
860 }
861
862 /**
Andy McFadden06a6b552010-07-13 16:28:09 -0700863 * Writes native heap data to the specified file descriptor.
864 *
865 * @hide
866 */
867 public static native void dumpNativeHeap(FileDescriptor fd);
868
869 /**
Brian Carlstromc21550a2010-10-05 21:34:06 -0700870 * Returns a count of the extant instances of a class.
871 *
872 * @hide
873 */
874 public static long countInstancesOfClass(Class cls) {
Brian Carlstrom7495cfa2010-11-30 18:06:00 -0800875 return VMDebug.countInstancesOfClass(cls, true);
Brian Carlstromc21550a2010-10-05 21:34:06 -0700876 }
877
878 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 * Returns the number of sent transactions from this process.
880 * @return The number of sent transactions or -1 if it could not read t.
881 */
882 public static native int getBinderSentTransactions();
883
884 /**
885 * Returns the number of received transactions from the binder driver.
886 * @return The number of received transactions or -1 if it could not read the stats.
887 */
888 public static native int getBinderReceivedTransactions();
889
890 /**
891 * Returns the number of active local Binder objects that exist in the
892 * current process.
893 */
894 public static final native int getBinderLocalObjectCount();
895
896 /**
897 * Returns the number of references to remote proxy Binder objects that
898 * exist in the current process.
899 */
900 public static final native int getBinderProxyObjectCount();
901
902 /**
903 * Returns the number of death notification links to Binder objects that
904 * exist in the current process.
905 */
906 public static final native int getBinderDeathObjectCount();
907
908 /**
Andy McFadden599c9182009-04-08 00:35:56 -0700909 * Primes the register map cache.
910 *
911 * Only works for classes in the bootstrap class loader. Does not
912 * cause classes to be loaded if they're not already present.
913 *
914 * The classAndMethodDesc argument is a concatentation of the VM-internal
915 * class descriptor, method name, and method descriptor. Examples:
916 * Landroid/os/Looper;.loop:()V
917 * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V
918 *
919 * @param classAndMethodDesc the method to prepare
920 *
921 * @hide
922 */
923 public static final boolean cacheRegisterMap(String classAndMethodDesc) {
924 return VMDebug.cacheRegisterMap(classAndMethodDesc);
925 }
926
927 /**
Andy McFaddenbfd6d482009-10-22 17:25:57 -0700928 * Dumps the contents of VM reference tables (e.g. JNI locals and
929 * globals) to the log file.
930 *
931 * @hide
932 */
933 public static final void dumpReferenceTables() {
934 VMDebug.dumpReferenceTables();
935 }
936
937 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 * API for gathering and querying instruction counts.
939 *
940 * Example usage:
Chet Haase2970c492010-11-09 13:58:04 -0800941 * <pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 * Debug.InstructionCount icount = new Debug.InstructionCount();
943 * icount.resetAndStart();
944 * [... do lots of stuff ...]
945 * if (icount.collect()) {
946 * System.out.println("Total instructions executed: "
947 * + icount.globalTotal());
948 * System.out.println("Method invocations: "
949 * + icount.globalMethodInvocations());
950 * }
Chet Haase2970c492010-11-09 13:58:04 -0800951 * </pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 */
953 public static class InstructionCount {
Dan Bornsteinb96f5892010-12-02 17:19:53 -0800954 private static final int NUM_INSTR =
955 OpcodeInfo.MAXIMUM_PACKED_VALUE + 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956
957 private int[] mCounts;
958
959 public InstructionCount() {
960 mCounts = new int[NUM_INSTR];
961 }
962
963 /**
964 * Reset counters and ensure counts are running. Counts may
965 * have already been running.
966 *
967 * @return true if counting was started
968 */
969 public boolean resetAndStart() {
970 try {
971 VMDebug.startInstructionCounting();
972 VMDebug.resetInstructionCount();
973 } catch (UnsupportedOperationException uoe) {
974 return false;
975 }
976 return true;
977 }
978
979 /**
980 * Collect instruction counts. May or may not stop the
981 * counting process.
982 */
983 public boolean collect() {
984 try {
985 VMDebug.stopInstructionCounting();
986 VMDebug.getInstructionCount(mCounts);
987 } catch (UnsupportedOperationException uoe) {
988 return false;
989 }
990 return true;
991 }
992
993 /**
994 * Return the total number of instructions executed globally (i.e. in
995 * all threads).
996 */
997 public int globalTotal() {
998 int count = 0;
Dan Bornstein1d99b062010-11-30 12:26:52 -0800999
1000 for (int i = 0; i < NUM_INSTR; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 count += mCounts[i];
Dan Bornstein1d99b062010-11-30 12:26:52 -08001002 }
1003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 return count;
1005 }
1006
1007 /**
1008 * Return the total number of method-invocation instructions
1009 * executed globally.
1010 */
1011 public int globalMethodInvocations() {
1012 int count = 0;
1013
Dan Bornstein1d99b062010-11-30 12:26:52 -08001014 for (int i = 0; i < NUM_INSTR; i++) {
1015 if (OpcodeInfo.isInvoke(i)) {
1016 count += mCounts[i];
1017 }
1018 }
1019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 return count;
1021 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001022 }
1023
Dave Bort1ce5bd32009-04-22 17:36:56 -07001024 /**
1025 * A Map of typed debug properties.
1026 */
1027 private static final TypedProperties debugProperties;
1028
1029 /*
1030 * Load the debug properties from the standard files into debugProperties.
1031 */
1032 static {
Joe Onorato43a17652011-04-06 19:22:23 -07001033 if (false) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001034 final String TAG = "DebugProperties";
1035 final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" };
1036 final TypedProperties tp = new TypedProperties();
1037
1038 // Read the properties from each of the files, if present.
Dave Borte9bfd9b2009-05-04 14:35:23 -07001039 for (String file : files) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001040 Reader r;
1041 try {
1042 r = new FileReader(file);
1043 } catch (FileNotFoundException ex) {
1044 // It's ok if a file is missing.
1045 continue;
1046 }
1047
Dave Bort1ce5bd32009-04-22 17:36:56 -07001048 try {
1049 tp.load(r);
Dave Borte9bfd9b2009-05-04 14:35:23 -07001050 } catch (Exception ex) {
1051 throw new RuntimeException("Problem loading " + file, ex);
1052 } finally {
1053 try {
1054 r.close();
1055 } catch (IOException ex) {
1056 // Ignore this error.
1057 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001058 }
1059 }
1060
1061 debugProperties = tp.isEmpty() ? null : tp;
1062 } else {
1063 debugProperties = null;
1064 }
1065 }
1066
1067
1068 /**
1069 * Returns true if the type of the field matches the specified class.
1070 * Handles the case where the class is, e.g., java.lang.Boolean, but
1071 * the field is of the primitive "boolean" type. Also handles all of
1072 * the java.lang.Number subclasses.
1073 */
1074 private static boolean fieldTypeMatches(Field field, Class<?> cl) {
1075 Class<?> fieldClass = field.getType();
1076 if (fieldClass == cl) {
1077 return true;
1078 }
1079 Field primitiveTypeField;
1080 try {
1081 /* All of the classes we care about (Boolean, Integer, etc.)
1082 * have a Class field called "TYPE" that points to the corresponding
1083 * primitive class.
1084 */
1085 primitiveTypeField = cl.getField("TYPE");
1086 } catch (NoSuchFieldException ex) {
1087 return false;
1088 }
1089 try {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001090 return fieldClass == (Class<?>) primitiveTypeField.get(null);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001091 } catch (IllegalAccessException ex) {
1092 return false;
1093 }
1094 }
1095
1096
1097 /**
1098 * Looks up the property that corresponds to the field, and sets the field's value
1099 * if the types match.
1100 */
Dave Borte9bfd9b2009-05-04 14:35:23 -07001101 private static void modifyFieldIfSet(final Field field, final TypedProperties properties,
1102 final String propertyName) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001103 if (field.getType() == java.lang.String.class) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001104 int stringInfo = properties.getStringInfo(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001105 switch (stringInfo) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001106 case TypedProperties.STRING_SET:
1107 // Handle as usual below.
1108 break;
1109 case TypedProperties.STRING_NULL:
1110 try {
1111 field.set(null, null); // null object for static fields; null string
1112 } catch (IllegalAccessException ex) {
1113 throw new IllegalArgumentException(
1114 "Cannot set field for " + propertyName, ex);
1115 }
1116 return;
1117 case TypedProperties.STRING_NOT_SET:
1118 return;
1119 case TypedProperties.STRING_TYPE_MISMATCH:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001120 throw new IllegalArgumentException(
Dave Borte9bfd9b2009-05-04 14:35:23 -07001121 "Type of " + propertyName + " " +
1122 " does not match field type (" + field.getType() + ")");
1123 default:
1124 throw new IllegalStateException(
1125 "Unexpected getStringInfo(" + propertyName + ") return value " +
1126 stringInfo);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001127 }
1128 }
Dave Borte9bfd9b2009-05-04 14:35:23 -07001129 Object value = properties.get(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001130 if (value != null) {
1131 if (!fieldTypeMatches(field, value.getClass())) {
1132 throw new IllegalArgumentException(
1133 "Type of " + propertyName + " (" + value.getClass() + ") " +
1134 " does not match field type (" + field.getType() + ")");
1135 }
1136 try {
1137 field.set(null, value); // null object for static fields
1138 } catch (IllegalAccessException ex) {
1139 throw new IllegalArgumentException(
1140 "Cannot set field for " + propertyName, ex);
1141 }
1142 }
1143 }
1144
1145
1146 /**
Romain Guyc4b11a72009-05-13 15:46:37 -07001147 * Equivalent to <code>setFieldsOn(cl, false)</code>.
1148 *
1149 * @see #setFieldsOn(Class, boolean)
Romain Guyd4103d02009-05-14 12:24:21 -07001150 *
1151 * @hide
Romain Guyc4b11a72009-05-13 15:46:37 -07001152 */
1153 public static void setFieldsOn(Class<?> cl) {
1154 setFieldsOn(cl, false);
1155 }
1156
1157 /**
Dave Bort1ce5bd32009-04-22 17:36:56 -07001158 * Reflectively sets static fields of a class based on internal debugging
Joe Onorato43a17652011-04-06 19:22:23 -07001159 * properties. This method is a no-op if false is
Dave Bort1ce5bd32009-04-22 17:36:56 -07001160 * false.
1161 * <p>
Joe Onorato43a17652011-04-06 19:22:23 -07001162 * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: false will
Dave Bort1ce5bd32009-04-22 17:36:56 -07001163 * always be false in release builds. This API is typically only useful
1164 * for platform developers.
1165 * </p>
1166 * Class setup: define a class whose only fields are non-final, static
1167 * primitive types (except for "char") or Strings. In a static block
1168 * after the field definitions/initializations, pass the class to
Romain Guyc4b11a72009-05-13 15:46:37 -07001169 * this method, Debug.setFieldsOn(). Example:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001170 * <pre>
1171 * package com.example;
1172 *
1173 * import android.os.Debug;
1174 *
1175 * public class MyDebugVars {
1176 * public static String s = "a string";
1177 * public static String s2 = "second string";
1178 * public static String ns = null;
1179 * public static boolean b = false;
1180 * public static int i = 5;
Romain Guyc4b11a72009-05-13 15:46:37 -07001181 * @Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001182 * public static float f = 0.1f;
Romain Guyc4b11a72009-05-13 15:46:37 -07001183 * @@Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001184 * public static double d = 0.5d;
1185 *
1186 * // This MUST appear AFTER all fields are defined and initialized!
1187 * static {
Romain Guyc4b11a72009-05-13 15:46:37 -07001188 * // Sets all the fields
Dave Borte9bfd9b2009-05-04 14:35:23 -07001189 * Debug.setFieldsOn(MyDebugVars.class);
Christian Mehlmauer798e2d32010-06-17 18:24:07 +02001190 *
Romain Guyc4b11a72009-05-13 15:46:37 -07001191 * // Sets only the fields annotated with @Debug.DebugProperty
1192 * // Debug.setFieldsOn(MyDebugVars.class, true);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001193 * }
1194 * }
1195 * </pre>
Dave Borte9bfd9b2009-05-04 14:35:23 -07001196 * setFieldsOn() may override the value of any field in the class based
Dave Bort1ce5bd32009-04-22 17:36:56 -07001197 * on internal properties that are fixed at boot time.
1198 * <p>
1199 * These properties are only set during platform debugging, and are not
1200 * meant to be used as a general-purpose properties store.
1201 *
1202 * {@hide}
1203 *
1204 * @param cl The class to (possibly) modify
Romain Guyc4b11a72009-05-13 15:46:37 -07001205 * @param partial If false, sets all static fields, otherwise, only set
1206 * fields with the {@link android.os.Debug.DebugProperty}
1207 * annotation
Dave Bort1ce5bd32009-04-22 17:36:56 -07001208 * @throws IllegalArgumentException if any fields are final or non-static,
1209 * or if the type of the field does not match the type of
1210 * the internal debugging property value.
1211 */
Romain Guyc4b11a72009-05-13 15:46:37 -07001212 public static void setFieldsOn(Class<?> cl, boolean partial) {
Joe Onorato43a17652011-04-06 19:22:23 -07001213 if (false) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001214 if (debugProperties != null) {
1215 /* Only look for fields declared directly by the class,
1216 * so we don't mysteriously change static fields in superclasses.
1217 */
1218 for (Field field : cl.getDeclaredFields()) {
Romain Guyc4b11a72009-05-13 15:46:37 -07001219 if (!partial || field.getAnnotation(DebugProperty.class) != null) {
1220 final String propertyName = cl.getName() + "." + field.getName();
1221 boolean isStatic = Modifier.isStatic(field.getModifiers());
1222 boolean isFinal = Modifier.isFinal(field.getModifiers());
1223
1224 if (!isStatic || isFinal) {
1225 throw new IllegalArgumentException(propertyName +
1226 " must be static and non-final");
1227 }
1228 modifyFieldIfSet(field, debugProperties, propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001229 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001230 }
1231 }
1232 } else {
Dan Egnor3eda9792010-03-05 13:28:36 -08001233 Log.wtf(TAG,
Dave Borte9bfd9b2009-05-04 14:35:23 -07001234 "setFieldsOn(" + (cl == null ? "null" : cl.getName()) +
Dave Bort1ce5bd32009-04-22 17:36:56 -07001235 ") called in non-DEBUG build");
1236 }
1237 }
Romain Guyc4b11a72009-05-13 15:46:37 -07001238
1239 /**
1240 * Annotation to put on fields you want to set with
1241 * {@link Debug#setFieldsOn(Class, boolean)}.
1242 *
1243 * @hide
1244 */
1245 @Target({ ElementType.FIELD })
1246 @Retention(RetentionPolicy.RUNTIME)
1247 public @interface DebugProperty {
1248 }
Dan Egnor3eda9792010-03-05 13:28:36 -08001249
1250 /**
1251 * Get a debugging dump of a system service by name.
1252 *
1253 * <p>Most services require the caller to hold android.permission.DUMP.
1254 *
1255 * @param name of the service to dump
1256 * @param fd to write dump output to (usually an output log file)
1257 * @param args to pass to the service's dump method, may be null
1258 * @return true if the service was dumped successfully, false if
1259 * the service could not be found or had an error while dumping
1260 */
1261 public static boolean dumpService(String name, FileDescriptor fd, String[] args) {
1262 IBinder service = ServiceManager.getService(name);
1263 if (service == null) {
1264 Log.e(TAG, "Can't find service to dump: " + name);
1265 return false;
1266 }
1267
1268 try {
1269 service.dump(fd, args);
1270 return true;
1271 } catch (RemoteException e) {
1272 Log.e(TAG, "Can't dump service: " + name, e);
1273 return false;
1274 }
1275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001276}