Loading core/java/android/app/ActivityThread.java +28 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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) { Loading core/java/android/app/IActivityManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -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) Loading core/java/android/app/IApplicationThread.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading core/proto/android/server/activitymanagerservice.proto +28 −0 Original line number Diff line number Diff line Loading @@ -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; } graphics/java/android/graphics/Bitmap.java +83 −20 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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]; } } Loading Loading @@ -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; } } } /** Loading Loading @@ -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 Loading @@ -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(); Loading @@ -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 Loading
core/java/android/app/ActivityThread.java +28 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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) { Loading
core/java/android/app/IActivityManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -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) Loading
core/java/android/app/IApplicationThread.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
core/proto/android/server/activitymanagerservice.proto +28 −0 Original line number Diff line number Diff line Loading @@ -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; }
graphics/java/android/graphics/Bitmap.java +83 −20 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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]; } } Loading Loading @@ -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; } } } /** Loading Loading @@ -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 Loading @@ -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(); Loading @@ -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