blob: 0a6db25443a452cd5431011de62b031a063f2bd4 [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
Dianne Hackborn8c841092013-06-24 13:46:13 -070019import com.android.internal.util.FastPrintWriter;
Dave Bort1ce5bd32009-04-22 17:36:56 -070020import com.android.internal.util.TypedProperties;
21
Dave Bort1ce5bd32009-04-22 17:36:56 -070022import android.util.Log;
23
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070024import java.io.FileDescriptor;
Dave Bort1ce5bd32009-04-22 17:36:56 -070025import java.io.FileNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import java.io.FileOutputStream;
Dave Bort1ce5bd32009-04-22 17:36:56 -070027import java.io.FileReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import java.io.IOException;
29import java.io.OutputStreamWriter;
30import java.io.PrintWriter;
Dave Bort1ce5bd32009-04-22 17:36:56 -070031import java.io.Reader;
32import java.lang.reflect.Field;
33import java.lang.reflect.Modifier;
Romain Guyc4b11a72009-05-13 15:46:37 -070034import java.lang.annotation.Target;
35import java.lang.annotation.ElementType;
36import java.lang.annotation.Retention;
37import java.lang.annotation.RetentionPolicy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038
39import org.apache.harmony.dalvik.ddmc.Chunk;
40import org.apache.harmony.dalvik.ddmc.ChunkHandler;
41import org.apache.harmony.dalvik.ddmc.DdmServer;
42
Dan Bornstein9f315542010-11-19 18:12:55 -080043import dalvik.bytecode.OpcodeInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import dalvik.bytecode.Opcodes;
45import dalvik.system.VMDebug;
46
47
48/**
Ian Rogersfe067a42013-02-22 19:59:23 -080049 * Provides various debugging methods for Android applications, including
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050 * tracing and allocation counts.
51 * <p><strong>Logging Trace Files</strong></p>
52 * <p>Debug can create log files that give details about an application, such as
53 * a call stack and start/stop times for any running methods. See <a
54href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
55 * information about reading trace files. To start logging trace files, call one
56 * of the startMethodTracing() methods. To stop tracing, call
57 * {@link #stopMethodTracing()}.
58 */
59public final class Debug
60{
Dan Egnor3eda9792010-03-05 13:28:36 -080061 private static final String TAG = "Debug";
62
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 /**
64 * Flags for startMethodTracing(). These can be ORed together.
65 *
66 * TRACE_COUNT_ALLOCS adds the results from startAllocCounting to the
67 * trace key file.
68 */
69 public static final int TRACE_COUNT_ALLOCS = VMDebug.TRACE_COUNT_ALLOCS;
70
71 /**
72 * Flags for printLoadedClasses(). Default behavior is to only show
73 * the class name.
74 */
75 public static final int SHOW_FULL_DETAIL = 1;
76 public static final int SHOW_CLASSLOADER = (1 << 1);
77 public static final int SHOW_INITIALIZED = (1 << 2);
78
79 // set/cleared by waitForDebugger()
80 private static volatile boolean mWaiting = false;
81
82 private Debug() {}
83
84 /*
85 * How long to wait for the debugger to finish sending requests. I've
86 * seen this hit 800msec on the device while waiting for a response
87 * to travel over USB and get processed, so we take that and add
88 * half a second.
89 */
90 private static final int MIN_DEBUGGER_IDLE = 1300; // msec
91
92 /* how long to sleep when polling for activity */
93 private static final int SPIN_DELAY = 200; // msec
94
95 /**
96 * Default trace file path and file
97 */
Christian Mehlmauer798e2d32010-06-17 18:24:07 +020098 private static final String DEFAULT_TRACE_PATH_PREFIX =
Jeff Sharkeyb049e212012-09-07 23:16:01 -070099 Environment.getLegacyExternalStorageDirectory().getPath() + "/";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 private static final String DEFAULT_TRACE_BODY = "dmtrace";
101 private static final String DEFAULT_TRACE_EXTENSION = ".trace";
102 private static final String DEFAULT_TRACE_FILE_PATH =
103 DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
104 + DEFAULT_TRACE_EXTENSION;
105
106
107 /**
108 * This class is used to retrieved various statistics about the memory mappings for this
109 * process. The returns info broken down by dalvik, native, and other. All results are in kB.
110 */
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700111 public static class MemoryInfo implements Parcelable {
Dianne Hackborn64770d12013-05-23 17:51:19 -0700112 /** The proportional set size for dalvik heap. (Doesn't include other Dalvik overhead.) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 public int dalvikPss;
Dianne Hackborn64770d12013-05-23 17:51:19 -0700114 /** The proportional set size that is swappable for dalvik heap. */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700115 /** @hide We may want to expose this, eventually. */
116 public int dalvikSwappablePss;
Dianne Hackborn64770d12013-05-23 17:51:19 -0700117 /** The private dirty pages used by dalvik heap. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 public int dalvikPrivateDirty;
Dianne Hackborn64770d12013-05-23 17:51:19 -0700119 /** The shared dirty pages used by dalvik heap. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 public int dalvikSharedDirty;
Dianne Hackborn64770d12013-05-23 17:51:19 -0700121 /** The private clean pages used by dalvik heap. */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700122 /** @hide We may want to expose this, eventually. */
123 public int dalvikPrivateClean;
Dianne Hackborn64770d12013-05-23 17:51:19 -0700124 /** The shared clean pages used by dalvik heap. */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700125 /** @hide We may want to expose this, eventually. */
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700126 public int dalvikSharedClean;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127
128 /** The proportional set size for the native heap. */
129 public int nativePss;
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700130 /** The proportional set size that is swappable for the native heap. */
131 /** @hide We may want to expose this, eventually. */
132 public int nativeSwappablePss;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 /** The private dirty pages used by the native heap. */
134 public int nativePrivateDirty;
135 /** The shared dirty pages used by the native heap. */
136 public int nativeSharedDirty;
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700137 /** The private clean pages used by the native heap. */
138 /** @hide We may want to expose this, eventually. */
139 public int nativePrivateClean;
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700140 /** The shared clean pages used by the native heap. */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700141 /** @hide We may want to expose this, eventually. */
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700142 public int nativeSharedClean;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143
144 /** The proportional set size for everything else. */
145 public int otherPss;
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700146 /** The proportional set size that is swappable for everything else. */
147 /** @hide We may want to expose this, eventually. */
148 public int otherSwappablePss;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 /** The private dirty pages used by everything else. */
150 public int otherPrivateDirty;
151 /** The shared dirty pages used by everything else. */
152 public int otherSharedDirty;
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700153 /** The private clean pages used by everything else. */
154 /** @hide We may want to expose this, eventually. */
155 public int otherPrivateClean;
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700156 /** The shared clean pages used by everything else. */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700157 /** @hide We may want to expose this, eventually. */
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700158 public int otherSharedClean;
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200159
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700160 /** @hide */
Dianne Hackborn64770d12013-05-23 17:51:19 -0700161 public static final int NUM_OTHER_STATS = 13;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700162
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700163 /** @hide */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700164 public static final int NUM_DVK_STATS = 5;
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700165
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700166 /** @hide */
167 public static final int NUM_CATEGORIES = 6;
168
169 /** @hide */
170 public static final int offsetPss = 0;
171 /** @hide */
172 public static final int offsetSwappablePss = 1;
173 /** @hide */
174 public static final int offsetPrivateDirty = 2;
175 /** @hide */
176 public static final int offsetSharedDirty = 3;
177 /** @hide */
178 public static final int offsetPrivateClean = 4;
179 /** @hide */
180 public static final int offsetSharedClean = 5;
181
182
183 private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES];
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700184
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700185 public MemoryInfo() {
186 }
187
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700188 /**
189 * Return total PSS memory usage in kB.
190 */
191 public int getTotalPss() {
192 return dalvikPss + nativePss + otherPss;
193 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200194
Dianne Hackbornc8230512013-07-13 21:32:12 -0700195 /**
196 * @hide Return total PSS memory usage in kB.
197 */
198 public int getTotalUss() {
199 return dalvikPrivateClean + dalvikPrivateDirty
200 + nativePrivateClean + nativePrivateDirty
201 + otherPrivateClean + otherPrivateDirty;
202 }
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700203
204 /**
205 * Return total PSS memory usage in kB.
206 */
207 public int getTotalSwappablePss() {
208 return dalvikSwappablePss + nativeSwappablePss + otherSwappablePss;
209 }
210
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700211 /**
212 * Return total private dirty memory usage in kB.
213 */
214 public int getTotalPrivateDirty() {
215 return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty;
216 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200217
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -0700218 /**
219 * Return total shared dirty memory usage in kB.
220 */
221 public int getTotalSharedDirty() {
222 return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty;
223 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200224
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700225 /**
226 * Return total shared clean memory usage in kB.
227 */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700228 public int getTotalPrivateClean() {
229 return dalvikPrivateClean + nativePrivateClean + otherPrivateClean;
230 }
231
232 /**
233 * Return total shared clean memory usage in kB.
234 */
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700235 public int getTotalSharedClean() {
236 return dalvikSharedClean + nativeSharedClean + otherSharedClean;
237 }
238
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700239 /* @hide */
240 public int getOtherPss(int which) {
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700241 return otherStats[which*NUM_CATEGORIES + offsetPss];
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700242 }
243
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700244
245 /* @hide */
246 public int getOtherSwappablePss(int which) {
247 return otherStats[which*NUM_CATEGORIES + offsetSwappablePss];
248 }
249
250
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700251 /* @hide */
252 public int getOtherPrivateDirty(int which) {
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700253 return otherStats[which*NUM_CATEGORIES + offsetPrivateDirty];
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700254 }
255
256 /* @hide */
257 public int getOtherSharedDirty(int which) {
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700258 return otherStats[which*NUM_CATEGORIES + offsetSharedDirty];
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700259 }
260
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700261 /* @hide */
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700262 public int getOtherPrivateClean(int which) {
263 return otherStats[which*NUM_CATEGORIES + offsetPrivateClean];
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700264 }
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700265
266
267 /* @hide */
268 public int getOtherSharedClean(int which) {
269 return otherStats[which*NUM_CATEGORIES + offsetSharedClean];
270 }
271
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700272 /* @hide */
273 public static String getOtherLabel(int which) {
274 switch (which) {
Dianne Hackborn64770d12013-05-23 17:51:19 -0700275 case 0: return "Dalvik Other";
276 case 1: return "Stack";
277 case 2: return "Cursor";
278 case 3: return "Ashmem";
279 case 4: return "Other dev";
280 case 5: return ".so mmap";
281 case 6: return ".jar mmap";
282 case 7: return ".apk mmap";
283 case 8: return ".ttf mmap";
284 case 9: return ".dex mmap";
285 case 10: return "code mmap";
286 case 11: return "image mmap";
287 case 12: return "Other mmap";
288 case 13: return ".Heap";
289 case 14: return ".LOS";
290 case 15: return ".LinearAlloc";
291 case 16: return ".GC";
292 case 17: return ".JITCache";
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700293 default: return "????";
294 }
295 }
296
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700297 public int describeContents() {
298 return 0;
299 }
300
301 public void writeToParcel(Parcel dest, int flags) {
302 dest.writeInt(dalvikPss);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700303 dest.writeInt(dalvikSwappablePss);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700304 dest.writeInt(dalvikPrivateDirty);
305 dest.writeInt(dalvikSharedDirty);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700306 dest.writeInt(dalvikPrivateClean);
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700307 dest.writeInt(dalvikSharedClean);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700308 dest.writeInt(nativePss);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700309 dest.writeInt(nativeSwappablePss);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700310 dest.writeInt(nativePrivateDirty);
311 dest.writeInt(nativeSharedDirty);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700312 dest.writeInt(nativePrivateClean);
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700313 dest.writeInt(nativeSharedClean);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700314 dest.writeInt(otherPss);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700315 dest.writeInt(otherSwappablePss);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700316 dest.writeInt(otherPrivateDirty);
317 dest.writeInt(otherSharedDirty);
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700318 dest.writeInt(otherPrivateClean);
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700319 dest.writeInt(otherSharedClean);
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700320 dest.writeIntArray(otherStats);
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700321 }
322
323 public void readFromParcel(Parcel source) {
324 dalvikPss = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700325 dalvikSwappablePss = source.readInt();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700326 dalvikPrivateDirty = source.readInt();
327 dalvikSharedDirty = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700328 dalvikPrivateClean = source.readInt();
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700329 dalvikSharedClean = source.readInt();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700330 nativePss = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700331 nativeSwappablePss = source.readInt();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700332 nativePrivateDirty = source.readInt();
333 nativeSharedDirty = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700334 nativePrivateClean = source.readInt();
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700335 nativeSharedClean = source.readInt();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700336 otherPss = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700337 otherSwappablePss = source.readInt();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700338 otherPrivateDirty = source.readInt();
339 otherSharedDirty = source.readInt();
Anwar Ghuloum3c615062013-05-13 14:18:02 -0700340 otherPrivateClean = source.readInt();
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -0700341 otherSharedClean = source.readInt();
Dianne Hackborn0e3328f2011-07-17 13:31:17 -0700342 otherStats = source.createIntArray();
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700343 }
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200344
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700345 public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
346 public MemoryInfo createFromParcel(Parcel source) {
347 return new MemoryInfo(source);
348 }
349 public MemoryInfo[] newArray(int size) {
350 return new MemoryInfo[size];
351 }
352 };
353
354 private MemoryInfo(Parcel source) {
355 readFromParcel(source);
356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 }
358
359
360 /**
361 * Wait until a debugger attaches. As soon as the debugger attaches,
362 * this returns, so you will need to place a breakpoint after the
363 * waitForDebugger() call if you want to start tracing immediately.
364 */
365 public static void waitForDebugger() {
366 if (!VMDebug.isDebuggingEnabled()) {
367 //System.out.println("debugging not enabled, not waiting");
368 return;
369 }
370 if (isDebuggerConnected())
371 return;
372
373 // if DDMS is listening, inform them of our plight
374 System.out.println("Sending WAIT chunk");
375 byte[] data = new byte[] { 0 }; // 0 == "waiting for debugger"
376 Chunk waitChunk = new Chunk(ChunkHandler.type("WAIT"), data, 0, 1);
377 DdmServer.sendChunk(waitChunk);
378
379 mWaiting = true;
380 while (!isDebuggerConnected()) {
381 try { Thread.sleep(SPIN_DELAY); }
382 catch (InterruptedException ie) {}
383 }
384 mWaiting = false;
385
386 System.out.println("Debugger has connected");
387
388 /*
389 * There is no "ready to go" signal from the debugger, and we're
390 * not allowed to suspend ourselves -- the debugger expects us to
391 * be running happily, and gets confused if we aren't. We need to
392 * allow the debugger a chance to set breakpoints before we start
393 * running again.
394 *
395 * Sit and spin until the debugger has been idle for a short while.
396 */
397 while (true) {
398 long delta = VMDebug.lastDebuggerActivity();
399 if (delta < 0) {
400 System.out.println("debugger detached?");
401 break;
402 }
403
404 if (delta < MIN_DEBUGGER_IDLE) {
405 System.out.println("waiting for debugger to settle...");
406 try { Thread.sleep(SPIN_DELAY); }
407 catch (InterruptedException ie) {}
408 } else {
409 System.out.println("debugger has settled (" + delta + ")");
410 break;
411 }
412 }
413 }
414
415 /**
416 * Returns "true" if one or more threads is waiting for a debugger
417 * to attach.
418 */
419 public static boolean waitingForDebugger() {
420 return mWaiting;
421 }
422
423 /**
424 * Determine if a debugger is currently attached.
425 */
426 public static boolean isDebuggerConnected() {
427 return VMDebug.isDebuggerConnected();
428 }
429
430 /**
Andy McFaddene5772322010-01-22 07:23:31 -0800431 * Returns an array of strings that identify VM features. This is
432 * used by DDMS to determine what sorts of operations the VM can
433 * perform.
434 *
435 * @hide
436 */
437 public static String[] getVmFeatureList() {
438 return VMDebug.getVmFeatureList();
439 }
440
441 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 * Change the JDWP port.
443 *
444 * @deprecated no longer needed or useful
445 */
446 @Deprecated
447 public static void changeDebugPort(int port) {}
448
449 /**
450 * This is the pathname to the sysfs file that enables and disables
451 * tracing on the qemu emulator.
452 */
453 private static final String SYSFS_QEMU_TRACE_STATE = "/sys/qemu_trace/state";
454
455 /**
456 * Enable qemu tracing. For this to work requires running everything inside
457 * the qemu emulator; otherwise, this method will have no effect. The trace
458 * file is specified on the command line when the emulator is started. For
459 * example, the following command line <br />
460 * <code>emulator -trace foo</code><br />
461 * will start running the emulator and create a trace file named "foo". This
462 * method simply enables writing the trace records to the trace file.
463 *
464 * <p>
465 * The main differences between this and {@link #startMethodTracing()} are
466 * that tracing in the qemu emulator traces every cpu instruction of every
467 * process, including kernel code, so we have more complete information,
468 * including all context switches. We can also get more detailed information
469 * such as cache misses. The sequence of calls is determined by
470 * post-processing the instruction trace. The qemu tracing is also done
471 * without modifying the application or perturbing the timing of calls
472 * because no instrumentation is added to the application being traced.
473 * </p>
474 *
475 * <p>
476 * One limitation of using this method compared to using
477 * {@link #startMethodTracing()} on the real device is that the emulator
478 * does not model all of the real hardware effects such as memory and
479 * bus contention. The emulator also has a simple cache model and cannot
480 * capture all the complexities of a real cache.
481 * </p>
482 */
483 public static void startNativeTracing() {
484 // Open the sysfs file for writing and write "1" to it.
485 PrintWriter outStream = null;
486 try {
487 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
Dianne Hackborn8c841092013-06-24 13:46:13 -0700488 outStream = new FastPrintWriter(fos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 outStream.println("1");
490 } catch (Exception e) {
491 } finally {
492 if (outStream != null)
493 outStream.close();
494 }
495
496 VMDebug.startEmulatorTracing();
497 }
498
499 /**
500 * Stop qemu tracing. See {@link #startNativeTracing()} to start tracing.
501 *
502 * <p>Tracing can be started and stopped as many times as desired. When
503 * the qemu emulator itself is stopped then the buffered trace records
504 * are flushed and written to the trace file. In fact, it is not necessary
505 * to call this method at all; simply killing qemu is sufficient. But
506 * starting and stopping a trace is useful for examining a specific
507 * region of code.</p>
508 */
509 public static void stopNativeTracing() {
510 VMDebug.stopEmulatorTracing();
511
512 // Open the sysfs file for writing and write "0" to it.
513 PrintWriter outStream = null;
514 try {
515 FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
Dianne Hackborn8c841092013-06-24 13:46:13 -0700516 outStream = new FastPrintWriter(fos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 outStream.println("0");
518 } catch (Exception e) {
519 // We could print an error message here but we probably want
520 // to quietly ignore errors if we are not running in the emulator.
521 } finally {
522 if (outStream != null)
523 outStream.close();
524 }
525 }
526
527 /**
528 * Enable "emulator traces", in which information about the current
529 * method is made available to the "emulator -trace" feature. There
530 * is no corresponding "disable" call -- this is intended for use by
531 * the framework when tracing should be turned on and left that way, so
532 * that traces captured with F9/F10 will include the necessary data.
533 *
534 * This puts the VM into "profile" mode, which has performance
535 * consequences.
536 *
537 * To temporarily enable tracing, use {@link #startNativeTracing()}.
538 */
539 public static void enableEmulatorTraceOutput() {
540 VMDebug.startEmulatorTracing();
541 }
542
543 /**
544 * Start method tracing with default log name and buffer size. See <a
545href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
546 * information about reading these files. Call stopMethodTracing() to stop
547 * tracing.
548 */
549 public static void startMethodTracing() {
550 VMDebug.startMethodTracing(DEFAULT_TRACE_FILE_PATH, 0, 0);
551 }
552
553 /**
554 * Start method tracing, specifying the trace log file name. The trace
555 * file will be put under "/sdcard" unless an absolute path is given.
556 * See <a
557 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
558 * information about reading trace files.
559 *
560 * @param traceName Name for the trace log file to create.
561 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
562 * If the files already exist, they will be truncated.
563 * If the trace file given does not end in ".trace", it will be appended for you.
564 */
565 public static void startMethodTracing(String traceName) {
566 startMethodTracing(traceName, 0, 0);
567 }
568
569 /**
570 * Start method tracing, specifying the trace log file name and the
571 * buffer size. The trace files will be put under "/sdcard" unless an
572 * absolute path is given. See <a
573 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
574 * information about reading trace files.
575 * @param traceName Name for the trace log file to create.
576 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
577 * If the files already exist, they will be truncated.
578 * If the trace file given does not end in ".trace", it will be appended for you.
579 *
580 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
581 */
582 public static void startMethodTracing(String traceName, int bufferSize) {
583 startMethodTracing(traceName, bufferSize, 0);
584 }
585
586 /**
587 * Start method tracing, specifying the trace log file name and the
588 * buffer size. The trace files will be put under "/sdcard" unless an
589 * absolute path is given. See <a
590 href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
591 * information about reading trace files.
592 *
593 * <p>
594 * When method tracing is enabled, the VM will run more slowly than
595 * usual, so the timings from the trace files should only be considered
596 * in relative terms (e.g. was run #1 faster than run #2). The times
597 * for native methods will not change, so don't try to use this to
598 * compare the performance of interpreted and native implementations of the
599 * same method. As an alternative, consider using "native" tracing
600 * in the emulator via {@link #startNativeTracing()}.
601 * </p>
602 *
603 * @param traceName Name for the trace log file to create.
604 * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace".
605 * If the files already exist, they will be truncated.
606 * If the trace file given does not end in ".trace", it will be appended for you.
607 * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
608 */
609 public static void startMethodTracing(String traceName, int bufferSize,
610 int flags) {
611
612 String pathName = traceName;
613 if (pathName.charAt(0) != '/')
614 pathName = DEFAULT_TRACE_PATH_PREFIX + pathName;
615 if (!pathName.endsWith(DEFAULT_TRACE_EXTENSION))
616 pathName = pathName + DEFAULT_TRACE_EXTENSION;
617
618 VMDebug.startMethodTracing(pathName, bufferSize, flags);
619 }
620
621 /**
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700622 * Like startMethodTracing(String, int, int), but taking an already-opened
623 * FileDescriptor in which the trace is written. The file name is also
624 * supplied simply for logging. Makes a dup of the file descriptor.
Christian Mehlmauer798e2d32010-06-17 18:24:07 +0200625 *
Dianne Hackborn9c8dd552009-06-23 19:22:52 -0700626 * Not exposed in the SDK unless we are really comfortable with supporting
627 * this and find it would be useful.
628 * @hide
629 */
630 public static void startMethodTracing(String traceName, FileDescriptor fd,
631 int bufferSize, int flags) {
632 VMDebug.startMethodTracing(traceName, fd, bufferSize, flags);
633 }
634
635 /**
Andy McFadden72a20db0c2010-01-22 12:20:41 -0800636 * Starts method tracing without a backing file. When stopMethodTracing
637 * is called, the result is sent directly to DDMS. (If DDMS is not
638 * attached when tracing ends, the profiling data will be discarded.)
639 *
640 * @hide
641 */
642 public static void startMethodTracingDdms(int bufferSize, int flags) {
643 VMDebug.startMethodTracingDdms(bufferSize, flags);
644 }
645
646 /**
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700647 * Determine whether method tracing is currently active.
648 * @hide
649 */
650 public static boolean isMethodTracingActive() {
651 return VMDebug.isMethodTracingActive();
652 }
653
654 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655 * Stop method tracing.
656 */
657 public static void stopMethodTracing() {
658 VMDebug.stopMethodTracing();
659 }
660
661 /**
662 * Get an indication of thread CPU usage. The value returned
663 * indicates the amount of time that the current thread has spent
664 * executing code or waiting for certain types of I/O.
665 *
666 * The time is expressed in nanoseconds, and is only meaningful
667 * when compared to the result from an earlier call. Note that
668 * nanosecond resolution does not imply nanosecond accuracy.
669 *
670 * On system which don't support this operation, the call returns -1.
671 */
672 public static long threadCpuTimeNanos() {
673 return VMDebug.threadCpuTimeNanos();
674 }
675
676 /**
Chet Haase2970c492010-11-09 13:58:04 -0800677 * Start counting the number and aggregate size of memory allocations.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 *
Ian Rogersfe067a42013-02-22 19:59:23 -0800679 * <p>The {@link #startAllocCounting() start} method resets the counts and enables counting.
680 * The {@link #stopAllocCounting() stop} method disables the counting so that the analysis
681 * code doesn't cause additional allocations. The various <code>get</code> methods return
682 * the specified value. And the various <code>reset</code> methods reset the specified
Chet Haase2970c492010-11-09 13:58:04 -0800683 * count.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 *
Ian Rogersfe067a42013-02-22 19:59:23 -0800685 * <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 -0800686 * The per-thread counts for threads other than the current thread
Chet Haase2970c492010-11-09 13:58:04 -0800687 * are not cleared by the "reset" or "start" calls.</p>
Ian Rogersfe067a42013-02-22 19:59:23 -0800688 *
689 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 */
Ian Rogersfe067a42013-02-22 19:59:23 -0800691 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 public static void startAllocCounting() {
693 VMDebug.startAllocCounting();
694 }
Chet Haase2970c492010-11-09 13:58:04 -0800695
696 /**
697 * Stop counting the number and aggregate size of memory allocations.
698 *
699 * @see #startAllocCounting()
700 */
Ian Rogersc2a3adb2013-04-19 11:31:48 -0700701 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 public static void stopAllocCounting() {
703 VMDebug.stopAllocCounting();
704 }
705
Ian Rogersfe067a42013-02-22 19:59:23 -0800706 /**
707 * Returns the global count of objects allocated by the runtime between a
708 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
709 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710 public static int getGlobalAllocCount() {
711 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
712 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800713
714 /**
715 * Clears the global count of objects allocated.
716 * @see #getGlobalAllocCount()
717 */
718 public static void resetGlobalAllocCount() {
719 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
720 }
721
722 /**
723 * Returns the global size, in bytes, of objects allocated by the runtime between a
724 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
725 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 public static int getGlobalAllocSize() {
727 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
728 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800729
730 /**
731 * Clears the global size of objects allocated.
732 * @see #getGlobalAllocCountSize()
733 */
734 public static void resetGlobalAllocSize() {
735 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
736 }
737
738 /**
739 * Returns the global count of objects freed by the runtime between a
740 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
741 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800742 public static int getGlobalFreedCount() {
743 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
744 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800745
746 /**
747 * Clears the global count of objects freed.
748 * @see #getGlobalFreedCount()
749 */
750 public static void resetGlobalFreedCount() {
751 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
752 }
753
754 /**
755 * Returns the global size, in bytes, of objects freed by the runtime between a
756 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
757 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 public static int getGlobalFreedSize() {
759 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
760 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800761
762 /**
763 * Clears the global size of objects freed.
764 * @see #getGlobalFreedSize()
765 */
766 public static void resetGlobalFreedSize() {
767 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
768 }
769
770 /**
771 * Returns the number of non-concurrent GC invocations between a
772 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
773 */
774 public static int getGlobalGcInvocationCount() {
775 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
776 }
777
778 /**
779 * Clears the count of non-concurrent GC invocations.
780 * @see #getGlobalGcInvocationCount()
781 */
782 public static void resetGlobalGcInvocationCount() {
783 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
784 }
785
786 /**
787 * Returns the number of classes successfully initialized (ie those that executed without
788 * throwing an exception) between a {@link #startAllocCounting() start} and
789 * {@link #stopAllocCounting() stop}.
790 */
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800791 public static int getGlobalClassInitCount() {
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800792 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
793 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800794
795 /**
796 * Clears the count of classes initialized.
797 * @see #getGlobalClassInitCount()
798 */
799 public static void resetGlobalClassInitCount() {
800 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
801 }
802
803 /**
804 * Returns the time spent successfully initializing classes between a
805 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
806 */
Andy McFaddenc4e1bf72010-02-22 17:07:36 -0800807 public static int getGlobalClassInitTime() {
808 /* cumulative elapsed time for class initialization, in usec */
809 return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
810 }
Carl Shapirob5961982010-12-22 15:54:53 -0800811
812 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800813 * Clears the count of time spent initializing classes.
814 * @see #getGlobalClassInitTime()
815 */
816 public static void resetGlobalClassInitTime() {
817 VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
818 }
819
820 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800821 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800822 * @deprecated This method is now obsolete.
823 */
824 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 public static int getGlobalExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800826 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 }
Carl Shapirob5961982010-12-22 15:54:53 -0800828
829 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800830 * This method exists for compatibility and has no effect.
831 * @deprecated This method is now obsolete.
832 */
833 @Deprecated
834 public static void resetGlobalExternalAllocSize() {}
835
836 /**
837 * This method exists for compatibility and has no effect.
838 * @deprecated This method is now obsolete.
839 */
840 @Deprecated
841 public static void resetGlobalExternalAllocCount() {}
842
843 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800844 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800845 * @deprecated This method is now obsolete.
846 */
847 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 public static int getGlobalExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800849 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 }
Carl Shapirob5961982010-12-22 15:54:53 -0800851
852 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800853 * This method exists for compatibility and always returns 0.
Carl Shapirob5961982010-12-22 15:54:53 -0800854 * @deprecated This method is now obsolete.
855 */
856 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857 public static int getGlobalExternalFreedCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800858 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 }
Carl Shapirob5961982010-12-22 15:54:53 -0800860
861 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800862 * This method exists for compatibility and has no effect.
863 * @deprecated This method is now obsolete.
864 */
865 @Deprecated
866 public static void resetGlobalExternalFreedCount() {}
867
868 /**
869 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800870 * @deprecated This method is now obsolete.
871 */
872 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 public static int getGlobalExternalFreedSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800874 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 }
Carl Shapirob5961982010-12-22 15:54:53 -0800876
Ian Rogersfe067a42013-02-22 19:59:23 -0800877 /**
878 * This method exists for compatibility and has no effect.
879 * @deprecated This method is now obsolete.
880 */
881 @Deprecated
882 public static void resetGlobalExternalFreedSize() {}
883
884 /**
885 * Returns the thread-local count of objects allocated by the runtime between a
886 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
887 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888 public static int getThreadAllocCount() {
889 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
890 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800891
892 /**
893 * Clears the thread-local count of objects allocated.
894 * @see #getThreadAllocCount()
895 */
896 public static void resetThreadAllocCount() {
897 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
898 }
899
900 /**
901 * Returns the thread-local size of objects allocated by the runtime between a
902 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
903 * @return The allocated size in bytes.
904 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 public static int getThreadAllocSize() {
906 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
907 }
Carl Shapirob5961982010-12-22 15:54:53 -0800908
909 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800910 * Clears the thread-local count of objects allocated.
911 * @see #getThreadAllocSize()
912 */
913 public static void resetThreadAllocSize() {
914 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
915 }
916
917 /**
918 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800919 * @deprecated This method is now obsolete.
920 */
921 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 public static int getThreadExternalAllocCount() {
Carl Shapirob5961982010-12-22 15:54:53 -0800923 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 }
Carl Shapirob5961982010-12-22 15:54:53 -0800925
926 /**
Ian Rogersfe067a42013-02-22 19:59:23 -0800927 * This method exists for compatibility and has no effect.
928 * @deprecated This method is now obsolete.
929 */
930 @Deprecated
931 public static void resetThreadExternalAllocCount() {}
932
933 /**
934 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800935 * @deprecated This method is now obsolete.
936 */
937 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 public static int getThreadExternalAllocSize() {
Carl Shapirob5961982010-12-22 15:54:53 -0800939 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 }
Carl Shapirob5961982010-12-22 15:54:53 -0800941
Carl Shapirob5961982010-12-22 15:54:53 -0800942 /**
Carl Shapiro7e942842011-01-12 17:17:45 -0800943 * This method exists for compatibility and has no effect.
Carl Shapirob5961982010-12-22 15:54:53 -0800944 * @deprecated This method is now obsolete.
945 */
946 @Deprecated
947 public static void resetThreadExternalAllocSize() {}
948
Ian Rogersfe067a42013-02-22 19:59:23 -0800949 /**
950 * Returns the number of thread-local non-concurrent GC invocations between a
951 * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
952 */
953 public static int getThreadGcInvocationCount() {
954 return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
955 }
956
957 /**
958 * Clears the thread-local count of non-concurrent GC invocations.
959 * @see #getThreadGcInvocationCount()
960 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 public static void resetThreadGcInvocationCount() {
962 VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
963 }
Ian Rogersfe067a42013-02-22 19:59:23 -0800964
965 /**
966 * Clears all the global and thread-local memory allocation counters.
967 * @see #startAllocCounting()
968 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969 public static void resetAllCounts() {
970 VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
971 }
972
973 /**
974 * Returns the size of the native heap.
975 * @return The size of the native heap in bytes.
976 */
977 public static native long getNativeHeapSize();
978
979 /**
980 * Returns the amount of allocated memory in the native heap.
981 * @return The allocated size in bytes.
982 */
983 public static native long getNativeHeapAllocatedSize();
984
985 /**
986 * Returns the amount of free memory in the native heap.
987 * @return The freed size in bytes.
988 */
989 public static native long getNativeHeapFreeSize();
990
991 /**
992 * Retrieves information about this processes memory usages. This information is broken down by
993 * how much is in use by dalivk, the native heap, and everything else.
994 */
995 public static native void getMemoryInfo(MemoryInfo memoryInfo);
996
997 /**
Dianne Hackborn3025ef32009-08-31 21:31:47 -0700998 * Note: currently only works when the requested pid has the same UID
999 * as the caller.
1000 * @hide
1001 */
1002 public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
1003
1004 /**
Dianne Hackbornb437e092011-08-05 17:50:29 -07001005 * Retrieves the PSS memory used by the process as given by the
1006 * smaps.
1007 */
1008 public static native long getPss();
1009
1010 /**
1011 * Retrieves the PSS memory used by the process as given by the
Dianne Hackbornc8230512013-07-13 21:32:12 -07001012 * smaps. Optionally supply a long array of 1 entry to also
1013 * receive the uss of the process. @hide
Dianne Hackbornb437e092011-08-05 17:50:29 -07001014 */
Dianne Hackbornc8230512013-07-13 21:32:12 -07001015 public static native long getPss(int pid, long[] outUss);
Dianne Hackbornb437e092011-08-05 17:50:29 -07001016
1017 /**
Carl Shapiro11073832011-01-12 16:28:57 -08001018 * Establish an object allocation limit in the current thread.
Carl Shapiro7e942842011-01-12 17:17:45 -08001019 * This feature was never enabled in release builds. The
1020 * allocation limits feature was removed in Honeycomb. This
1021 * method exists for compatibility and always returns -1 and has
1022 * no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 *
Carl Shapiro11073832011-01-12 16:28:57 -08001024 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 */
Carl Shapiro11073832011-01-12 16:28:57 -08001026 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 public static int setAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -08001028 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 }
1030
1031 /**
Carl Shapiro11073832011-01-12 16:28:57 -08001032 * Establish a global object allocation limit. This feature was
Carl Shapiro7e942842011-01-12 17:17:45 -08001033 * never enabled in release builds. The allocation limits feature
1034 * was removed in Honeycomb. This method exists for compatibility
1035 * and always returns -1 and has no effect.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001036 *
Carl Shapiro11073832011-01-12 16:28:57 -08001037 * @deprecated This method is now obsolete.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 */
Carl Shapiro11073832011-01-12 16:28:57 -08001039 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 public static int setGlobalAllocationLimit(int limit) {
Carl Shapiro11073832011-01-12 16:28:57 -08001041 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 }
1043
1044 /**
1045 * Dump a list of all currently loaded class to the log file.
1046 *
1047 * @param flags See constants above.
1048 */
1049 public static void printLoadedClasses(int flags) {
1050 VMDebug.printLoadedClasses(flags);
1051 }
1052
1053 /**
1054 * Get the number of loaded classes.
1055 * @return the number of loaded classes.
1056 */
1057 public static int getLoadedClassCount() {
1058 return VMDebug.getLoadedClassCount();
1059 }
1060
1061 /**
Andy McFadden824c5102010-07-09 16:26:57 -07001062 * Dump "hprof" data to the specified file. This may cause a GC.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 *
1064 * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof").
1065 * @throws UnsupportedOperationException if the VM was built without
1066 * HPROF support.
1067 * @throws IOException if an error occurs while opening or writing files.
1068 */
1069 public static void dumpHprofData(String fileName) throws IOException {
1070 VMDebug.dumpHprofData(fileName);
1071 }
1072
1073 /**
Andy McFadden824c5102010-07-09 16:26:57 -07001074 * Like dumpHprofData(String), but takes an already-opened
1075 * FileDescriptor to which the trace is written. The file name is also
1076 * supplied simply for logging. Makes a dup of the file descriptor.
1077 *
1078 * Primarily for use by the "am" shell command.
1079 *
1080 * @hide
1081 */
1082 public static void dumpHprofData(String fileName, FileDescriptor fd)
1083 throws IOException {
1084 VMDebug.dumpHprofData(fileName, fd);
1085 }
1086
1087 /**
1088 * Collect "hprof" and send it to DDMS. This may cause a GC.
Andy McFadden07a96612010-01-28 16:54:37 -08001089 *
1090 * @throws UnsupportedOperationException if the VM was built without
1091 * HPROF support.
Andy McFadden07a96612010-01-28 16:54:37 -08001092 * @hide
1093 */
1094 public static void dumpHprofDataDdms() {
1095 VMDebug.dumpHprofDataDdms();
1096 }
1097
1098 /**
Andy McFadden06a6b552010-07-13 16:28:09 -07001099 * Writes native heap data to the specified file descriptor.
1100 *
1101 * @hide
1102 */
1103 public static native void dumpNativeHeap(FileDescriptor fd);
1104
1105 /**
Brian Carlstromc21550a2010-10-05 21:34:06 -07001106 * Returns a count of the extant instances of a class.
1107 *
1108 * @hide
1109 */
1110 public static long countInstancesOfClass(Class cls) {
Brian Carlstrom7495cfa2010-11-30 18:06:00 -08001111 return VMDebug.countInstancesOfClass(cls, true);
Brian Carlstromc21550a2010-10-05 21:34:06 -07001112 }
1113
1114 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 * Returns the number of sent transactions from this process.
1116 * @return The number of sent transactions or -1 if it could not read t.
1117 */
1118 public static native int getBinderSentTransactions();
1119
1120 /**
1121 * Returns the number of received transactions from the binder driver.
1122 * @return The number of received transactions or -1 if it could not read the stats.
1123 */
1124 public static native int getBinderReceivedTransactions();
1125
1126 /**
1127 * Returns the number of active local Binder objects that exist in the
1128 * current process.
1129 */
1130 public static final native int getBinderLocalObjectCount();
1131
1132 /**
1133 * Returns the number of references to remote proxy Binder objects that
1134 * exist in the current process.
1135 */
1136 public static final native int getBinderProxyObjectCount();
1137
1138 /**
1139 * Returns the number of death notification links to Binder objects that
1140 * exist in the current process.
1141 */
1142 public static final native int getBinderDeathObjectCount();
1143
1144 /**
Andy McFadden599c9182009-04-08 00:35:56 -07001145 * Primes the register map cache.
1146 *
1147 * Only works for classes in the bootstrap class loader. Does not
1148 * cause classes to be loaded if they're not already present.
1149 *
1150 * The classAndMethodDesc argument is a concatentation of the VM-internal
1151 * class descriptor, method name, and method descriptor. Examples:
1152 * Landroid/os/Looper;.loop:()V
1153 * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V
1154 *
1155 * @param classAndMethodDesc the method to prepare
1156 *
1157 * @hide
1158 */
1159 public static final boolean cacheRegisterMap(String classAndMethodDesc) {
1160 return VMDebug.cacheRegisterMap(classAndMethodDesc);
1161 }
1162
1163 /**
Andy McFaddenbfd6d482009-10-22 17:25:57 -07001164 * Dumps the contents of VM reference tables (e.g. JNI locals and
1165 * globals) to the log file.
1166 *
1167 * @hide
1168 */
1169 public static final void dumpReferenceTables() {
1170 VMDebug.dumpReferenceTables();
1171 }
1172
1173 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 * API for gathering and querying instruction counts.
1175 *
1176 * Example usage:
Chet Haase2970c492010-11-09 13:58:04 -08001177 * <pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 * Debug.InstructionCount icount = new Debug.InstructionCount();
1179 * icount.resetAndStart();
1180 * [... do lots of stuff ...]
1181 * if (icount.collect()) {
1182 * System.out.println("Total instructions executed: "
1183 * + icount.globalTotal());
1184 * System.out.println("Method invocations: "
1185 * + icount.globalMethodInvocations());
1186 * }
Chet Haase2970c492010-11-09 13:58:04 -08001187 * </pre>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001188 */
1189 public static class InstructionCount {
Dan Bornsteinb96f5892010-12-02 17:19:53 -08001190 private static final int NUM_INSTR =
1191 OpcodeInfo.MAXIMUM_PACKED_VALUE + 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192
1193 private int[] mCounts;
1194
1195 public InstructionCount() {
1196 mCounts = new int[NUM_INSTR];
1197 }
1198
1199 /**
1200 * Reset counters and ensure counts are running. Counts may
1201 * have already been running.
1202 *
1203 * @return true if counting was started
1204 */
1205 public boolean resetAndStart() {
1206 try {
1207 VMDebug.startInstructionCounting();
1208 VMDebug.resetInstructionCount();
1209 } catch (UnsupportedOperationException uoe) {
1210 return false;
1211 }
1212 return true;
1213 }
1214
1215 /**
1216 * Collect instruction counts. May or may not stop the
1217 * counting process.
1218 */
1219 public boolean collect() {
1220 try {
1221 VMDebug.stopInstructionCounting();
1222 VMDebug.getInstructionCount(mCounts);
1223 } catch (UnsupportedOperationException uoe) {
1224 return false;
1225 }
1226 return true;
1227 }
1228
1229 /**
1230 * Return the total number of instructions executed globally (i.e. in
1231 * all threads).
1232 */
1233 public int globalTotal() {
1234 int count = 0;
Dan Bornstein1d99b062010-11-30 12:26:52 -08001235
1236 for (int i = 0; i < NUM_INSTR; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 count += mCounts[i];
Dan Bornstein1d99b062010-11-30 12:26:52 -08001238 }
1239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 return count;
1241 }
1242
1243 /**
1244 * Return the total number of method-invocation instructions
1245 * executed globally.
1246 */
1247 public int globalMethodInvocations() {
1248 int count = 0;
1249
Dan Bornstein1d99b062010-11-30 12:26:52 -08001250 for (int i = 0; i < NUM_INSTR; i++) {
1251 if (OpcodeInfo.isInvoke(i)) {
1252 count += mCounts[i];
1253 }
1254 }
1255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 return count;
1257 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001258 }
1259
Dave Bort1ce5bd32009-04-22 17:36:56 -07001260 /**
1261 * A Map of typed debug properties.
1262 */
1263 private static final TypedProperties debugProperties;
1264
1265 /*
1266 * Load the debug properties from the standard files into debugProperties.
1267 */
1268 static {
Joe Onorato43a17652011-04-06 19:22:23 -07001269 if (false) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001270 final String TAG = "DebugProperties";
1271 final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" };
1272 final TypedProperties tp = new TypedProperties();
1273
1274 // Read the properties from each of the files, if present.
Dave Borte9bfd9b2009-05-04 14:35:23 -07001275 for (String file : files) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001276 Reader r;
1277 try {
1278 r = new FileReader(file);
1279 } catch (FileNotFoundException ex) {
1280 // It's ok if a file is missing.
1281 continue;
1282 }
1283
Dave Bort1ce5bd32009-04-22 17:36:56 -07001284 try {
1285 tp.load(r);
Dave Borte9bfd9b2009-05-04 14:35:23 -07001286 } catch (Exception ex) {
1287 throw new RuntimeException("Problem loading " + file, ex);
1288 } finally {
1289 try {
1290 r.close();
1291 } catch (IOException ex) {
1292 // Ignore this error.
1293 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001294 }
1295 }
1296
1297 debugProperties = tp.isEmpty() ? null : tp;
1298 } else {
1299 debugProperties = null;
1300 }
1301 }
1302
1303
1304 /**
1305 * Returns true if the type of the field matches the specified class.
1306 * Handles the case where the class is, e.g., java.lang.Boolean, but
1307 * the field is of the primitive "boolean" type. Also handles all of
1308 * the java.lang.Number subclasses.
1309 */
1310 private static boolean fieldTypeMatches(Field field, Class<?> cl) {
1311 Class<?> fieldClass = field.getType();
1312 if (fieldClass == cl) {
1313 return true;
1314 }
1315 Field primitiveTypeField;
1316 try {
1317 /* All of the classes we care about (Boolean, Integer, etc.)
1318 * have a Class field called "TYPE" that points to the corresponding
1319 * primitive class.
1320 */
1321 primitiveTypeField = cl.getField("TYPE");
1322 } catch (NoSuchFieldException ex) {
1323 return false;
1324 }
1325 try {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001326 return fieldClass == (Class<?>) primitiveTypeField.get(null);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001327 } catch (IllegalAccessException ex) {
1328 return false;
1329 }
1330 }
1331
1332
1333 /**
1334 * Looks up the property that corresponds to the field, and sets the field's value
1335 * if the types match.
1336 */
Dave Borte9bfd9b2009-05-04 14:35:23 -07001337 private static void modifyFieldIfSet(final Field field, final TypedProperties properties,
1338 final String propertyName) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001339 if (field.getType() == java.lang.String.class) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001340 int stringInfo = properties.getStringInfo(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001341 switch (stringInfo) {
Dave Borte9bfd9b2009-05-04 14:35:23 -07001342 case TypedProperties.STRING_SET:
1343 // Handle as usual below.
1344 break;
1345 case TypedProperties.STRING_NULL:
1346 try {
1347 field.set(null, null); // null object for static fields; null string
1348 } catch (IllegalAccessException ex) {
1349 throw new IllegalArgumentException(
1350 "Cannot set field for " + propertyName, ex);
1351 }
1352 return;
1353 case TypedProperties.STRING_NOT_SET:
1354 return;
1355 case TypedProperties.STRING_TYPE_MISMATCH:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001356 throw new IllegalArgumentException(
Dave Borte9bfd9b2009-05-04 14:35:23 -07001357 "Type of " + propertyName + " " +
1358 " does not match field type (" + field.getType() + ")");
1359 default:
1360 throw new IllegalStateException(
1361 "Unexpected getStringInfo(" + propertyName + ") return value " +
1362 stringInfo);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001363 }
1364 }
Dave Borte9bfd9b2009-05-04 14:35:23 -07001365 Object value = properties.get(propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001366 if (value != null) {
1367 if (!fieldTypeMatches(field, value.getClass())) {
1368 throw new IllegalArgumentException(
1369 "Type of " + propertyName + " (" + value.getClass() + ") " +
1370 " does not match field type (" + field.getType() + ")");
1371 }
1372 try {
1373 field.set(null, value); // null object for static fields
1374 } catch (IllegalAccessException ex) {
1375 throw new IllegalArgumentException(
1376 "Cannot set field for " + propertyName, ex);
1377 }
1378 }
1379 }
1380
1381
1382 /**
Romain Guyc4b11a72009-05-13 15:46:37 -07001383 * Equivalent to <code>setFieldsOn(cl, false)</code>.
1384 *
1385 * @see #setFieldsOn(Class, boolean)
Romain Guyd4103d02009-05-14 12:24:21 -07001386 *
1387 * @hide
Romain Guyc4b11a72009-05-13 15:46:37 -07001388 */
1389 public static void setFieldsOn(Class<?> cl) {
1390 setFieldsOn(cl, false);
1391 }
1392
1393 /**
Dave Bort1ce5bd32009-04-22 17:36:56 -07001394 * Reflectively sets static fields of a class based on internal debugging
Joe Onorato43a17652011-04-06 19:22:23 -07001395 * properties. This method is a no-op if false is
Dave Bort1ce5bd32009-04-22 17:36:56 -07001396 * false.
1397 * <p>
Joe Onorato43a17652011-04-06 19:22:23 -07001398 * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: false will
Dave Bort1ce5bd32009-04-22 17:36:56 -07001399 * always be false in release builds. This API is typically only useful
1400 * for platform developers.
1401 * </p>
1402 * Class setup: define a class whose only fields are non-final, static
1403 * primitive types (except for "char") or Strings. In a static block
1404 * after the field definitions/initializations, pass the class to
Romain Guyc4b11a72009-05-13 15:46:37 -07001405 * this method, Debug.setFieldsOn(). Example:
Dave Bort1ce5bd32009-04-22 17:36:56 -07001406 * <pre>
1407 * package com.example;
1408 *
1409 * import android.os.Debug;
1410 *
1411 * public class MyDebugVars {
1412 * public static String s = "a string";
1413 * public static String s2 = "second string";
1414 * public static String ns = null;
1415 * public static boolean b = false;
1416 * public static int i = 5;
Romain Guyc4b11a72009-05-13 15:46:37 -07001417 * @Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001418 * public static float f = 0.1f;
Romain Guyc4b11a72009-05-13 15:46:37 -07001419 * @@Debug.DebugProperty
Dave Bort1ce5bd32009-04-22 17:36:56 -07001420 * public static double d = 0.5d;
1421 *
1422 * // This MUST appear AFTER all fields are defined and initialized!
1423 * static {
Romain Guyc4b11a72009-05-13 15:46:37 -07001424 * // Sets all the fields
Dave Borte9bfd9b2009-05-04 14:35:23 -07001425 * Debug.setFieldsOn(MyDebugVars.class);
Christian Mehlmauer798e2d32010-06-17 18:24:07 +02001426 *
Romain Guyc4b11a72009-05-13 15:46:37 -07001427 * // Sets only the fields annotated with @Debug.DebugProperty
1428 * // Debug.setFieldsOn(MyDebugVars.class, true);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001429 * }
1430 * }
1431 * </pre>
Dave Borte9bfd9b2009-05-04 14:35:23 -07001432 * setFieldsOn() may override the value of any field in the class based
Dave Bort1ce5bd32009-04-22 17:36:56 -07001433 * on internal properties that are fixed at boot time.
1434 * <p>
1435 * These properties are only set during platform debugging, and are not
1436 * meant to be used as a general-purpose properties store.
1437 *
1438 * {@hide}
1439 *
1440 * @param cl The class to (possibly) modify
Romain Guyc4b11a72009-05-13 15:46:37 -07001441 * @param partial If false, sets all static fields, otherwise, only set
1442 * fields with the {@link android.os.Debug.DebugProperty}
1443 * annotation
Dave Bort1ce5bd32009-04-22 17:36:56 -07001444 * @throws IllegalArgumentException if any fields are final or non-static,
1445 * or if the type of the field does not match the type of
1446 * the internal debugging property value.
1447 */
Romain Guyc4b11a72009-05-13 15:46:37 -07001448 public static void setFieldsOn(Class<?> cl, boolean partial) {
Joe Onorato43a17652011-04-06 19:22:23 -07001449 if (false) {
Dave Bort1ce5bd32009-04-22 17:36:56 -07001450 if (debugProperties != null) {
1451 /* Only look for fields declared directly by the class,
1452 * so we don't mysteriously change static fields in superclasses.
1453 */
1454 for (Field field : cl.getDeclaredFields()) {
Romain Guyc4b11a72009-05-13 15:46:37 -07001455 if (!partial || field.getAnnotation(DebugProperty.class) != null) {
1456 final String propertyName = cl.getName() + "." + field.getName();
1457 boolean isStatic = Modifier.isStatic(field.getModifiers());
1458 boolean isFinal = Modifier.isFinal(field.getModifiers());
1459
1460 if (!isStatic || isFinal) {
1461 throw new IllegalArgumentException(propertyName +
1462 " must be static and non-final");
1463 }
1464 modifyFieldIfSet(field, debugProperties, propertyName);
Dave Bort1ce5bd32009-04-22 17:36:56 -07001465 }
Dave Bort1ce5bd32009-04-22 17:36:56 -07001466 }
1467 }
1468 } else {
Dan Egnor3eda9792010-03-05 13:28:36 -08001469 Log.wtf(TAG,
Dave Borte9bfd9b2009-05-04 14:35:23 -07001470 "setFieldsOn(" + (cl == null ? "null" : cl.getName()) +
Dave Bort1ce5bd32009-04-22 17:36:56 -07001471 ") called in non-DEBUG build");
1472 }
1473 }
Romain Guyc4b11a72009-05-13 15:46:37 -07001474
1475 /**
1476 * Annotation to put on fields you want to set with
1477 * {@link Debug#setFieldsOn(Class, boolean)}.
1478 *
1479 * @hide
1480 */
1481 @Target({ ElementType.FIELD })
1482 @Retention(RetentionPolicy.RUNTIME)
1483 public @interface DebugProperty {
1484 }
Dan Egnor3eda9792010-03-05 13:28:36 -08001485
1486 /**
1487 * Get a debugging dump of a system service by name.
1488 *
1489 * <p>Most services require the caller to hold android.permission.DUMP.
1490 *
1491 * @param name of the service to dump
1492 * @param fd to write dump output to (usually an output log file)
1493 * @param args to pass to the service's dump method, may be null
1494 * @return true if the service was dumped successfully, false if
1495 * the service could not be found or had an error while dumping
1496 */
1497 public static boolean dumpService(String name, FileDescriptor fd, String[] args) {
1498 IBinder service = ServiceManager.getService(name);
1499 if (service == null) {
1500 Log.e(TAG, "Can't find service to dump: " + name);
1501 return false;
1502 }
1503
1504 try {
1505 service.dump(fd, args);
1506 return true;
1507 } catch (RemoteException e) {
1508 Log.e(TAG, "Can't dump service: " + name, e);
1509 return false;
1510 }
1511 }
Craig Mautnera51a9562012-04-17 17:05:26 -07001512
1513 /**
Dianne Hackbornf72467a2012-06-08 17:23:59 -07001514 * Have the stack traces of the given native process dumped to the
1515 * specified file. Will be appended to the file.
1516 * @hide
1517 */
1518 public static native void dumpNativeBacktraceToFile(int pid, String file);
1519
1520 /**
Craig Mautnera51a9562012-04-17 17:05:26 -07001521 * Return a String describing the calling method and location at a particular stack depth.
Anwar Ghuloum3a8ce1b2013-04-26 16:18:28 -07001522 * @param callStack the Thread stack
Craig Mautnera51a9562012-04-17 17:05:26 -07001523 * @param depth the depth of stack to return information for.
1524 * @return the String describing the caller at that depth.
1525 */
1526 private static String getCaller(StackTraceElement callStack[], int depth) {
1527 // callStack[4] is the caller of the method that called getCallers()
1528 if (4 + depth >= callStack.length) {
1529 return "<bottom of call stack>";
1530 }
1531 StackTraceElement caller = callStack[4 + depth];
1532 return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber();
1533 }
1534
1535 /**
1536 * Return a string consisting of methods and locations at multiple call stack levels.
1537 * @param depth the number of levels to return, starting with the immediate caller.
1538 * @return a string describing the call stack.
1539 * {@hide}
1540 */
1541 public static String getCallers(final int depth) {
1542 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
1543 StringBuffer sb = new StringBuffer();
1544 for (int i = 0; i < depth; i++) {
1545 sb.append(getCaller(callStack, i)).append(" ");
1546 }
1547 return sb.toString();
1548 }
1549
1550 /**
Dianne Hackbornef03a7f2012-10-29 18:46:52 -07001551 * Like {@link #getCallers(int)}, but each location is append to the string
1552 * as a new line with <var>linePrefix</var> in front of it.
1553 * @param depth the number of levels to return, starting with the immediate caller.
1554 * @param linePrefix prefix to put in front of each location.
1555 * @return a string describing the call stack.
1556 * {@hide}
1557 */
1558 public static String getCallers(final int depth, String linePrefix) {
1559 final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
1560 StringBuffer sb = new StringBuffer();
1561 for (int i = 0; i < depth; i++) {
1562 sb.append(linePrefix).append(getCaller(callStack, i)).append("\n");
1563 }
1564 return sb.toString();
1565 }
1566
1567 /**
Ian Rogersfe067a42013-02-22 19:59:23 -08001568 * @return a String describing the immediate caller of the calling method.
Craig Mautnera51a9562012-04-17 17:05:26 -07001569 * {@hide}
1570 */
1571 public static String getCaller() {
1572 return getCaller(Thread.currentThread().getStackTrace(), 0);
1573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574}