Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09d7d7db authored by Andy McFadden's avatar Andy McFadden Committed by Android (Google) Code Review
Browse files

Merge "Allow "am" to initiate heap dumps."

parents 46c076d1 824c5107
Loading
Loading
Loading
Loading
+26 −0
Original line number Original line Diff line number Diff line
@@ -98,6 +98,8 @@ public class Am {
            sendBroadcast();
            sendBroadcast();
        } else if (op.equals("profile")) {
        } else if (op.equals("profile")) {
            runProfile();
            runProfile();
        } else if (op.equals("dumpheap")) {
            runDumpHeap();
        } else {
        } else {
            throw new IllegalArgumentException("Unknown command: " + op);
            throw new IllegalArgumentException("Unknown command: " + op);
        }
        }
@@ -424,6 +426,28 @@ public class Am {
        }
        }
    }
    }


    private void runDumpHeap() throws Exception {
        boolean managed = !"-n".equals(nextOption());
        String process = nextArgRequired();
        String heapFile = nextArgRequired();
        ParcelFileDescriptor fd = null;

        try {
            fd = ParcelFileDescriptor.open(
                    new File(heapFile),
                    ParcelFileDescriptor.MODE_CREATE |
                    ParcelFileDescriptor.MODE_TRUNCATE |
                    ParcelFileDescriptor.MODE_READ_WRITE);
        } catch (FileNotFoundException e) {
            System.err.println("Error: Unable to open file: " + heapFile);
            return;
        }

        if (!mAm.dumpHeap(process, managed, heapFile, fd)) {
            throw new AndroidException("HEAP DUMP FAILED on process " + process);
        }
    }

    private class IntentReceiver extends IIntentReceiver.Stub {
    private class IntentReceiver extends IIntentReceiver.Stub {
        private boolean mFinished = false;
        private boolean mFinished = false;


@@ -593,6 +617,8 @@ public class Am {
                "\n" +
                "\n" +
                "    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" +
                "    dump heap: am dumpheap [flags] <PROCESS> <FILE>\n" +
                "        -n: dump native heap instead of managed heap\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" +
+36 −1
Original line number Original line Diff line number Diff line
@@ -1294,6 +1294,19 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            return true;
            return true;
        }
        }


        case DUMP_HEAP_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            String process = data.readString();
            boolean managed = data.readInt() != 0;
            String path = data.readString();
            ParcelFileDescriptor fd = data.readInt() != 0
                    ? data.readFileDescriptor() : null;
            boolean res = dumpHeap(process, managed, path, fd);
            reply.writeNoException();
            reply.writeInt(res ? 1 : 0);
            return true;
        }

        }
        }
        
        
        return super.onTransact(code, data, reply, flags);
        return super.onTransact(code, data, reply, flags);
