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

Commit 063ac7b8 authored by Eric Miao's avatar Eric Miao Committed by Gerrit Code Review
Browse files

Merge "Add compressed bitmaps to be included in `am dumpheap`" into main

parents 281a76bf d48d873a
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -1050,6 +1050,8 @@ public final class ActivityThread extends ClientTransactionHandler
        public boolean managed;
        public boolean mallocInfo;
        public boolean runGc;
        // compression format to dump bitmaps, null if no bitmaps to be dumped
        public String dumpBitmaps;
        String path;
        ParcelFileDescriptor fd;
        RemoteCallback finishCallback;
@@ -1442,11 +1444,12 @@ public final class ActivityThread extends ClientTransactionHandler
        }

        @Override
        public void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, String path,
                ParcelFileDescriptor fd, RemoteCallback finishCallback) {
        public void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, String dumpBitmaps,
                String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
            DumpHeapData dhd = new DumpHeapData();
            dhd.managed = managed;
            dhd.mallocInfo = mallocInfo;
            dhd.dumpBitmaps = dumpBitmaps;
            dhd.runGc = runGc;
            dhd.path = path;
            try {
@@ -6731,6 +6734,9 @@ public final class ActivityThread extends ClientTransactionHandler
            System.runFinalization();
            System.gc();
        }
        if (dhd.dumpBitmaps != null) {
            Bitmap.dumpAll(dhd.dumpBitmaps);
        }
        try (ParcelFileDescriptor fd = dhd.fd) {
            if (dhd.managed) {
                Debug.dumpHprofData(dhd.path, fd.getFileDescriptor());
@@ -6758,6 +6764,9 @@ public final class ActivityThread extends ClientTransactionHandler
        if (dhd.finishCallback != null) {
            dhd.finishCallback.sendResult(null);
        }
        if (dhd.dumpBitmaps != null) {
            Bitmap.dumpAll(null); // clear dump
        }
    }

    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
+1 −1
Original line number Diff line number Diff line
@@ -392,7 +392,7 @@ interface IActivityManager {
    oneway void getMimeTypeFilterAsync(in Uri uri, int userId, in RemoteCallback resultCallback);
    // Cause the specified process to dump the specified heap.
    boolean dumpHeap(in String process, int userId, boolean managed, boolean mallocInfo,
            boolean runGc, in String path, in ParcelFileDescriptor fd,
            boolean runGc, in String dumpBitmaps, in String path, in ParcelFileDescriptor fd,
            in RemoteCallback finishCallback);
    @UnsupportedAppUsage
    boolean isUserRunning(int userid, int flags);
+2 −1
Original line number Diff line number Diff line
@@ -116,7 +116,8 @@ oneway interface IApplicationThread {
    void scheduleSuicide();
    void dispatchPackageBroadcast(int cmd, in String[] packages);
    void scheduleCrash(in String msg, int typeId, in Bundle extras);
    void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, in String path,
    void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc,
            in String dumpBitmaps, in String path,
            in ParcelFileDescriptor fd, in RemoteCallback finishCallback);
    void dumpActivity(in ParcelFileDescriptor fd, IBinder servicetoken, in String prefix,
            in String[] args);
+91 −0
Original line number Diff line number Diff line
@@ -41,12 +41,15 @@ import dalvik.annotation.optimization.CriticalNative;
import libcore.util.NativeAllocationRegistry;

import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.WeakHashMap;

public final class Bitmap implements Parcelable {
    private static final String TAG = "Bitmap";
@@ -119,6 +122,11 @@ public final class Bitmap implements Parcelable {
        return sDefaultDensity;
    }

    /**
     * @hide
     */
    private static final WeakHashMap<Bitmap, Void> sAllBitmaps = new WeakHashMap<>();

    /**
     * Private constructor that must receive an already allocated native bitmap
     * int (pointer).
@@ -162,6 +170,9 @@ public final class Bitmap implements Parcelable {
                    Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount);
        }
        registry.registerNativeAllocation(this, nativeBitmap);
        synchronized (Bitmap.class) {
          sAllBitmaps.put(this, null);
        }
    }

    /**
@@ -1509,6 +1520,86 @@ public final class Bitmap implements Parcelable {
        final int nativeInt;
    }

    /**
     * @hide
     */
    private static final class DumpData {
        private int count;
        private int format;
        private long[] natives;
        private byte[][] buffers;
        private int max;

        public DumpData(@NonNull CompressFormat format, int max) {
            this.max = max;
            this.format = format.nativeInt;
            this.natives = new long[max];
            this.buffers = new byte[max][];
            this.count = 0;
        }

        public void add(long nativePtr, byte[] buffer) {
            natives[count] = nativePtr;
            buffers[count] = buffer;
            count = (count >= max) ? max : count + 1;
        }

        public int size() {
            return count;
        }
    }

    /**
     * @hide
     */
    private static DumpData dumpData = null;


    /**
     * @hide
     *
     * Dump all the bitmaps with their contents compressed into dumpData
     *
     * @param format  format of the compressed image, null to clear dump data
     */
    public static void dumpAll(@Nullable String format) {
        if (format == null) {
            /* release the dump data */
            dumpData = null;
            return;
        }
        final CompressFormat fmt;
        if (format.equals("jpg") || format.equals("jpeg")) {
            fmt = CompressFormat.JPEG;
        } else if (format.equals("png")) {
            fmt = CompressFormat.PNG;
        } else if (format.equals("webp")) {
            fmt = CompressFormat.WEBP_LOSSLESS;
        } else {
            Log.w(TAG, "No bitmaps dumped: unrecognized format " + format);
            return;
        }

        final ArrayList<Bitmap> allBitmaps;
        synchronized (Bitmap.class) {
          allBitmaps = new ArrayList<>(sAllBitmaps.size());
          for (Bitmap bitmap : sAllBitmaps.keySet()) {
            if (bitmap != null && !bitmap.isRecycled()) {
              allBitmaps.add(bitmap);
            }
          }
        }

        dumpData = new DumpData(fmt, allBitmaps.size());
        for (Bitmap bitmap : allBitmaps) {
            ByteArrayOutputStream bas = new ByteArrayOutputStream();
            if (bitmap.compress(fmt, 90, bas)) {
                dumpData.add(bitmap.getNativeInstance(), bas.toByteArray());
            }
        }
        Log.i(TAG, dumpData.size() + "/" + allBitmaps.size() + " bitmaps dumped");
    }

    /**
     * Number of bytes of temp storage we use for communicating between the
     * native compressor and the java OutputStream.
+4 −2
Original line number Diff line number Diff line
@@ -17297,7 +17297,8 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Override
    public boolean dumpHeap(String process, int userId, boolean managed, boolean mallocInfo,
            boolean runGc, String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
            boolean runGc, String dumpBitmaps,
            String path, ParcelFileDescriptor fd, RemoteCallback finishCallback) {
        try {
            // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
            // its own permission (same as profileControl).
@@ -17331,7 +17332,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                        }
                    }, null);
                thread.dumpHeap(managed, mallocInfo, runGc, path, fd, intermediateCallback);
                thread.dumpHeap(managed, mallocInfo, runGc, dumpBitmaps,
                                path, fd, intermediateCallback);
                fd = null;
                return true;
            }
Loading