Add binder transaction tracking.

Add the ability to am to be able to track binder transact calls. This
will help us diagnose excessive IPC calls.

This CL adds the trace-ip command to am. The usage is,

To start binder transaction tracking,
am trace-ipc start
To stop tracking and dump the data to a file,
am trace-ipc stop --dump-file <FILE>

Bug: 21398706
Change-Id: Ic0c9b3be757dd0662a2750a0d8447e2a5ef1fa90
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 6ae21eb..07b9ebe 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2554,6 +2554,24 @@
             reply.writeInt(res ? 1 : 0);
             return true;
         }
+
+        case START_BINDER_TRACKING_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            boolean res = startBinderTracking();
+            reply.writeNoException();
+            reply.writeInt(res ? 1 : 0);
+            return true;
+        }
+
+        case STOP_BINDER_TRACKING_AND_DUMP_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            ParcelFileDescriptor fd = data.readInt() != 0
+                    ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
+            boolean res = stopBinderTrackingAndDump(fd);
+            reply.writeNoException();
+            reply.writeInt(res ? 1 : 0);
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -5505,6 +5523,36 @@
         reply.recycle();
     }
 
+    public boolean startBinderTracking() throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(START_BINDER_TRACKING_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean res = reply.readInt() != 0;
+        reply.recycle();
+        data.recycle();
+        return res;
+    }
+
+    public boolean stopBinderTrackingAndDump(ParcelFileDescriptor fd) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        if (fd != null) {
+            data.writeInt(1);
+            fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+        } else {
+            data.writeInt(0);
+        }
+        mRemote.transact(STOP_BINDER_TRACKING_AND_DUMP_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean res = reply.readInt() != 0;
+        reply.recycle();
+        data.recycle();
+        return res;
+    }
+
     @Override
     public IActivityContainer createStackOnDisplay(int displayId) throws RemoteException {
         Parcel data = Parcel.obtain();