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
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 194e8e1..f2aa91f 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -35,9 +35,7 @@
 import android.view.IWindowManager;
 
 import java.io.BufferedReader;
-import java.io.DataInputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStreamReader;
@@ -433,6 +431,8 @@
     }
 
     class MyActivityController extends IActivityController.Stub {
+        final String mGdbPort;
+
         static final int STATE_NORMAL = 0;
         static final int STATE_CRASHED = 1;
         static final int STATE_EARLY_ANR = 2;
@@ -454,6 +454,14 @@
 
         int mResult;
 
+        Process mGdbProcess;
+        Thread mGdbThread;
+        boolean mGotGdbPrint;
+
+        MyActivityController(String gdbPort) {
+            mGdbPort = gdbPort;
+        }
+
         @Override
         public boolean activityResuming(String pkg) throws RemoteException {
             synchronized (this) {
@@ -483,7 +491,7 @@
                 System.out.println("stack:");
                 System.out.print(stackTrace);
                 System.out.println("#");
-                int result = waitControllerLocked(STATE_CRASHED);
+                int result = waitControllerLocked(pid, STATE_CRASHED);
                 return result == RESULT_CRASH_KILL ? false : true;
             }
         }
@@ -496,7 +504,7 @@
                 System.out.println("processName: " + processName);
                 System.out.println("processPid: " + pid);
                 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;
                 return 0;
             }
@@ -512,14 +520,83 @@
                 System.out.println("processStats:");
                 System.out.print(processStats);
                 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_WAIT) return 1;
                 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;
             System.out.println("");
             printMessageForState();
@@ -531,6 +608,8 @@
                 }
             }
 
+            killGdbLocked();
+
             return mResult;
         }
 
@@ -632,7 +711,19 @@
     }
 
     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();
     }
 
@@ -806,7 +897,8 @@
                 "    start profiling: am profile <PROCESS> start <FILE>\n" +
                 "    stop profiling: am profile <PROCESS> stop\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" +
                 "    <INTENT> specifications include these flags:\n" +
                 "        [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 6e9caaf..822f62d 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -122,11 +122,11 @@
     run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL);
     run_command("LIBRANK", 10, "librank", NULL);
 
-    dump_file("BINDER FAILED TRANSACTION LOG", "/proc/binder/failed_transaction_log");
-    dump_file("BINDER TRANSACTION LOG", "/proc/binder/transaction_log");
-    dump_file("BINDER TRANSACTIONS", "/proc/binder/transactions");
-    dump_file("BINDER STATS", "/proc/binder/stats");
-    run_command("BINDER PROCESS STATE", 10, "sh", "-c", "cat /proc/binder/proc/*");
+    dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
+    dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
+    dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
+    dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
+    dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
 
     run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
 
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 0608e72..9c249ce 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -2637,6 +2637,7 @@
             if (DBG) Log.d(TAG, "WindowLayout in layoutWindow:" + params);
         }
         mPendingConfiguration.seq = 0;
+        //Log.d(TAG, ">>>>>> CALLING relayout");
         int relayoutResult = sWindowSession.relayout(
                 mWindow, params,
                 (int) (mView.mMeasuredWidth * appScale + 0.5f),
@@ -2644,6 +2645,7 @@
                 viewVisibility, insetsPending, mWinFrame,
                 mPendingContentInsets, mPendingVisibleInsets,
                 mPendingConfiguration, mSurface);
+        //Log.d(TAG, "<<<<<< BACK FROM relayout");
         if (restore) {
             params.restore();
         }
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index a3e117f..13c58f0 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -517,12 +517,26 @@
     }
     
     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) {
             err = waitForResponse(reply);
         } else {
             Parcel fakeReply;
             err = waitForResponse(&fakeReply);
         }
+        #if 0
+        if (code == 4) { // relayout
+            LOGI("<<<<<< RETURNING transaction 4");
+        } else {
+            LOGI("<<<<<< RETURNING transaction %d", code);
+        }
+        #endif
         
         IF_LOG_TRANSACTIONS() {
             TextOutput::Bundle _b(alog);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index d7a1ac25..c637274 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -5679,9 +5679,12 @@
                 int requestedWidth, int requestedHeight, int viewFlags,
                 boolean insetsPending, Rect outFrame, Rect outContentInsets,
                 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,
                     outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
+            //Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());
+            return res;
         }
 
         public void setTransparentRegion(IWindow window, Region region) {