blob: d8e30e21151be4540c7e00bc1eafe4d13ec22b80 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
18
Dave Bort1ce5bd32009-04-22 17:36:56 -070019import com.android.internal.util.TypedProperties;
20
Dave Bort1ce5bd32009-04-22 17:36:56 -070021import android.util.Log;
22
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070023import java.io.FileDescriptor;
Dave Bort1ce5bd32009-04-22 17:36:56 -070024import java.io.FileNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import java.io.FileOutputStream;
Dave Bort1ce5bd32009-04-22 17:36:56 -070026import java.io.FileReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import java.io.IOException;
28import java.io.OutputStreamWriter;
29import java.io.PrintWriter;
Dave Bort1ce5bd32009-04-22 17:36:56 -070030import java.io.Reader;
31import java.lang.reflect.Field;
32import java.lang.reflect.Modifier;
Romain Guyc4b11a72009-05-13 15:46:37 -070033import java.lang.annotation.Target;
34import java.lang.annotation.ElementType;
35import java.lang.annotation.Retention;
36import java.lang.annotation.RetentionPolicy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
38import org.apache.harmony.dalvik.ddmc.Chunk;
39import org.apache.harmony.dalvik.ddmc.ChunkHandler;
40import org.apache.harmony.dalvik.ddmc.DdmServer;
41
Dan Bornstein9f315542010-11-19 18:12:55 -080042import dalvik.bytecode.OpcodeInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import dalvik.bytecode.Opcodes;
44import dalvik.system.VMDebug;
45
46
47/**
Ian Rogersfe067a42013-02-22 19:59:23 -080048 * Provides various debugging methods for Android applications, including
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 * tracing and allocation counts.
50 * <p><strong>Logging Trace Files</strong></p>
51 * <p>Debug can create log files that give details about an application, such as
52 * a call stack and start/stop times for any running methods. See <a
53href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
54 * information about reading trace files. To start logging trace files, call one
55 * of the startMethodTracing() methods. To stop tracing, call
56 * {@link #stopMethodTracing()}.
57 */
58public final class Debug
59{
Dan Egnor3eda9792010-03-05 13:28:36 -080060 private static final String TAG = "Debug";
61
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 /**
63 * Flags for startMethodTracing(). These can be ORed together.
64 *
65 * TRACE_COUNT_ALLOCS adds the results from startAllocCounting to the
66 * trace key file.
67 */
68 public static final int TRACE_COUNT_ALLOCS = VMDebug.TRACE_COUNT_ALLOCS;
69
70 /**
71 * Flags for printLoadedClasses(). Default behavior is to only show
72 * the class name.
73 */
74 public static final int SHOW_FULL_DETAIL = 1;
75 public static final int SHOW_CLASSLOADER = (1 << 1);
76 public static final int SHOW_INITIALIZED = (1 << 2);
77
78 // set/cleared by waitForDebugger()
79 private static volatile boolean mWaiting = false;
80
81 private Debug() {}
82
83 /*
84 * How long to wait for the debugger to finish sending requests. I've
85 * seen this hit 800msec on the device while waiting for a response
86 * to travel over USB and get processed, so we take that and add
87 * half a second.
88 */
89 private static final int MIN_DEBUGGER_IDLE = 1300; // msec
90
91 /* how long to sleep when polling for activity */
92 private static final int SPIN_DELAY = 200; // msec
93
94 /**
95 * Default trace file path and file
96 */
Christian Mehlmauer798e2d32010-06-17 18:24:07 +020097 private static final String DEFAULT_TRACE_PATH_PREFIX =
Jeff Sharkeyb049e212012-09-07 23:16:01 -070098 Environment.getLegacyExternalStorageDirectory().getPath() + "/";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 private static final String DEFAULT_TRACE_BODY = "dmtrace";
100 private static final String DEFAULT_TRACE_EXTENSION = ".trace";
101 private static final String DEFAULT_TRACE_FILE_PATH =
102 DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
103 + DEFAULT_TRACE_EXTENSION;
104
105
106 /**
107 * This class is used to retrieved various statistics about the memory mappings for this
108 * process. The returns info broken down by dalvik, native, and other. All results are in kB.
109 */
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700110 public static class MemoryInfo implements Parcelable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 /** The proportional set size for dalvik. */
112 public int dalvikPss;
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700113 /** The proportional set size that is swappable for dalvik. */
114 /** @hide We may want to expose this, eventually. */
115 public int dalvikSwappablePss;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 /** The private dirty pages used by dalvik. */
117 public int dalvikPrivateDirty;
118 /** The shared dirty pages used by dalvik. */
119 public int dalvikSharedDirty;
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700120 /** The private clean pages used by dalvik. */
121 /** @hide We may want to expose this, eventually. */
122 public int dalvikPrivateClean;
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700123 /** The shared clean pages used by dalvik. */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700124 /** @hide We may want to expose this, eventually. */
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700125 public int dalvikSharedClean;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126
127 /** The proportional set size for the native heap. */
128 public int nativePss;
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700129 /** The proportional set size that is swappable for the native heap. */
130 /** @hide We may want to expose this, eventually. */
131 public int nativeSwappablePss;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 /** The private dirty pages used by the native heap. */
133 public int nativePrivateDirty;
134 /** The shared dirty pages used by the native heap. */
135 public int nativeSharedDirty;
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700136 /** The private clean pages used by the native heap. */
137 /** @hide We may want to expose this, eventually. */
138 public int nativePrivateClean;
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700139 /** The shared clean pages used by the native heap. */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700140 /** @hide We may want to expose this, eventually. */
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700141 public int nativeSharedClean;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142
143 /** The proportional set size for everything else. */
144 public int otherPss;
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700145 /** The proportional set size that is swappable for everything else. */
146 /** @hide We may want to expose this, eventually. */
147 public int otherSwappablePss;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 /** The private dirty pages used by everything else. */
149 public int otherPrivateDirty;
150 /** The shared dirty pages used by everything else. */
151 public int otherSharedDirty;
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700152 /** The private clean pages used by everything else. */
153 /** @hide We may want to expose this, eventually. */
154 public int otherPrivateClean;
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700155 /** The shared clean pages used by everything else. */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700156 /** @hide We may want to expose this, eventually. */
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700157 public int otherSharedClean;
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200158
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700159 /** @hide */
Anwar Ghuloum88887d02013-03-19 15:30:12 -0700160 public static final int NUM_OTHER_STATS = 12;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700161
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700162 /** @hide */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700163 public static final int NUM_DVK_STATS = 5;
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700164
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700165 /** @hide */
166 public static final int NUM_CATEGORIES = 6;
167
168 /** @hide */
169 public static final int offsetPss = 0;
170 /** @hide */
171 public static final int offsetSwappablePss = 1;
172 /** @hide */
173 public static final int offsetPrivateDirty = 2;
174 /** @hide */
175 public static final int offsetSharedDirty = 3;
176 /** @hide */
177 public static final int offsetPrivateClean = 4;
178 /** @hide */
179 public static final int offsetSharedClean = 5;
180
181
182 private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES];
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700183
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700184 public MemoryInfo() {
185 }
186
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700187 /**
188 * Return total PSS memory usage in kB.
189 */
190 public int getTotalPss() {
191 return dalvikPss + nativePss + otherPss;
192 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200193
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700194
195 /**
196 * Return total PSS memory usage in kB.
197 */
198 public int getTotalSwappablePss() {
199 return dalvikSwappablePss + nativeSwappablePss + otherSwappablePss;
200 }
201
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700202 /**
203 * Return total private dirty memory usage in kB.
204 */
205 public int getTotalPrivateDirty() {
206 return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty;
207 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200208
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700209 /**
210 * Return total shared dirty memory usage in kB.
211 */
212 public int getTotalSharedDirty() {
213 return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty;
214 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200215
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700216 /**
217 * Return total shared clean memory usage in kB.
218 */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700219 public int getTotalPrivateClean() {
220 return dalvikPrivateClean + nativePrivateClean + otherPrivateClean;
221 }
222
223 /**
224 * Return total shared clean memory usage in kB.
225 */
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700226 public int getTotalSharedClean() {
227 return dalvikSharedClean + nativeSharedClean + otherSharedClean;
228 }
229
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700230 /* @hide */
231 public int getOtherPss(int which) {
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700232 return otherStats[which*NUM_CATEGORIES + offsetPss];
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700233 }
234
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700235
236 /* @hide */
237 public int getOtherSwappablePss(int which) {
238 return otherStats[which*NUM_CATEGORIES + offsetSwappablePss];
239 }
240
241
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700242 /* @hide */
243 public int getOtherPrivateDirty(int which) {
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700244 return otherStats[which*NUM_CATEGORIES + offsetPrivateDirty];
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700245 }
246
247 /* @hide */
248 public int getOtherSharedDirty(int which) {
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700249 return otherStats[which*NUM_CATEGORIES + offsetSharedDirty];
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700250 }
251
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700252 /* @hide */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700253 public int getOtherPrivateClean(int which) {
254 return otherStats[which*NUM_CATEGORIES + offsetPrivateClean];
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700255 }
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700256
257
258 /* @hide */
259 public int getOtherSharedClean(int which) {
260 return otherStats[which*NUM_CATEGORIES + offsetSharedClean];
261 }
262
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700263 /* @hide */
264 public static String getOtherLabel(int which) {
265 switch (which) {
Ian Rogers7c9f30b2013-02-27 10:57:13 -0800266 case 0: return "Stack";
267 case 1: return "Cursor";
268 case 2: return "Ashmem";
269 case 3: return "Other dev";
270 case 4: return ".so mmap";
271 case 5: return ".jar mmap";
272 case 6: return ".apk mmap";
273 case 7: return ".ttf mmap";
274 case 8: return ".dex mmap";
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700275 case 9: return "code mmap";
276 case 10: return "image mmap";
Anwar Ghuloum88887d02013-03-19 15:30:12 -0700277 case 11: return "Other mmap";
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700278 case 12: return ".Heap";
279 case 13: return ".LOS";
280 case 14: return ".LinearAlloc";
281 case 15: return ".GC";
282 case 16: return ".JITCache";
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700283 default: return "????";
284 }
285 }
286
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700287 public int describeContents() {
288 return 0;
289 }
290
291 public void writeToParcel(Parcel dest, int flags) {
292 dest.writeInt(dalvikPss);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700293 dest.writeInt(dalvikSwappablePss);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700294 dest.writeInt(dalvikPrivateDirty);
295 dest.writeInt(dalvikSharedDirty);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700296 dest.writeInt(dalvikPrivateClean);
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700297 dest.writeInt(dalvikSharedClean);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700298 dest.writeInt(nativePss);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700299 dest.writeInt(nativeSwappablePss);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700300 dest.writeInt(nativePrivateDirty);
301 dest.writeInt(nativeSharedDirty);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700302 dest.writeInt(nativePrivateClean);
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700303 dest.writeInt(nativeSharedClean);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700304 dest.writeInt(otherPss);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700305 dest.writeInt(otherSwappablePss);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700306 dest.writeInt(otherPrivateDirty);
307 dest.writeInt(otherSharedDirty);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700308 dest.writeInt(otherPrivateClean);
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700309 dest.writeInt(otherSharedClean);
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700310 dest.writeIntArray(otherStats);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700311 }
312
313 public void readFromParcel(Parcel source) {
314 dalvikPss = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700315 dalvikSwappablePss = source.readInt();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700316 dalvikPrivateDirty = source.readInt();
317 dalvikSharedDirty = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700318 dalvikPrivateClean = source.readInt();
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700319 dalvikSharedClean = source.readInt();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700320 nativePss = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700321 nativeSwappablePss = source.readInt();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700322 nativePrivateDirty = source.readInt();
323 nativeSharedDirty = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700324 nativePrivateClean = source.readInt();
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700325 nativeSharedClean = source.readInt();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700326 otherPss = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700327 otherSwappablePss = source.readInt();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700328 otherPrivateDirty = source.readInt();
329 otherSharedDirty = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700330 otherPrivateClean = source.readInt();
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700331 otherSharedClean = source.readInt();
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700332 otherStats = source.createIntArray();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700333 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200334
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700335 public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
336 public MemoryInfo createFromParcel(Parcel source) {
337 return new MemoryInfo(source);
338 }
339 public MemoryInfo[] newArray(int size) {
340 return new MemoryInfo[size];
341 }
342 };
343
344 private MemoryInfo(Parcel source) {
345 readFromParcel(source);
346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 }
348
349
350 /**
351 * Wait until a debugger attaches. As soon as the debugger attaches,
352 * this returns, so you will need to place a breakpoint after the
353 * waitForDebugger() call if you want to start tracing immediately.
354 */
355 public static void waitForDebugger() {
356 if (!VMDebug.isDebuggingEnabled()) {
357 //System.out.println("debugging not enabled, not waiting");
358 return;
359 }
360 if (isDebuggerConnected())
361 return;
362
363 // if DDMS is listening, inform them of our plight
364 System.out.println("Sending WAIT chunk");
365 byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger"
366 Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1);
367 DdmServer.sendChunk(waitChunk);
368
369 mWaiting = true;
370 while (!isDebuggerConnected()) {
371 try { Thread.sleep(SPIN_DELAY); }
372 catch (InterruptedException ie) {}
373 }
374 mWaiting = false;
375
376 System.out.println("Debugger has connected");
377
378 /*
379 * There is no "ready to go" signal from the debugger, and we're
380 * not allowed to suspend ourselves -- the debugger expects us to
381 * be running happily, and gets confused if we aren't. We need to
382 * allow the debugger a chance to set breakpoints before we start
383 * running again.
384 *
385 * Sit and spin until the debugger has been idle for a short while.
386 */
387 while (true) {
388 long delta = VMDebug.lastDebuggerActivity();
389 if (delta < 0) {
390 System.out.println("debugger detached?");
391 break;
392 }
393
394 if (delta < MIN_DEBUGGER_IDLE) {
395 System.out.println("waiting for debugger to settle...");
396 try { Thread.sleep(SPIN_DELAY); }
397 catch (InterruptedException ie) {}
398 } else {
399 System.out.println("debugger has settled (" + delta + ")");
400 break;
401 }
402 }
403 }
404
405 /**
406 * Returns "true" if one or more threads is waiting for a debugger
407 * to attach.
408 */
409 public static boolean waitingForDebugger() {
410 return mWaiting;
411 }
412
413 /**
414 * Determine if a debugger is currently attached.
415 */
416 public static boolean isDebuggerConnected() {
417 return VMDebug.isDebuggerConnected();
418 }
419
420 /**
Andy McFaddene5772322010-01-22 07:23:31 -0800421 * Returns an array of strings that identify VM features. This is
422 * used by DDMS to determine what sorts of operations the VM can
423 * perform.
424 *
425 * @hide
426 */
427 public static String[] getVmFeatureList() {
428 return VMDebug.getVmFeatureList();
429 }
430
431 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 * Change the JDWP port.
433 *
434 * @deprecated no longer needed or useful
435 */
436 @Deprecated
437 public static void changeDebugPort(int port) {}
438
439 /**
440 * This is the pathname to the sysfs file that enables and disables
441 * tracing on the qemu emulator.
442 */
443 private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state";
444
445 /**
446 * Enable qemu tracing. For this to work requires running everything inside
447 * the qemu emulator; otherwise, this method will have no effect. The trace
448 * file is specified on the command line when the emulator is started. For
449 * example, the following command line <br />
450 * <code>emulator -trace foo</code><br />
451 * will start running the emulator and create a trace file named "foo". This
452 * method simply enables writing the trace records to the trace file.
453 *
454 * <p>
455 * The main differences between this and {@link #startMethodTracing()} are
456 * that tracing in the qemu emulator traces every cpu instruction of every
457 * process, including kernel code, so we have more complete information,
458 * including all context switches. We can also get more detailed information
459 * such as cache misses. The sequence of calls is determined by
460 * post-processing the instruction trace. The qemu tracing is also done
461 * without modifying the application or perturbing the timing of calls
462 * because no instrumentation is added to the application being traced.
463 * </p>
464 *
465 * <p>
466 * One limitation of using this method compared to using
467 * {@link #startMethodTracing()} on the real device is that the emulator
468 * does not model all of the real hardware effects such as memory and
469 * bus contention. The emulator also has a simple cache model and cannot
470 * capture all the complexities of a real cache.
471 * </p>
472 */
473 public static void startNativeTracing() {
474 // Open the sysfs file for writing and write "1" to it.
475 PrintWriter outStream = null;
476 try {
477 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
478 outStream = new PrintWriter(new OutputStreamWriter(fos));
479 outStream.println("1");
480 } catch (Exception e) {
481 } finally {
482 if (outStream != null)
483 outStream.close();
484 }
485
486 VMDebug.startEmulatorTracing();
487 }
488
489 /**
490 * Stop qemu tracing. See {@link #startNativeTracing()} to start tracing.
491 *
492 * <p>Tracing can be started and stopped as many times as desired. When
493 * the qemu emulator itself is stopped then the buffered trace records
494 * are flushed and written to the trace file. In fact, it is not necessary
495 * to call this method at all; simply killing qemu is sufficient. But
496 * starting and stopping a trace is useful for examining a specific
497 * region of code.</p>
498 */
499 public static void stopNativeTracing() {
500 VMDebug.stopEmulatorTracing();
501
502 // Open the sysfs file for writing and write "0" to it.
503 PrintWriter outStream = null;
504 try {
505 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
506 outStream = new PrintWriter(new OutputStreamWriter(fos));
507 outStream.println("0");
508 } catch (Exception e) {
509 // We could print an error message here but we probably want
510 // to quietly ignore errors if we are not running in the emulator.
511 } finally {
512 if (outStream != null)
513 outStream.close();
514 }
515 }
516
517 /**
518 * Enable "emulator traces", in which information about the current
519 * method is made available to the "emulator -trace" feature. There
520 * is no corresponding "disable" call -- this is intended for use by
521 * the framework when tracing should be turned on and left that way, so
522 * that traces captured with F9/F10 will include the necessary data.
523 *
524 * This puts the VM into "profile" mode, which has performance
525 * consequences.
526 *
527 * To temporarily enable tracing, use {@link #startNativeTracing()}.
528 */
529 public static void enableEmulatorTraceOutput() {
530 VMDebug.startEmulatorTracing();
531 }
532
533 /**
534 * Start method tracing with default log name and buffer size. See <a
535href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
536 * information about reading these files. Call stopMethodTracing() to stop
537 * tracing.
538 */
539 public static void startMethodTracing() {
540 VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0);
541 }
542
543 /**
544 * Start method tracing, specifying the trace log file name. The trace
545 * file will be put under "/sdcard" unless an absolute path is given.
546 * See <a
547 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
548 * information about reading trace files.
549 *
550 * @param traceName Name for the trace log file to create.
551 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
552 * If the files already exist, they will be truncated.
553 * If the trace file given does not end in ".trace", it will be appended for you.
554 */
555 public static void startMethodTracing(String traceName) {
556 startMethodTracing(traceName, 0, 0);
557 }
558
559 /**
560 * Start method tracing, specifying the trace log file name and the
561 * buffer size. The trace files will be put under "/sdcard" unless an
562 * absolute path is given. See <a
563 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
564 * information about reading trace files.
565 * @param traceName Name for the trace log file to create.
566 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
567 * If the files already exist, they will be truncated.
568 * If the trace file given does not end in ".trace", it will be appended for you.
569 *
570 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
571 */
572 public static void startMethodTracing(String traceName, int bufferSize) {
573 startMethodTracing(traceName, bufferSize, 0);
574 }
575
576 /**
577 * Start method tracing, specifying the trace log file name and the
578 * buffer size. The trace files will be put under "/sdcard" unless an
579 * absolute path is given. See <a
580 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
581 * information about reading trace files.
582 *
583 * <p>
584 * When method tracing is enabled, the VM will run more slowly than
585 * usual, so the timings from the trace files should only be considered
586 * in relative terms (e.g. was run #1 faster than run #2). The times
587 * for native methods will not change, so don't try to use this to
588 * compare the performance of interpreted and native implementations of the
589 * same method. As an alternative, consider using "native" tracing
590 * in the emulator via {@link #startNativeTracing()}.
591 * </p>
592 *
593 * @param traceName Name for the trace log file to create.
594 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
595 * If the files already exist, they will be truncated.
596 * If the trace file given does not end in ".trace", it will be appended for you.
597 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
598 */
599 public static void startMethodTracing(String traceName, int bufferSize,
600 int flags) {
601
602 String pathName = traceName;
603 if (pathName.charAt(0) != '/')
604 pathName = DEFAULT_TRACE_PATH_PREFIX + pathName;
605 if (!pathName.endsWith(DEFAULT_TRACE_EXTENSION))
606 pathName = pathName + DEFAULT_TRACE_EXTENSION;
607
608 VMDebug.startMethodTracing(pathName, bufferSize, flags);
609 }
610
611 /**
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700612 * Like startMethodTracing(String, int, int), but taking an already-opened
613 * FileDescriptor in which the trace is written. The file name is also
614 * supplied simply for logging. Makes a dup of the file descriptor.
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200615 *
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700616 * Not exposed in the SDK unless we are really comfortable with supporting
617 * this and find it would be useful.
618 * @hide
619 */
620 public static void startMethodTracing(String traceName, FileDescriptor fd,
621 int bufferSize, int flags) {
622 VMDebug.startMethodTracing(traceName, fd, bufferSize, flags);
623 }
624
625 /**
Andy McFadden72a20db0c2010-01-22 12:20:41 -0800626 * Starts method tracing without a backing file. When stopMethodTracing
627 * is called, the result is sent directly to DDMS. (If DDMS is not
628 * attached when tracing ends, the profiling data will be discarded.)
629 *
630 * @hide
631 */
632 public static void startMethodTracingDdms(int bufferSize, int flags) {
633 VMDebug.startMethodTracingDdms(bufferSize, flags);
634 }
635
636 /**
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700637 * Determine whether method tracing is currently active.
638 * @hide
639 */
640 public static boolean isMethodTracingActive() {
641 return VMDebug.isMethodTracingActive();
642 }
643
644 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 * Stop method tracing.
646 */
647 public static void stopMethodTracing() {
648 VMDebug.stopMethodTracing();
649 }
650
651 /**
652 * Get an indication of thread CPU usage. The value returned
653 * indicates the amount of time that the current thread has spent
654 * executing code or waiting for certain types of I/O.
655 *
656 * The time is expressed in nanoseconds, and is only meaningful
657 * when compared to the result from an earlier call. Note that
658 * nanosecond resolution does not imply nanosecond accuracy.
659 *
660 * On system which don't support this operation, the call returns -1.
661 */
662 public static long threadCpuTimeNanos() {
663 return VMDebug.threadCpuTimeNanos();
664 }
665
666 /**
Chet Haase2970c492010-11-09 13:58:04 -0800667 * Start counting the number and aggregate size of memory allocations.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 *
Ian Rogersfe067a42013-02-22 19:59:23 -0800669 * <p>The {@link #startAllocCounting() start} method resets the counts and enables counting.
670 * The {@link #stopAllocCounting() stop} method disables the counting so that the analysis
671 * code doesn't cause additional allocations. The various <code>get</code> methods return
672 * the specified value. And the various <code>reset</code> methods reset the specified
Chet Haase2970c492010-11-09 13:58:04 -0800673 * count.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 *
Ian Rogersfe067a42013-02-22 19:59:23 -0800675 * <p>Counts are kept for the system as a whole (global) and for each thread.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 * The per-thread counts for threads other than the current thread
Chet Haase2970c492010-11-09 13:58:04 -0800677 * are not cleared by the "reset" or "start" calls.</p>
Ian Rogersfe067a42013-02-22 19:59:23 -0800678 *
679 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 */
Ian Rogersfe067a42013-02-22 19:59:23 -0800681 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 public static void startAllocCounting() {
683 VMDebug.startAllocCounting();
684 }
Chet Haase2970c492010-11-09 13:58:04 -0800685
686 /**
687 * Stop counting the number and aggregate size of memory allocations.
688 *
689 * @see #startAllocCounting()
690 */
Ian Rogersc2a3adb2013-04-19 11:31:48 -0700691 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 public static void stopAllocCounting() {
693 VMDebug.stopAllocCounting();
694 }
695
Ian Rogersfe067a42013-02-22 19:59:23 -0800696 /**
697 * Returns the global count of objects allocated by the runtime between a
698 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
699 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 public static int getGlobalAllocCount() {
701 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
702 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800703
704 /**
705 * Clears the global count of objects allocated.
706 * @see #getGlobalAllocCount()
707 */
708 public static void resetGlobalAllocCount() {
709 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
710 }
711
712 /**
713 * Returns the global size, in bytes, of objects allocated by the runtime between a
714 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
715 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 public static int getGlobalAllocSize() {
717 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
718 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800719
720 /**
721 * Clears the global size of objects allocated.
722 * @see #getGlobalAllocCountSize()
723 */
724 public static void resetGlobalAllocSize() {
725 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
726 }
727
728 /**
729 * Returns the global count of objects freed by the runtime between a
730 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
731 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 public static int getGlobalFreedCount() {
733 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
734 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800735
736 /**
737 * Clears the global count of objects freed.
738 * @see #getGlobalFreedCount()
739 */
740 public static void resetGlobalFreedCount() {
741 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
742 }
743
744 /**
745 * Returns the global size, in bytes, of objects freed by the runtime between a
746 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
747 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 public static int getGlobalFreedSize() {
749 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
750 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800751
752 /**
753 * Clears the global size of objects freed.
754 * @see #getGlobalFreedSize()
755 */
756 public static void resetGlobalFreedSize() {
757 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
758 }
759
760 /**
761 * Returns the number of non-concurrent GC invocations between a
762 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
763 */
764 public static int getGlobalGcInvocationCount() {
765 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
766 }
767
768 /**
769 * Clears the count of non-concurrent GC invocations.
770 * @see #getGlobalGcInvocationCount()
771 */
772 public static void resetGlobalGcInvocationCount() {
773 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
774 }
775
776 /**
777 * Returns the number of classes successfully initialized (ie those that executed without
778 * throwing an exception) between a {@link #startAllocCounting() start} and
779 * {@link #stopAllocCounting() stop}.
780 */
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800781 public static int getGlobalClassInitCount() {
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800782 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
783 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800784
785 /**
786 * Clears the count of classes initialized.
787 * @see #getGlobalClassInitCount()
788 */
789 public static void resetGlobalClassInitCount() {
790 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
791 }
792
793 /**
794 * Returns the time spent successfully initializing classes between a
795 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
796 */
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800797 public static int getGlobalClassInitTime() {
798 /* cumulative elapsed time for class initialization, in usec */
799 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
800 }
Carl Shapirob5961982010-12-22 15:54:53 -0800801
802 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800803 * Clears the count of time spent initializing classes.
804 * @see #getGlobalClassInitTime()
805 */
806 public static void resetGlobalClassInitTime() {
807 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
808 }
809
810 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800811 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800812 * @deprecated This method is now obsolete.
813 */
814 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 public static int getGlobalExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800816 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 }
Carl Shapirob5961982010-12-22 15:54:53 -0800818
819 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800820 * This method exists for compatibility and has no effect.
821 * @deprecated This method is now obsolete.
822 */
823 @Deprecated
824 public static void resetGlobalExternalAllocSize() {}
825
826 /**
827 * This method exists for compatibility and has no effect.
828 * @deprecated This method is now obsolete.
829 */
830 @Deprecated
831 public static void resetGlobalExternalAllocCount() {}
832
833 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800834 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800835 * @deprecated This method is now obsolete.
836 */
837 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 public static int getGlobalExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800839 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 }
Carl Shapirob5961982010-12-22 15:54:53 -0800841
842 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800843 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800844 * @deprecated This method is now obsolete.
845 */
846 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 public static int getGlobalExternalFreedCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800848 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849 }
Carl Shapirob5961982010-12-22 15:54:53 -0800850
851 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800852 * This method exists for compatibility and has no effect.
853 * @deprecated This method is now obsolete.
854 */
855 @Deprecated
856 public static void resetGlobalExternalFreedCount() {}
857
858 /**
859 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800860 * @deprecated This method is now obsolete.
861 */
862 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 public static int getGlobalExternalFreedSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800864 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 }
Carl Shapirob5961982010-12-22 15:54:53 -0800866
Ian Rogersfe067a42013-02-22 19:59:23 -0800867 /**
868 * This method exists for compatibility and has no effect.
869 * @deprecated This method is now obsolete.
870 */
871 @Deprecated
872 public static void resetGlobalExternalFreedSize() {}
873
874 /**
875 * Returns the thread-local count of objects allocated by the runtime between a
876 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
877 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 public static int getThreadAllocCount() {
879 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
880 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800881
882 /**
883 * Clears the thread-local count of objects allocated.
884 * @see #getThreadAllocCount()
885 */
886 public static void resetThreadAllocCount() {
887 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
888 }
889
890 /**
891 * Returns the thread-local size of objects allocated by the runtime between a
892 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
893 * @return The allocated size in bytes.
894 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 public static int getThreadAllocSize() {
896 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
897 }
Carl Shapirob5961982010-12-22 15:54:53 -0800898
899 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800900 * Clears the thread-local count of objects allocated.
901 * @see #getThreadAllocSize()
902 */
903 public static void resetThreadAllocSize() {
904 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
905 }
906
907 /**
908 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800909 * @deprecated This method is now obsolete.
910 */
911 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 public static int getThreadExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800913 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 }
Carl Shapirob5961982010-12-22 15:54:53 -0800915
916 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800917 * This method exists for compatibility and has no effect.
918 * @deprecated This method is now obsolete.
919 */
920 @Deprecated
921 public static void resetThreadExternalAllocCount() {}
922
923 /**
924 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800925 * @deprecated This method is now obsolete.
926 */
927 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 public static int getThreadExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800929 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 }
Carl Shapirob5961982010-12-22 15:54:53 -0800931
Carl Shapirob5961982010-12-22 15:54:53 -0800932 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800933 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800934 * @deprecated This method is now obsolete.
935 */
936 @Deprecated
937 public static void resetThreadExternalAllocSize() {}
938
Ian Rogersfe067a42013-02-22 19:59:23 -0800939 /**
940 * Returns the number of thread-local non-concurrent GC invocations between a
941 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
942 */
943 public static int getThreadGcInvocationCount() {
944 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
945 }
946
947 /**
948 * Clears the thread-local count of non-concurrent GC invocations.
949 * @see #getThreadGcInvocationCount()
950 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 public static void resetThreadGcInvocationCount() {
952 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
953 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800954
955 /**
956 * Clears all the global and thread-local memory allocation counters.
957 * @see #startAllocCounting()
958 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 public static void resetAllCounts() {
960 VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
961 }
962
963 /**
964 * Returns the size of the native heap.
965 * @return The size of the native heap in bytes.
966 */
967 public static native long getNativeHeapSize();
968
969 /**
970 * Returns the amount of allocated memory in the native heap.
971 * @return The allocated size in bytes.
972 */
973 public static native long getNativeHeapAllocatedSize();
974
975 /**
976 * Returns the amount of free memory in the native heap.
977 * @return The freed size in bytes.
978 */
979 public static native long getNativeHeapFreeSize();
980
981 /**
982 * Retrieves information about this processes memory usages. This information is broken down by
983 * how much is in use by dalivk, the native heap, and everything else.
984 */
985 public static native void getMemoryInfo(MemoryInfo memoryInfo);
986
987 /**
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700988 * Note: currently only works when the requested pid has the same UID
989 * as the caller.
990 * @hide
991 */
992 public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
993
994 /**
Dianne Hackbornb437e092011-08-05 17:50:29 -0700995 * Retrieves the PSS memory used by the process as given by the
996 * smaps.
997 */
998 public static native long getPss();
999
1000 /**
1001 * Retrieves the PSS memory used by the process as given by the
1002 * smaps. @hide
1003 */
1004 public static native long getPss(int pid);
1005
1006 /**
Carl Shapiro11073832011-01-12 16:28:57 -08001007 * Establish an object allocation limit in the current thread.
Carl Shapiro7e942842011-01-12 17:17:45 -08001008 * This feature was never enabled in release builds. The
1009 * allocation limits feature was removed in Honeycomb. This
1010 * method exists for compatibility and always returns -1 and has
1011 * no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 *
Carl Shapiro11073832011-01-12 16:28:57 -08001013 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 */
Carl Shapiro11073832011-01-12 16:28:57 -08001015 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 public static int setAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -08001017 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 }
1019
1020 /**
Carl Shapiro11073832011-01-12 16:28:57 -08001021 * Establish a global object allocation limit. This feature was
Carl Shapiro7e942842011-01-12 17:17:45 -08001022 * never enabled in release builds. The allocation limits feature
1023 * was removed in Honeycomb. This method exists for compatibility
1024 * and always returns -1 and has no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 *
Carl Shapiro11073832011-01-12 16:28:57 -08001026 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 */
Carl Shapiro11073832011-01-12 16:28:57 -08001028 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 public static int setGlobalAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -08001030 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 }
1032
1033 /**
1034 * Dump a list of all currently loaded class to the log file.
1035 *
1036 * @param flags See constants above.
1037 */
1038 public static void printLoadedClasses(int flags) {
1039 VMDebug.printLoadedClasses(flags);
1040 }
1041
1042 /**
1043 * Get the number of loaded classes.
1044 * @return the number of loaded classes.
1045 */
1046 public static int getLoadedClassCount() {
1047 return VMDebug.getLoadedClassCount();
1048 }
1049
1050 /**
Andy McFadden824c5102010-07-09 16:26:57 -07001051 * Dump "hprof" data to the specified file. This may cause a GC.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 *
1053 * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof").
1054 * @throws UnsupportedOperationException if the VM was built without
1055 * HPROF support.
1056 * @throws IOException if an error occurs while opening or writing files.
1057 */
1058 public static void dumpHprofData(String fileName) throws IOException {
1059 VMDebug.dumpHprofData(fileName);
1060 }
1061
1062 /**
Andy McFadden824c5102010-07-09 16:26:57 -07001063 * Like dumpHprofData(String), but takes an already-opened
1064 * FileDescriptor to which the trace is written. The file name is also
1065 * supplied simply for logging. Makes a dup of the file descriptor.
1066 *
1067 * Primarily for use by the "am" shell command.
1068 *
1069 * @hide
1070 */
1071 public static void dumpHprofData(String fileName, FileDescriptor fd)
1072 throws IOException {
1073 VMDebug.dumpHprofData(fileName, fd);
1074 }
1075
1076 /**
1077 * Collect "hprof" and send it to DDMS. This may cause a GC.
Andy McFadden07a96612010-01-28 16:54:37 -08001078 *
1079 * @throws UnsupportedOperationException if the VM was built without
1080 * HPROF support.
Andy McFadden07a96612010-01-28 16:54:37 -08001081 * @hide
1082 */
1083 public static void dumpHprofDataDdms() {
1084 VMDebug.dumpHprofDataDdms();
1085 }
1086
1087 /**
Andy McFadden06a6b552010-07-13 16:28:09 -07001088 * Writes native heap data to the specified file descriptor.
1089 *
1090 * @hide
1091 */
1092 public static native void dumpNativeHeap(FileDescriptor fd);
1093
1094 /**
Brian Carlstromc21550a2010-10-05 21:34:06 -07001095 * Returns a count of the extant instances of a class.
1096 *
1097 * @hide
1098 */
1099 public static long countInstancesOfClass(Class cls) {
Brian Carlstrom7495cfa2010-11-30 18:06:00 -08001100 return VMDebug.countInstancesOfClass(cls, true);
Brian Carlstromc21550a2010-10-05 21:34:06 -07001101 }
1102
1103 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 * Returns the number of sent transactions from this process.
1105 * @return The number of sent transactions or -1 if it could not read t.
1106 */
1107 public static native int getBinderSentTransactions();
1108
1109 /**
1110 * Returns the number of received transactions from the binder driver.
1111 * @return The number of received transactions or -1 if it could not read the stats.
1112 */
1113 public static native int getBinderReceivedTransactions();
1114
1115 /**
1116 * Returns the number of active local Binder objects that exist in the
1117 * current process.
1118 */
1119 public static final native int getBinderLocalObjectCount();
1120
1121 /**
1122 * Returns the number of references to remote proxy Binder objects that
1123 * exist in the current process.
1124 */
1125 public static final native int getBinderProxyObjectCount();
1126
1127 /**
1128 * Returns the number of death notification links to Binder objects that
1129 * exist in the current process.
1130 */
1131 public static final native int getBinderDeathObjectCount();
1132
1133 /**
Andy McFadden599c9182009-04-08 00:35:56 -07001134 * Primes the register map cache.
1135 *
1136 * Only works for classes in the bootstrap class loader. Does not
1137 * cause classes to be loaded if they're not already present.
1138 *
1139 * The classAndMethodDesc argument is a concatentation of the VM-internal
1140 * class descriptor, method name, and method descriptor. Examples:
1141 * Landroid/os/Looper;.loop:()V
1142 * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V
1143 *
1144 * @param classAndMethodDesc the method to prepare
1145 *
1146 * @hide
1147 */
1148 public static final boolean cacheRegisterMap(String classAndMethodDesc) {
1149 return VMDebug.cacheRegisterMap(classAndMethodDesc);
1150 }
1151
1152 /**
Andy McFaddenbfd6d482009-10-22 17:25:57 -07001153 * Dumps the contents of VM reference tables (e.g. JNI locals and
1154 * globals) to the log file.
1155 *
1156 * @hide
1157 */
1158 public static final void dumpReferenceTables() {
1159 VMDebug.dumpReferenceTables();
1160 }
1161
1162 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 * API for gathering and querying instruction counts.
1164 *
1165 * Example usage:
Chet Haase2970c492010-11-09 13:58:04 -08001166 * <pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 * Debug.InstructionCount icount = new Debug.InstructionCount();
1168 * icount.resetAndStart();
1169 * [... do lots of stuff ...]
1170 * if (icount.collect()) {
1171 * System.out.println("Total instructions executed: "
1172 * + icount.globalTotal());
1173 * System.out.println("Method invocations: "
1174 * + icount.globalMethodInvocations());
1175 * }
Chet Haase2970c492010-11-09 13:58:04 -08001176 * </pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 */
1178 public static class InstructionCount {
Dan Bornsteinb96f5892010-12-02 17:19:53 -08001179 private static final int NUM_INSTR =
1180 OpcodeInfo.MAXIMUM_PACKED_VALUE + 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181
1182 private int[] mCounts;
1183
1184 public InstructionCount() {
1185 mCounts = new int[NUM_INSTR];
1186 }
1187
1188 /**
1189 * Reset counters and ensure counts are running. Counts may
1190 * have already been running.
1191 *
1192 * @return true if counting was started
1193 */
1194 public boolean resetAndStart() {
1195 try {
1196 VMDebug.startInstructionCounting();
1197 VMDebug.resetInstructionCount();
1198 } catch (UnsupportedOperationException uoe) {
1199 return false;
1200 }
1201 return true;
1202 }
1203
1204 /**
1205 * Collect instruction counts. May or may not stop the
1206 * counting process.
1207 */
1208 public boolean collect() {
1209 try {
1210 VMDebug.stopInstructionCounting();
1211 VMDebug.getInstructionCount(mCounts);
1212 } catch (UnsupportedOperationException uoe) {
1213 return false;
1214 }
1215 return true;
1216 }
1217
1218 /**
1219 * Return the total number of instructions executed globally (i.e. in
1220 * all threads).
1221 */
1222 public int globalTotal() {
1223 int count = 0;
Dan Bornstein1d99b062010-11-30 12:26:52 -08001224
1225 for (int i = 0; i < NUM_INSTR; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 count += mCounts[i];
Dan Bornstein1d99b062010-11-30 12:26:52 -08001227 }
1228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 return count;
1230 }
1231
1232 /**
1233 * Return the total number of method-invocation instructions
1234 * executed globally.
1235 */
1236 public int globalMethodInvocations() {
1237 int count = 0;
1238
Dan Bornstein1d99b062010-11-30 12:26:52 -08001239 for (int i = 0; i < NUM_INSTR; i++) {
1240 if (OpcodeInfo.isInvoke(i)) {
1241 count += mCounts[i];
1242 }
1243 }
1244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001245 return count;
1246 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001247 }
1248
Dave Bort1ce5bd32009-04-22 17:36:56 -07001249 /**
1250 * A Map of typed debug properties.
1251 */
1252 private static final TypedProperties debugProperties;
1253
1254 /*
1255 * Load the debug properties from the standard files into debugProperties.
1256 */
1257 static {
Joe Onorato43a17652011-04-06 19:22:23 -07001258 if (false) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001259 final String TAG = "DebugProperties";
1260 final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" };
1261 final TypedProperties tp = new TypedProperties();
1262
1263 // Read the properties from each of the files, if present.
Dave Borte9bfd9b2009-05-04 14:35:23 -07001264 for (String file : files) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001265 Reader r;
1266 try {
1267 r = new FileReader(file);
1268 } catch (FileNotFoundException ex) {
1269 // It's ok if a file is missing.
1270 continue;
1271 }
1272
Dave Bort1ce5bd32009-04-22 17:36:56 -07001273 try {
1274 tp.load(r);
Dave Borte9bfd9b2009-05-04 14:35:23 -07001275 } catch (Exception ex) {
1276 throw new RuntimeException("Problem loading " + file, ex);
1277 } finally {
1278 try {
1279 r.close();
1280 } catch (IOException ex) {
1281 // Ignore this error.
1282 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001283 }
1284 }
1285
1286 debugProperties = tp.isEmpty() ? null : tp;
1287 } else {
1288 debugProperties = null;
1289 }
1290 }
1291
1292
1293 /**
1294 * Returns true if the type of the field matches the specified class.
1295 * Handles the case where the class is, e.g., java.lang.Boolean, but
1296 * the field is of the primitive "boolean" type. Also handles all of
1297 * the java.lang.Number subclasses.
1298 */
1299 private static boolean fieldTypeMatches(Field field, Class<?> cl) {
1300 Class<?> fieldClass = field.getType();
1301 if (fieldClass == cl) {
1302 return true;
1303 }
1304 Field primitiveTypeField;
1305 try {
1306 /* All of the classes we care about (Boolean, Integer, etc.)
1307 * have a Class field called "TYPE" that points to the corresponding
1308 * primitive class.
1309 */
1310 primitiveTypeField = cl.getField("TYPE");
1311 } catch (NoSuchFieldException ex) {
1312 return false;
1313 }
1314 try {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001315 return fieldClass == (Class<?>) primitiveTypeField.get(null);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001316 } catch (IllegalAccessException ex) {
1317 return false;
1318 }
1319 }
1320
1321
1322 /**
1323 * Looks up the property that corresponds to the field, and sets the field's value
1324 * if the types match.
1325 */
Dave Borte9bfd9b2009-05-04 14:35:23 -07001326 private static void modifyFieldIfSet(final Field field, final TypedProperties properties,
1327 final String propertyName) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001328 if (field.getType() == java.lang.String.class) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001329 int stringInfo = properties.getStringInfo(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001330 switch (stringInfo) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001331 case TypedProperties.STRING_SET:
1332 // Handle as usual below.
1333 break;
1334 case TypedProperties.STRING_NULL:
1335 try {
1336 field.set(null, null); // null object for static fields; null string
1337 } catch (IllegalAccessException ex) {
1338 throw new IllegalArgumentException(
1339 "Cannot set field for " + propertyName, ex);
1340 }
1341 return;
1342 case TypedProperties.STRING_NOT_SET:
1343 return;
1344 case TypedProperties.STRING_TYPE_MISMATCH:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001345 throw new IllegalArgumentException(
Dave Borte9bfd9b2009-05-04 14:35:23 -07001346 "Type of " + propertyName + " " +
1347 " does not match field type (" + field.getType() + ")");
1348 default:
1349 throw new IllegalStateException(
1350 "Unexpected getStringInfo(" + propertyName + ") return value " +
1351 stringInfo);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001352 }
1353 }
Dave Borte9bfd9b2009-05-04 14:35:23 -07001354 Object value = properties.get(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001355 if (value != null) {
1356 if (!fieldTypeMatches(field, value.getClass())) {
1357 throw new IllegalArgumentException(
1358 "Type of " + propertyName + " (" + value.getClass() + ") " +
1359 " does not match field type (" + field.getType() + ")");
1360 }
1361 try {
1362 field.set(null, value); // null object for static fields
1363 } catch (IllegalAccessException ex) {
1364 throw new IllegalArgumentException(
1365 "Cannot set field for " + propertyName, ex);
1366 }
1367 }
1368 }
1369
1370
1371 /**
Romain Guyc4b11a72009-05-13 15:46:37 -07001372 * Equivalent to <code>setFieldsOn(cl, false)</code>.
1373 *
1374 * @see #setFieldsOn(Class, boolean)
Romain Guyd4103d02009-05-14 12:24:21 -07001375 *
1376 * @hide
Romain Guyc4b11a72009-05-13 15:46:37 -07001377 */
1378 public static void setFieldsOn(Class<?> cl) {
1379 setFieldsOn(cl, false);
1380 }
1381
1382 /**
Dave Bort1ce5bd32009-04-22 17:36:56 -07001383 * Reflectively sets static fields of a class based on internal debugging
Joe Onorato43a17652011-04-06 19:22:23 -07001384 * properties. This method is a no-op if false is
Dave Bort1ce5bd32009-04-22 17:36:56 -07001385 * false.
1386 * <p>
Joe Onorato43a17652011-04-06 19:22:23 -07001387 * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: false will
Dave Bort1ce5bd32009-04-22 17:36:56 -07001388 * always be false in release builds. This API is typically only useful
1389 * for platform developers.
1390 * </p>
1391 * Class setup: define a class whose only fields are non-final, static
1392 * primitive types (except for "char") or Strings. In a static block
1393 * after the field definitions/initializations, pass the class to
Romain Guyc4b11a72009-05-13 15:46:37 -07001394 * this method, Debug.setFieldsOn(). Example:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001395 * <pre>
1396 * package com.example;
1397 *
1398 * import android.os.Debug;
1399 *
1400 * public class MyDebugVars {
1401 * public static String s = "a string";
1402 * public static String s2 = "second string";
1403 * public static String ns = null;
1404 * public static boolean b = false;
1405 * public static int i = 5;
Romain Guyc4b11a72009-05-13 15:46:37 -07001406 * @Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001407 * public static float f = 0.1f;
Romain Guyc4b11a72009-05-13 15:46:37 -07001408 * @@Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001409 * public static double d = 0.5d;
1410 *
1411 * // This MUST appear AFTER all fields are defined and initialized!
1412 * static {
Romain Guyc4b11a72009-05-13 15:46:37 -07001413 * // Sets all the fields
Dave Borte9bfd9b2009-05-04 14:35:23 -07001414 * Debug.setFieldsOn(MyDebugVars.class);
Christian Mehlmauer798e2d32010-06-17 18:24:07 +02001415 *
Romain Guyc4b11a72009-05-13 15:46:37 -07001416 * // Sets only the fields annotated with @Debug.DebugProperty
1417 * // Debug.setFieldsOn(MyDebugVars.class, true);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001418 * }
1419 * }
1420 * </pre>
Dave Borte9bfd9b2009-05-04 14:35:23 -07001421 * setFieldsOn() may override the value of any field in the class based
Dave Bort1ce5bd32009-04-22 17:36:56 -07001422 * on internal properties that are fixed at boot time.
1423 * <p>
1424 * These properties are only set during platform debugging, and are not
1425 * meant to be used as a general-purpose properties store.
1426 *
1427 * {@hide}
1428 *
1429 * @param cl The class to (possibly) modify
Romain Guyc4b11a72009-05-13 15:46:37 -07001430 * @param partial If false, sets all static fields, otherwise, only set
1431 * fields with the {@link android.os.Debug.DebugProperty}
1432 * annotation
Dave Bort1ce5bd32009-04-22 17:36:56 -07001433 * @throws IllegalArgumentException if any fields are final or non-static,
1434 * or if the type of the field does not match the type of
1435 * the internal debugging property value.
1436 */
Romain Guyc4b11a72009-05-13 15:46:37 -07001437 public static void setFieldsOn(Class<?> cl, boolean partial) {
Joe Onorato43a17652011-04-06 19:22:23 -07001438 if (false) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001439 if (debugProperties != null) {
1440 /* Only look for fields declared directly by the class,
1441 * so we don't mysteriously change static fields in superclasses.
1442 */
1443 for (Field field : cl.getDeclaredFields()) {
Romain Guyc4b11a72009-05-13 15:46:37 -07001444 if (!partial || field.getAnnotation(DebugProperty.class) != null) {
1445 final String propertyName = cl.getName() + "." + field.getName();
1446 boolean isStatic = Modifier.isStatic(field.getModifiers());
1447 boolean isFinal = Modifier.isFinal(field.getModifiers());
1448
1449 if (!isStatic || isFinal) {
1450 throw new IllegalArgumentException(propertyName +
1451 " must be static and non-final");
1452 }
1453 modifyFieldIfSet(field, debugProperties, propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001454 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001455 }
1456 }
1457 } else {
Dan Egnor3eda9792010-03-05 13:28:36 -08001458 Log.wtf(TAG,
Dave Borte9bfd9b2009-05-04 14:35:23 -07001459 "setFieldsOn(" + (cl == null ? "null" : cl.getName()) +
Dave Bort1ce5bd32009-04-22 17:36:56 -07001460 ") called in non-DEBUG build");
1461 }
1462 }
Romain Guyc4b11a72009-05-13 15:46:37 -07001463
1464 /**
1465 * Annotation to put on fields you want to set with
1466 * {@link Debug#setFieldsOn(Class, boolean)}.
1467 *
1468 * @hide
1469 */
1470 @Target({ ElementType.FIELD })
1471 @Retention(RetentionPolicy.RUNTIME)
1472 public @interface DebugProperty {
1473 }
Dan Egnor3eda9792010-03-05 13:28:36 -08001474
1475 /**
1476 * Get a debugging dump of a system service by name.
1477 *
1478 * <p>Most services require the caller to hold android.permission.DUMP.
1479 *
1480 * @param name of the service to dump
1481 * @param fd to write dump output to (usually an output log file)
1482 * @param args to pass to the service's dump method, may be null
1483 * @return true if the service was dumped successfully, false if
1484 * the service could not be found or had an error while dumping
1485 */
1486 public static boolean dumpService(String name, FileDescriptor fd, String[] args) {
1487 IBinder service = ServiceManager.getService(name);
1488 if (service == null) {
1489 Log.e(TAG, "Can't find service to dump: " + name);
1490 return false;
1491 }
1492
1493 try {
1494 service.dump(fd, args);
1495 return true;
1496 } catch (RemoteException e) {
1497 Log.e(TAG, "Can't dump service: " + name, e);
1498 return false;
1499 }
1500 }
Craig Mautnera51a9562012-04-17 17:05:26 -07001501
1502 /**
Dianne Hackbornf72467a2012-06-08 17:23:59 -07001503 * Have the stack traces of the given native process dumped to the
1504 * specified file. Will be appended to the file.
1505 * @hide
1506 */
1507 public static native void dumpNativeBacktraceToFile(int pid, String file);
1508
1509 /**
Craig Mautnera51a9562012-04-17 17:05:26 -07001510 * Return a String describing the calling method and location at a particular stack depth.
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -07001511 * @param callStack the Thread stack
Craig Mautnera51a9562012-04-17 17:05:26 -07001512 * @param depth the depth of stack to return information for.
1513 * @return the String describing the caller at that depth.
1514 */
1515 private static String getCaller(StackTraceElement callStack[], int depth) {
1516 // callStack[4] is the caller of the method that called getCallers()
1517 if (4 + depth >= callStack.length) {
1518 return "<bottom of call stack>";
1519 }
1520 StackTraceElement caller = callStack[4 + depth];
1521 return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber();
1522 }
1523
1524 /**
1525 * Return a string consisting of methods and locations at multiple call stack levels.
1526 * @param depth the number of levels to return, starting with the immediate caller.
1527 * @return a string describing the call stack.
1528 * {@hide}
1529 */
1530 public static String getCallers(final int depth) {
1531 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
1532 StringBuffer sb = new StringBuffer();
1533 for (int i = 0; i < depth; i++) {
1534 sb.append(getCaller(callStack, i)).append(" ");
1535 }
1536 return sb.toString();
1537 }
1538
1539 /**
Dianne Hackbornef03a7f2012-10-29 18:46:52 -07001540 * Like {@link #getCallers(int)}, but each location is append to the string
1541 * as a new line with <var>linePrefix</var> in front of it.
1542 * @param depth the number of levels to return, starting with the immediate caller.
1543 * @param linePrefix prefix to put in front of each location.
1544 * @return a string describing the call stack.
1545 * {@hide}
1546 */
1547 public static String getCallers(final int depth, String linePrefix) {
1548 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
1549 StringBuffer sb = new StringBuffer();
1550 for (int i = 0; i < depth; i++) {
1551 sb.append(linePrefix).append(getCaller(callStack, i)).append("\n");
1552 }
1553 return sb.toString();
1554 }
1555
1556 /**
Ian Rogersfe067a42013-02-22 19:59:23 -08001557 * @return a String describing the immediate caller of the calling method.
Craig Mautnera51a9562012-04-17 17:05:26 -07001558 * {@hide}
1559 */
1560 public static String getCaller() {
1561 return getCaller(Thread.currentThread().getStackTrace(), 0);
1562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563}