Some debugging support.

- New feature to "am monitor" to have it automatically launch
  gdbserv for you when a crash/ANR happens, and tell you how to
  run the client.

- Update dumpstate to match new location of binder debug logs

- Various commented out logs that are being used to track down
  issues.

Change-Id: Ia5dd0cd2df983a1fc6be697642a4590aa02a26a5
This commit is contained in:
Dianne Hackborn
2010-09-24 11:16:23 -07:00
parent 6d8fae722c
commit f123e49bf0
5 changed files with 125 additions and 14 deletions

View File

@ -35,9 +35,7 @@ import android.util.AndroidException;
import android.view.IWindowManager; import android.view.IWindowManager;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@ -433,6 +431,8 @@ public class Am {
} }
class MyActivityController extends IActivityController.Stub { class MyActivityController extends IActivityController.Stub {
final String mGdbPort;
static final int STATE_NORMAL = 0; static final int STATE_NORMAL = 0;
static final int STATE_CRASHED = 1; static final int STATE_CRASHED = 1;
static final int STATE_EARLY_ANR = 2; static final int STATE_EARLY_ANR = 2;
@ -454,6 +454,14 @@ public class Am {
int mResult; int mResult;
Process mGdbProcess;
Thread mGdbThread;
boolean mGotGdbPrint;
MyActivityController(String gdbPort) {
mGdbPort = gdbPort;
}
@Override @Override
public boolean activityResuming(String pkg) throws RemoteException { public boolean activityResuming(String pkg) throws RemoteException {
synchronized (this) { synchronized (this) {
@ -483,7 +491,7 @@ public class Am {
System.out.println("stack:"); System.out.println("stack:");
System.out.print(stackTrace); System.out.print(stackTrace);
System.out.println("#"); System.out.println("#");
int result = waitControllerLocked(STATE_CRASHED); int result = waitControllerLocked(pid, STATE_CRASHED);
return result == RESULT_CRASH_KILL ? false : true; return result == RESULT_CRASH_KILL ? false : true;
} }
} }
@ -496,7 +504,7 @@ public class Am {
System.out.println("processName: " + processName); System.out.println("processName: " + processName);
System.out.println("processPid: " + pid); System.out.println("processPid: " + pid);
System.out.println("annotation: " + annotation); System.out.println("annotation: " + annotation);
int result = waitControllerLocked(STATE_EARLY_ANR); int result = waitControllerLocked(pid, STATE_EARLY_ANR);
if (result == RESULT_EARLY_ANR_KILL) return -1; if (result == RESULT_EARLY_ANR_KILL) return -1;
return 0; return 0;
} }
@ -512,14 +520,83 @@ public class Am {
System.out.println("processStats:"); System.out.println("processStats:");
System.out.print(processStats); System.out.print(processStats);
System.out.println("#"); System.out.println("#");
int result = waitControllerLocked(STATE_ANR); int result = waitControllerLocked(pid, STATE_ANR);
if (result == RESULT_ANR_KILL) return -1; if (result == RESULT_ANR_KILL) return -1;
if (result == RESULT_ANR_WAIT) return 1; if (result == RESULT_ANR_WAIT) return 1;
return 0; return 0;
} }
} }
int waitControllerLocked(int state) { void killGdbLocked() {
mGotGdbPrint = false;
if (mGdbProcess != null) {
System.out.println("Stopping gdbserver");
mGdbProcess.destroy();
mGdbProcess = null;
}
if (mGdbThread != null) {
mGdbThread.interrupt();
mGdbThread = null;
}
}
int waitControllerLocked(int pid, int state) {
if (mGdbPort != null) {
killGdbLocked();
try {
System.out.println("Starting gdbserver on port " + mGdbPort);
System.out.println("Do the following:");
System.out.println(" adb forward tcp:" + mGdbPort + " tcp:" + mGdbPort);
System.out.println(" gdbclient app_process :" + mGdbPort);
mGdbProcess = Runtime.getRuntime().exec(new String[] {
"gdbserver", ":" + mGdbPort, "--attach", Integer.toString(pid)
});
final InputStreamReader converter = new InputStreamReader(
mGdbProcess.getInputStream());
mGdbThread = new Thread() {
@Override
public void run() {
BufferedReader in = new BufferedReader(converter);
String line;
int count = 0;
while (true) {
synchronized (MyActivityController.this) {
if (mGdbThread == null) {
return;
}
if (count == 2) {
mGotGdbPrint = true;
MyActivityController.this.notifyAll();
}
}
try {
line = in.readLine();
if (line == null) {
return;
}
System.out.println("GDB: " + line);
count++;
} catch (IOException e) {
return;
}
}
}
};
mGdbThread.start();
// Stupid waiting for .5s. Doesn't matter if we end early.
try {
this.wait(500);
} catch (InterruptedException e) {
}
} catch (IOException e) {
System.err.println("Failure starting gdbserver: " + e);
killGdbLocked();
}
}
mState = state; mState = state;
System.out.println(""); System.out.println("");
printMessageForState(); printMessageForState();
@ -531,6 +608,8 @@ public class Am {
} }
} }
killGdbLocked();
return mResult; return mResult;
} }
@ -632,7 +711,19 @@ public class Am {
} }
private void runMonitor() throws Exception { private void runMonitor() throws Exception {
MyActivityController controller = new MyActivityController(); String opt;
String gdbPort = null;
while ((opt=nextOption()) != null) {
if (opt.equals("--gdb")) {
gdbPort = nextArgRequired();
} else {
System.err.println("Error: Unknown option: " + opt);
showUsage();
return;
}
}
MyActivityController controller = new MyActivityController(gdbPort);
controller.run(); controller.run();
} }
@ -806,7 +897,8 @@ public class Am {
" start profiling: am profile <PROCESS> start <FILE>\n" + " start profiling: am profile <PROCESS> start <FILE>\n" +
" stop profiling: am profile <PROCESS> stop\n" + " stop profiling: am profile <PROCESS> stop\n" +
"\n" + "\n" +
" start monitoring: am monitor\n" + " start monitoring: am monitor [--gdb <port>]\n" +
" --gdb: start gdbserv on the given port at crash/ANR\n" +
"\n" + "\n" +
" <INTENT> specifications include these flags:\n" + " <INTENT> specifications include these flags:\n" +
" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" + " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +

View File

@ -122,11 +122,11 @@ static void dumpstate() {
run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL); run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL);
run_command("LIBRANK", 10, "librank", NULL); run_command("LIBRANK", 10, "librank", NULL);
dump_file("BINDER FAILED TRANSACTION LOG", "/proc/binder/failed_transaction_log"); dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
dump_file("BINDER TRANSACTION LOG", "/proc/binder/transaction_log"); dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
dump_file("BINDER TRANSACTIONS", "/proc/binder/transactions"); dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
dump_file("BINDER STATS", "/proc/binder/stats"); dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
run_command("BINDER PROCESS STATE", 10, "sh", "-c", "cat /proc/binder/proc/*"); dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL); run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);