@@ -2875,5 +2888,27 @@ class ActivityManagerProxy implements IActivityManager
        reply.recycle();
        reply.recycle();
    }
    }


    public boolean dumpHeap(String process, boolean managed,
            String path, ParcelFileDescriptor fd) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeString(process);
        data.writeInt(managed ? 1 : 0);
        data.writeString(path);
        if (fd != null) {
            data.writeInt(1);
            fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(DUMP_HEAP_TRANSACTION, data, reply, 0);
        reply.readException();
        boolean res = reply.readInt() != 0;
        reply.recycle();
        data.recycle();
        return res;
    }

    private IBinder mRemote;
    private IBinder mRemote;
}
}
+37 −0
Original line number Original line Diff line number Diff line
@@ -356,6 +356,11 @@ public final class ActivityThread {
        ParcelFileDescriptor fd;
        ParcelFileDescriptor fd;
    }
    }


    private static final class DumpHeapData {
        String path;
        ParcelFileDescriptor fd;
    }

    private final class ApplicationThread extends ApplicationThreadNative {
    private final class ApplicationThread extends ApplicationThreadNative {
        private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
        private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
        private static final String ONE_COUNT_COLUMN = "%17s %8d";
        private static final String ONE_COUNT_COLUMN = "%17s %8d";
@@ -623,6 +628,13 @@ public final class ActivityThread {
            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
        }
        }


        public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) {
            DumpHeapData dhd = new DumpHeapData();
            dhd.path = path;
            dhd.fd = fd;
            queueOrSendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0);
        }

        public void setSchedulingGroup(int group) {
        public void setSchedulingGroup(int group) {
            // Note: do this immediately, since going into the foreground
            // Note: do this immediately, since going into the foreground
            // should happen regardless of what pending work we have to do
            // should happen regardless of what pending work we have to do
@@ -874,6 +886,7 @@ public final class ActivityThread {
        public static final int ENABLE_JIT              = 132;
        public static final int ENABLE_JIT              = 132;
        public static final int DISPATCH_PACKAGE_BROADCAST = 133;
        public static final int DISPATCH_PACKAGE_BROADCAST = 133;
        public static final int SCHEDULE_CRASH          = 134;
        public static final int SCHEDULE_CRASH          = 134;
        public static final int DUMP_HEAP               = 135;
        String codeToString(int code) {
        String codeToString(int code) {
            if (localLOGV) {
            if (localLOGV) {
                switch (code) {
                switch (code) {
@@ -912,6 +925,7 @@ public final class ActivityThread {
                    case ENABLE_JIT: return "ENABLE_JIT";
                    case ENABLE_JIT: return "ENABLE_JIT";
                    case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
                    case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
                    case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
                    case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
                    case DUMP_HEAP: return "DUMP_HEAP";
                }
                }
            }
            }
            return "(unknown)";
            return "(unknown)";
@@ -1037,6 +1051,9 @@ public final class ActivityThread {
                    break;
                    break;
                case SCHEDULE_CRASH:
                case SCHEDULE_CRASH:
                    throw new RemoteServiceException((String)msg.obj);
                    throw new RemoteServiceException((String)msg.obj);
                case DUMP_HEAP:
                    handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
                    break;
            }
            }
        }
        }


@@ -3015,6 +3032,26 @@ public final class ActivityThread {
        }
        }
    }
    }


    final void handleDumpHeap(boolean managed, DumpHeapData dhd) {
        if (managed) {
            try {
                Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor());
            } catch (IOException e) {
                Slog.w(TAG, "Managed heap dump failed on path " + dhd.path
                        + " -- can the process access this path?");
            } finally {
                try {
                    dhd.fd.close();
                } catch (IOException e) {
                    Slog.w(TAG, "Failure closing profile fd", e);
                }
            }
        } else {
            // TODO
            Slog.w(TAG, "Native heap dump not yet implemented");
        }
    }

    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
        boolean hasPkgInfo = false;
        boolean hasPkgInfo = false;
        if (packages != null) {
        if (packages != null) {
+28 −0
Original line number Original line Diff line number Diff line
@@ -403,6 +403,17 @@ public abstract class ApplicationThreadNative extends Binder
            scheduleCrash(msg);
            scheduleCrash(msg);
            return true;
            return true;
        }
        }

        case DUMP_HEAP_TRANSACTION:
        {
            data.enforceInterface(IApplicationThread.descriptor);
            boolean managed = data.readInt() != 0;
            String path = data.readString();
            ParcelFileDescriptor fd = data.readInt() != 0
                    ? data.readFileDescriptor() : null;
            dumpHeap(managed, path, fd);
            return true;
        }
        }
        }


        return super.onTransact(code, data, reply, flags);
        return super.onTransact(code, data, reply, flags);
@@ -829,5 +840,22 @@ class ApplicationThreadProxy implements IApplicationThread {
        data.recycle();
        data.recycle();
        
        
    }
    }

    public void dumpHeap(boolean managed, String path,
            ParcelFileDescriptor fd) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeInt(managed ? 1 : 0);
        data.writeString(path);
        if (fd != null) {
            data.writeInt(1);
            fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(DUMP_HEAP_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }
}
}
+6 −1
Original line number Original line Diff line number Diff line
@@ -317,6 +317,10 @@ public interface IActivityManager extends IInterface {
    public void crashApplication(int uid, int initialPid, String packageName,
    public void crashApplication(int uid, int initialPid, String packageName,
            String message) throws RemoteException;
            String message) throws RemoteException;


    // Cause the specified process to dump the specified heap.
    public boolean dumpHeap(String process, boolean managed, String path,
        ParcelFileDescriptor fd) throws RemoteException;

    /*
    /*
     * Private non-Binder interfaces
     * Private non-Binder interfaces
     */
     */
@@ -533,4 +537,5 @@ public interface IActivityManager extends IInterface {
    int SET_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+111;
    int SET_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+111;
    int IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+112;
    int IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+112;
    int CRASH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+113;
    int CRASH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+113;
    int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+114;
}
}
Loading