summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Haiping Yang <haiping@google.com> 2024-04-20 05:40:52 +0000
committer Haiping Yang <haiping@google.com> 2024-05-08 05:24:53 +0000
commit6bf31f4966a6a78721b0345fedb8dbe9c393548f (patch)
tree3dae9f81d7fd56357fa75506e4351dfd431a82e5
parente25101a2a23af1a2a3cc536fe40b7994ff970007 (diff)
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
-rw-r--r--core/java/android/content/pm/flags.aconfig12
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java104
2 files changed, 116 insertions, 0 deletions
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index cde565b3f66e..added33ba35a 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -136,6 +136,18 @@ flag {
}
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
namespace: "package_manager_service"
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 179379487aba..7a36f6dabe06 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -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("");