View File

@ -2637,6 +2637,7 @@ public final class ViewRoot extends Handler implements ViewParent,
if (DBG) Log.d(TAG, "WindowLayout in layoutWindow:" + params); if (DBG) Log.d(TAG, "WindowLayout in layoutWindow:" + params);
} }
mPendingConfiguration.seq = 0; mPendingConfiguration.seq = 0;
//Log.d(TAG, ">>>>>> CALLING relayout");
int relayoutResult = sWindowSession.relayout( int relayoutResult = sWindowSession.relayout(
mWindow, params, mWindow, params,
(int) (mView.mMeasuredWidth * appScale + 0.5f), (int) (mView.mMeasuredWidth * appScale + 0.5f),
@ -2644,6 +2645,7 @@ public final class ViewRoot extends Handler implements ViewParent,
viewVisibility, insetsPending, mWinFrame, viewVisibility, insetsPending, mWinFrame,
mPendingContentInsets, mPendingVisibleInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingConfiguration, mSurface); mPendingConfiguration, mSurface);
//Log.d(TAG, "<<<<<< BACK FROM relayout");
if (restore) { if (restore) {
params.restore(); params.restore();
} }

View File

@ -517,12 +517,26 @@ status_t IPCThreadState::transact(int32_t handle,
} }
if ((flags & TF_ONE_WAY) == 0) { if ((flags & TF_ONE_WAY) == 0) {
#if 0
if (code == 4) { // relayout
LOGI(">>>>>> CALLING transaction 4");
} else {
LOGI(">>>>>> CALLING transaction %d", code);
}
#endif
if (reply) { if (reply) {
err = waitForResponse(reply); err = waitForResponse(reply);
} else { } else {
Parcel fakeReply; Parcel fakeReply;
err = waitForResponse(&fakeReply); err = waitForResponse(&fakeReply);
} }
#if 0
if (code == 4) { // relayout
LOGI("<<<<<< RETURNING transaction 4");
} else {
LOGI("<<<<<< RETURNING transaction %d", code);
}
#endif
IF_LOG_TRANSACTIONS() { IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog); TextOutput::Bundle _b(alog);

View File

@ -5679,9 +5679,12 @@ public class WindowManagerService extends IWindowManager.Stub
int requestedWidth, int requestedHeight, int viewFlags, int requestedWidth, int requestedHeight, int viewFlags,
boolean insetsPending, Rect outFrame, Rect outContentInsets, boolean insetsPending, Rect outFrame, Rect outContentInsets,
Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
return relayoutWindow(this, window, attrs, //Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid());
int res = relayoutWindow(this, window, attrs,
requestedWidth, requestedHeight, viewFlags, insetsPending, requestedWidth, requestedHeight, viewFlags, insetsPending,
outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface); outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
//Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());
return res;
} }
public void setTransparentRegion(IWindow window, Region region) { public void setTransparentRegion(IWindow window, Region region) {