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

Commit 0a201105 authored by Eric Miao's avatar Eric Miao Committed by Android (Google) Code Review
Browse files

Merge "Add am dumpbitmaps to dump bitmap information/content" into main

parents 82d59b83 0ebd869c
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -253,6 +253,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.org.conscrypt.TrustedCertificateStore;
import com.android.server.am.MemInfoDumpProto;
import com.android.server.am.BitmapDumpProto;

import dalvik.annotation.optimization.NeverCompile;
import dalvik.system.AppSpecializationHooks;
@@ -2014,6 +2015,21 @@ public final class ActivityThread extends ClientTransactionHandler
            }
        }

        @Override
        @NeverCompile
        public void dumpBitmapsProto(ParcelFileDescriptor pfd, String dumpFormat) {
            try {
                int pid = Process.myPid();
                String processName = (mBoundApplication != null)
                    ? mBoundApplication.processName
                    : Process.myProcessName();
                ActivityThread.dumpBitmapsProto(new ProtoOutputStream(pfd.getFileDescriptor()),
                    pid, processName, dumpFormat);
            } finally {
                IoUtils.closeQuietly(pfd);
            }
        }

        @Override
        public void dumpCacheInfo(ParcelFileDescriptor pfd, String[] args) {
            try {
@@ -3906,6 +3922,18 @@ public final class ActivityThread extends ClientTransactionHandler
        proto.end(asToken);
    }

    @NeverCompile
    public static void dumpBitmapsProto(ProtoOutputStream proto, int pid,
                String processName, String dumpFormat) {
        try {
            proto.write(BitmapDumpProto.AppBitmapInfo.PID, pid);
            proto.write(BitmapDumpProto.AppBitmapInfo.PROCESS_NAME, processName);
            Bitmap.dumpAll(proto, dumpFormat);
        } finally {
            proto.flush();
        }
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void registerOnActivityPausedListener(Activity activity,
            OnActivityPausedListener listener) {
+2 −0
Original line number Diff line number Diff line
@@ -401,6 +401,8 @@ interface IActivityManager {
    boolean dumpHeap(in String process, int userId, boolean managed, boolean mallocInfo,
            boolean runGc, in String dumpBitmaps, in String path, in ParcelFileDescriptor fd,
            in RemoteCallback finishCallback);
    void dumpBitmapsProto(in ParcelFileDescriptor fd, in String[] processes,
            int userId, boolean allPkgs, in String dumpFormat);
    @UnsupportedAppUsage
    boolean isUserRunning(int userid, int flags);
    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
+1 −0
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@ oneway interface IApplicationThread {
            boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable,
            in String[] args);
    void dumpGfxInfo(in ParcelFileDescriptor fd, in String[] args);
    void dumpBitmapsProto(in ParcelFileDescriptor fd, in String dumpFormat);
    void dumpCacheInfo(in ParcelFileDescriptor fd, in String[] args);
    void dumpProvider(in ParcelFileDescriptor fd, IBinder servicetoken,
            in String[] args);
+28 −0
Original line number Diff line number Diff line
@@ -1067,3 +1067,31 @@ message AppsStartInfoProto {
    optional int64 monotonic_time = 3;
}
// LINT.ThenChange(/services/core/java/com/android/server/am/AppStartInfoTracker.java)

message BitmapDumpProto {
    option (.android.msg_privacy).dest = DEST_AUTOMATIC;

    message AppBitmapInfo {
        option (.android.msg_privacy).dest = DEST_AUTOMATIC;

        optional int32 pid = 1;
        optional string process_name = 2;

        message BitmapInfo {
            option (.android.msg_privacy).dest = DEST_AUTOMATIC;

            optional int64 id = 1;
            optional int32 width = 2;
            optional int32 height = 3;
            optional int32 size = 4;
            optional bool mutable = 5;
            optional int32 config = 6;
            optional int64 source = 7;
            optional bytes content = 8;
        }

        repeated BitmapInfo bitmaps = 3;
    }

    repeated AppBitmapInfo app_bitmaps = 1;
}
+83 −20
Original line number Diff line number Diff line
@@ -34,8 +34,9 @@ import android.os.Trace;
import android.util.DisplayMetrics;
import android.util.Half;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.ThreadedRenderer;

import com.android.server.am.BitmapDumpProto;
import dalvik.annotation.optimization.CriticalNative;

import libcore.util.NativeAllocationRegistry;
@@ -43,11 +44,13 @@ import libcore.util.NativeAllocationRegistry;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.WeakHashMap;

@@ -611,8 +614,11 @@ public final class Bitmap implements Parcelable {
            this.nativeInt = ni;
        }

        /**
         * @hide
         */
        @UnsupportedAppUsage
        static Config nativeToConfig(int ni) {
        public static Config nativeToConfig(int ni) {
            return sConfigs[ni];
        }
    }
@@ -1544,6 +1550,21 @@ public final class Bitmap implements Parcelable {
            this.nativeInt = nativeInt;
        }
        final int nativeInt;

        /**
         * @hide
         */
        public static @Nullable CompressFormat from(@NonNull String format) {
            if (format.equals("jpg") || format.equals("jpeg")) {
                return CompressFormat.JPEG;
            } else if (format.equals("png")) {
                return CompressFormat.PNG;
            } else if (format.equals("webp")) {
                return CompressFormat.WEBP_LOSSLESS;
            } else {
                return null;
            }
        }
    }

    /**
@@ -1580,6 +1601,18 @@ public final class Bitmap implements Parcelable {
     */
    private static DumpData dumpData = null;

    private static ArrayList<Bitmap> getAllBitmaps() {
        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);
            }
          }
        }
        return allBitmaps;
    }

    /**
     * @hide
@@ -1594,28 +1627,14 @@ public final class Bitmap implements Parcelable {
            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 {

        final CompressFormat fmt = CompressFormat.from(format);
        if (fmt == null) {
            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);
            }
          }
        }

        final ArrayList<Bitmap> allBitmaps = getAllBitmaps();
        dumpData = new DumpData(fmt, allBitmaps.size());
        for (Bitmap bitmap : allBitmaps) {
            ByteArrayOutputStream bas = new ByteArrayOutputStream();
@@ -1626,6 +1645,50 @@ public final class Bitmap implements Parcelable {
        Log.i(TAG, dumpData.size() + "/" + allBitmaps.size() + " bitmaps dumped");
    }

    /**
     * @hide
     *
     * Dump information of all the bitmaps into the protobuf stream. If dumpFormat
     * is specified, compress the bitmaps and store the content.
     *
     * @param proto       protobuf stream for storing bitmap information
     * @param dumpFormat  if not null, specify the format of the compressed image
     */
    public static void dumpAll(ProtoOutputStream proto, @Nullable String dumpFormat) {
        final ArrayList<Bitmap> allBitmaps = getAllBitmaps();

        if (allBitmaps.size() == 0) {
            return;
        }

        for (Bitmap bitmap : allBitmaps) {
            int bytes = bitmap.getAllocationByteCount();
            int config = bitmap.getConfig().nativeInt;

            final long token = proto.start(BitmapDumpProto.AppBitmapInfo.BITMAPS);
            proto.write(BitmapDumpProto.AppBitmapInfo.BitmapInfo.ID, bitmap.mId);
            proto.write(BitmapDumpProto.AppBitmapInfo.BitmapInfo.WIDTH, bitmap.mWidth);
            proto.write(BitmapDumpProto.AppBitmapInfo.BitmapInfo.HEIGHT, bitmap.mHeight);
            proto.write(BitmapDumpProto.AppBitmapInfo.BitmapInfo.SIZE, bytes);
            proto.write(BitmapDumpProto.AppBitmapInfo.BitmapInfo.MUTABLE, bitmap.isMutable());
            proto.write(BitmapDumpProto.AppBitmapInfo.BitmapInfo.CONFIG, config);
            proto.write(BitmapDumpProto.AppBitmapInfo.BitmapInfo.SOURCE, bitmap.mSourceId);
            if (dumpFormat != null) {
                try {
                    ByteArrayOutputStream bas = new ByteArrayOutputStream();
                    if (bitmap.compress(CompressFormat.from(dumpFormat), 90, bas)) {
                        proto.write(BitmapDumpProto.AppBitmapInfo.BitmapInfo.CONTENT,
                                    bas.toByteArray());
                    }
                    bas.close();
                } catch (IOException e) {
                    Log.e(TAG, "failed to compress bitmap-" + bitmap.mId + ": " + e);
                }
            }
            proto.end(token);
        }
    }

    /**
     * Number of bytes of temp storage we use for communicating between the
     * native compressor and the java OutputStream.
Loading