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

Commit 6bf31f49 authored by Haiping Yang's avatar Haiping Yang
Browse files

Add dumpsys entry point for package storageStats.

Flag: android.content.pm.Flags.get_package_storage_stats
Bug:332905331

Test: adb shell pm get-package-storage-stats  com.google.android.youtube
sample output:
code: 151909888 bytes (144.87 Mb)
data: 8081408 bytes (7.71 Mb)
cache: 6602752 bytes (6.30 Mb)
apk: 110509971 bytes (105.39 Mb)
lib: 0 bytes
dm: 1282352 bytes (1.22 Mb)
dexopt artifacts: 40149956 bytes (38.29 Mb)
current profile : 18094 bytes (17.67 Kb)
reference profile: 98524 bytes (96.21 Kb)
external cache: 6279168 bytes (5.99 Mb)

Change-Id: I19083664f29756f3e3918de74d48b44b81a254dc
parent e25101a2
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -135,6 +135,18 @@ flag {
    bug: "314815969"
}

flag {
    name: "get_package_storage_stats"
    namespace: "system_performance"
    is_exported: true
    description: "Add dumpsys entry point for package StorageStats"
    bug: "332905331"
    is_fixed_read_only: true
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "provide_info_of_apk_in_apex"
    is_exported: true
+104 −0
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.role.RoleManager;
import android.app.usage.StorageStats;
import android.app.usage.StorageStatsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentReceiver;
@@ -136,6 +138,7 @@ import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.security.SecureRandom;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
@@ -275,6 +278,8 @@ class PackageManagerShellCommand extends ShellCommand {
                    return runClear();
                case "get-archived-package-metadata":
                    return runGetArchivedPackageMetadata();
                case "get-package-storage-stats":
                    return runGetPackageStorageStats();
                case "install-archived":
                    return runArchivedInstall();
                case "enable":
@@ -1861,6 +1866,103 @@ class PackageManagerShellCommand extends ShellCommand {
        return 0;
    }

    /**
     * Returns a string that shows the number of bytes in b, Kb, Mb or Gb.
     */
    protected static String getFormattedBytes(long size) {
        double k = size/1024.0;
        double m = size/1048576.0;
        double g = size/1073741824.0;

        DecimalFormat dec = new DecimalFormat("0.00");
        if (g > 1) {
            return dec.format(g).concat(" Gb");
        } else if (m > 1) {
            return dec.format(m).concat(" Mb");
        } else if (k > 1) {
            return dec.format(k).concat(" Kb");
        }
        return "";
    }

    /**
     * Return the string that displays the data size.
     */
    private String getDataSizeDisplay(long size) {
        String formattedOutput = getFormattedBytes(size);
        if (!formattedOutput.isEmpty()) {
           formattedOutput = " (" + formattedOutput + ")";
        }
        return Long.toString(size) + " bytes" + formattedOutput;
    }

    /**
     * Display storage stats of the specified package.
     *
     * Usage: get-package-storage-stats [--usr USER_ID] PACKAGE
     */
    private int runGetPackageStorageStats() throws RemoteException {
        final PrintWriter pw = getOutPrintWriter();
        if (!android.content.pm.Flags.getPackageStorageStats()) {
            pw.println("Error: get_package_storage_stats flag is not enabled");
            return 1;
        }
        if (!android.app.usage.Flags.getAppBytesByDataTypeApi()) {
            pw.println("Error: get_app_bytes_by_data_type_api flag is not enabled");
            return 1;
        }
        int userId = UserHandle.USER_CURRENT;

        String opt;
        while ((opt = getNextOption()) != null) {
            switch (opt) {
                case "--user":
                    userId = UserHandle.parseUserArg(getNextArgRequired());
                    break;
                default:
                    pw.println("Error: Unknown option: " + opt);
                    return 1;
            }
        }

        final String packageName = getNextArg();
        if (packageName == null) {
            pw.println("Error: package name not specified");
            return 1;
        }
        try {
            StorageStatsManager storageStatsManager =
                mContext.getSystemService(StorageStatsManager.class);
            final int translatedUserId = translateUserId(userId, UserHandle.USER_NULL,
                "runGetPackageStorageStats");
            StorageStats stats =
                storageStatsManager.queryStatsForPackage(StorageManager.UUID_DEFAULT,
                    packageName, UserHandle.of(translatedUserId));

            pw.println("code: " + getDataSizeDisplay(stats.getAppBytes()));
            pw.println("data: " + getDataSizeDisplay(stats.getDataBytes()));
            pw.println("cache: " + getDataSizeDisplay(stats.getCacheBytes()));
            pw.println("apk: " + getDataSizeDisplay(stats.getAppBytesByDataType(
                StorageStats.APP_DATA_TYPE_FILE_TYPE_APK)));
            pw.println("lib: " + getDataSizeDisplay(
                stats.getAppBytesByDataType(StorageStats.APP_DATA_TYPE_LIB)));
            pw.println("dm: " + getDataSizeDisplay(stats.getAppBytesByDataType(
                StorageStats.APP_DATA_TYPE_FILE_TYPE_DM)));
            pw.println("dexopt artifacts: " + getDataSizeDisplay(stats.getAppBytesByDataType(
                StorageStats.APP_DATA_TYPE_FILE_TYPE_DEXOPT_ARTIFACT)));
            pw.println("current profile : " + getDataSizeDisplay(stats.getAppBytesByDataType(
                StorageStats.APP_DATA_TYPE_FILE_TYPE_CURRENT_PROFILE)));
            pw.println("reference profile: " + getDataSizeDisplay(stats.getAppBytesByDataType(
                StorageStats.APP_DATA_TYPE_FILE_TYPE_REFERENCE_PROFILE)));
            pw.println("external cache: " + getDataSizeDisplay(stats.getExternalCacheBytes()));
        } catch (Exception e) {
            getErrPrintWriter().println("Failed to get storage stats, reason: " + e);
            pw.println("Failure [failed to get storage stats], reason: " + e);
            return -1;
        }
        return 0;
    }

    private int runInstallExisting() throws RemoteException {
        final PrintWriter pw = getOutPrintWriter();
        int userId = UserHandle.USER_CURRENT;
@@ -4869,6 +4971,8 @@ class PackageManagerShellCommand extends ShellCommand {
        pw.println("    Displays the component name of the domain verification agent on device.");
        pw.println("    If the component isn't enabled, an error message will be displayed.");
        pw.println("      --user: return the agent of the given user (SYSTEM_USER if unspecified)");
        pw.println("  get-package-storage-stats [--user <USER_ID>] <PACKAGE>");
        pw.println("    Return the storage stats for the given app, if present");
        pw.println("");
        printArtServiceHelp();
        pw.println("");