Loading core/api/current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -9315,10 +9315,14 @@ package android.app.usage { public final class StorageStats implements android.os.Parcelable { method public int describeContents(); method public long getAppBytes(); method @FlaggedApi("android.app.usage.get_app_bytes_by_data_type_api") public long getAppBytesByDataType(int); method public long getCacheBytes(); method public long getDataBytes(); method public long getExternalCacheBytes(); method public void writeToParcel(android.os.Parcel, int); field @FlaggedApi("android.app.usage.get_app_bytes_by_data_type_api") public static final int APP_DATA_TYPE_FILE_TYPE_APK = 0; // 0x0 field @FlaggedApi("android.app.usage.get_app_bytes_by_data_type_api") public static final int APP_DATA_TYPE_FILE_TYPE_DM = 1; // 0x1 field @FlaggedApi("android.app.usage.get_app_bytes_by_data_type_api") public static final int APP_DATA_TYPE_LIB = 2; // 0x2 field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR; } core/java/android/app/usage/StorageStats.java +73 −4 Original line number Diff line number Diff line Loading @@ -17,11 +17,16 @@ package android.app.usage; import android.annotation.BytesLong; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Storage statistics for a UID, package, or {@link UserHandle} on a single * storage volume. Loading @@ -29,10 +34,47 @@ import android.os.UserHandle; * @see StorageStatsManager */ public final class StorageStats implements Parcelable { /** {@hide} */ public long codeBytes; /** {@hide} */ public long dataBytes; /** {@hide} */ public long cacheBytes; /** {@hide} */ public long externalCacheBytes; /** @hide */ public long codeBytes; /** @hide */ public long dataBytes; /** @hide */ public long cacheBytes; /** @hide */ public long apkBytes; /** @hide */ public long libBytes; /** @hide */ public long dmBytes; /** @hide */ public long externalCacheBytes; /** Represents all .apk files in application code path. * Can be used as an input to {@link #getAppBytesByDataType(int)} * to get the sum of sizes for files of this type. */ @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API) public static final int APP_DATA_TYPE_FILE_TYPE_APK = 0; /** Represents all .dm files in application code path. * Can be used as an input to {@link #getAppBytesByDataType(int)} * to get the sum of sizes for files of this type. */ @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API) public static final int APP_DATA_TYPE_FILE_TYPE_DM = 1; /** Represents lib/ in application code path. * Can be used as an input to {@link #getAppBytesByDataType(int)} * to get the size of lib/ directory. */ @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API) public static final int APP_DATA_TYPE_LIB = 2; /** * Keep in sync with the file types defined above. * @hide */ @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API) @IntDef(flag = false, value = { APP_DATA_TYPE_FILE_TYPE_APK, APP_DATA_TYPE_FILE_TYPE_DM, APP_DATA_TYPE_LIB, }) @Retention(RetentionPolicy.SOURCE) public @interface AppDataType {} /** * Return the size of app. This includes {@code APK} files, optimized Loading @@ -47,6 +89,27 @@ public final class StorageStats implements Parcelable { return codeBytes; } /** * Return the size of the specified data type. This includes files stored under * application code path. * <p> * If there is more than one package inside a uid, the return represents the aggregated * stats when query StorageStat for package or uid. * The data is not collected and the return defaults to 0 when query StorageStats for user. * * <p> * Data is isolated for each user on a multiuser device. */ @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API) public long getAppBytesByDataType(@AppDataType int dataType) { switch (dataType) { case APP_DATA_TYPE_FILE_TYPE_APK: return apkBytes; case APP_DATA_TYPE_LIB: return libBytes; case APP_DATA_TYPE_FILE_TYPE_DM: return dmBytes; default: return 0; } } /** * Return the size of all data. This includes files stored under * {@link Context#getDataDir()}, {@link Context#getCacheDir()}, Loading Loading @@ -98,6 +161,9 @@ public final class StorageStats implements Parcelable { this.codeBytes = in.readLong(); this.dataBytes = in.readLong(); this.cacheBytes = in.readLong(); this.apkBytes = in.readLong(); this.libBytes = in.readLong(); this.dmBytes = in.readLong(); this.externalCacheBytes = in.readLong(); } Loading @@ -111,6 +177,9 @@ public final class StorageStats implements Parcelable { dest.writeLong(codeBytes); dest.writeLong(dataBytes); dest.writeLong(cacheBytes); dest.writeLong(apkBytes); dest.writeLong(libBytes); dest.writeLong(dmBytes); dest.writeLong(externalCacheBytes); } Loading core/java/android/app/usage/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -35,3 +35,10 @@ flag { description: " Feature flag to support filter based event query API" bug: "194321117" } flag { name: "get_app_bytes_by_data_type_api" namespace: "system_performance" description: "Feature flag for collecting app data size by file type API" bug: "294088945" } core/java/android/content/pm/PackageStats.java +38 −1 Original line number Diff line number Diff line Loading @@ -55,6 +55,18 @@ public class PackageStats implements Parcelable { /** Size of cache used by the application. (e.g., /data/data/<app>/cache) */ public long cacheSize; /** Size of .apk files of the application. */ /** @hide */ public long apkSize; /** Size of the libraries of the application. */ /** @hide */ public long libSize; /** Size of the .dm files of the application. */ /** @hide */ public long dmSize; /** * Size of the secure container on external storage holding the * application's code. Loading Loading @@ -108,6 +120,18 @@ public class PackageStats implements Parcelable { sb.append(" cache="); sb.append(cacheSize); } if (apkSize != 0) { sb.append(" apk="); sb.append(apkSize); } if (libSize != 0) { sb.append(" lib="); sb.append(libSize); } if (dmSize != 0) { sb.append(" dm="); sb.append(dmSize); } if (externalCodeSize != 0) { sb.append(" extCode="); sb.append(externalCodeSize); Loading Loading @@ -149,6 +173,9 @@ public class PackageStats implements Parcelable { codeSize = source.readLong(); dataSize = source.readLong(); cacheSize = source.readLong(); apkSize = source.readLong(); libSize = source.readLong(); dmSize = source.readLong(); externalCodeSize = source.readLong(); externalDataSize = source.readLong(); externalCacheSize = source.readLong(); Loading @@ -162,6 +189,9 @@ public class PackageStats implements Parcelable { codeSize = pStats.codeSize; dataSize = pStats.dataSize; cacheSize = pStats.cacheSize; apkSize = pStats.apkSize; libSize = pStats.libSize; dmSize = pStats.dmSize; externalCodeSize = pStats.externalCodeSize; externalDataSize = pStats.externalDataSize; externalCacheSize = pStats.externalCacheSize; Loading @@ -179,6 +209,9 @@ public class PackageStats implements Parcelable { dest.writeLong(codeSize); dest.writeLong(dataSize); dest.writeLong(cacheSize); dest.writeLong(apkSize); dest.writeLong(libSize); dest.writeLong(dmSize); dest.writeLong(externalCodeSize); dest.writeLong(externalDataSize); dest.writeLong(externalCacheSize); Loading @@ -198,6 +231,9 @@ public class PackageStats implements Parcelable { && codeSize == otherStats.codeSize && dataSize == otherStats.dataSize && cacheSize == otherStats.cacheSize && apkSize == otherStats.apkSize && libSize == otherStats.libSize && dmSize == otherStats.dmSize && externalCodeSize == otherStats.externalCodeSize && externalDataSize == otherStats.externalDataSize && externalCacheSize == otherStats.externalCacheSize Loading @@ -208,7 +244,8 @@ public class PackageStats implements Parcelable { @Override public int hashCode() { return Objects.hash(packageName, userHandle, codeSize, dataSize, cacheSize, externalCodeSize, externalDataSize, externalCacheSize, externalMediaSize, apkSize, libSize, dmSize, cacheSize, externalCodeSize, externalDataSize, externalCacheSize, externalMediaSize, externalObbSize); } Loading services/usage/java/com/android/server/usage/StorageStatsService.java +67 −2 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.app.usage.ExternalStorageStats; import android.app.usage.Flags; import android.app.usage.IStorageStatsManager; import android.app.usage.StorageStats; import android.app.usage.UsageStatsManagerInternal; Loading Loading @@ -434,6 +435,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { final long[] ceDataInodes = new long[packageNames.length]; String[] codePaths = new String[0]; final PackageStats stats = new PackageStats(TAG); for (int i = 0; i < packageNames.length; i++) { try { final ApplicationInfo appInfo = mPackage.getApplicationInfoAsUser(packageNames[i], Loading @@ -445,13 +447,16 @@ public class StorageStatsService extends IStorageStatsManager.Stub { codePaths = ArrayUtils.appendElement(String.class, codePaths, appInfo.getCodePath()); } if (Flags.getAppBytesByDataTypeApi()) { computeAppStatsByDataTypes( stats, appInfo.sourceDir); } } } catch (NameNotFoundException e) { throw new ParcelableException(e); } } final PackageStats stats = new PackageStats(TAG); try { mInstaller.getAppSize(volumeUuid, packageNames, userId, getDefaultFlags(), appId, ceDataInodes, codePaths, stats); Loading Loading @@ -587,6 +592,9 @@ public class StorageStatsService extends IStorageStatsManager.Stub { res.codeBytes = stats.codeSize + stats.externalCodeSize; res.dataBytes = stats.dataSize + stats.externalDataSize; res.cacheBytes = stats.cacheSize + stats.externalCacheSize; res.apkBytes = stats.apkSize; res.libBytes = stats.libSize; res.dmBytes = stats.dmSize; res.externalCacheBytes = stats.externalCacheSize; return res; } Loading Loading @@ -894,4 +902,61 @@ public class StorageStatsService extends IStorageStatsManager.Stub { mStorageStatsAugmenters.add(Pair.create(tag, storageStatsAugmenter)); } } private long getDirBytes(File dir) { if (!dir.isDirectory()) { return 0; } long size = 0; try { for (File file : dir.listFiles()) { if (file.isFile()) { size += file.length(); continue; } if (file.isDirectory()) { size += getDirBytes(file); } } } catch (NullPointerException e) { Slog.w(TAG, "Failed to list directory " + dir.getName()); } return size; } private long getFileBytesInDir(File dir, String suffix) { if (!dir.isDirectory()) { return 0; } long size = 0; try { for (File file : dir.listFiles()) { if (file.isFile() && file.getName().endsWith(suffix)) { size += file.length(); } } } catch (NullPointerException e) { Slog.w(TAG, "Failed to list directory " + dir.getName()); } return size; } private void computeAppStatsByDataTypes( PackageStats stats, String sourceDirName) { // Get apk, lib, dm file sizes. File srcDir = new File(sourceDirName); if (srcDir.isFile()) { sourceDirName = srcDir.getParent(); srcDir = new File(sourceDirName); } stats.apkSize += getFileBytesInDir(srcDir, ".apk"); stats.dmSize += getFileBytesInDir(srcDir, ".dm"); stats.libSize += getDirBytes(new File(sourceDirName + "/lib/")); } } Loading
core/api/current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -9315,10 +9315,14 @@ package android.app.usage { public final class StorageStats implements android.os.Parcelable { method public int describeContents(); method public long getAppBytes(); method @FlaggedApi("android.app.usage.get_app_bytes_by_data_type_api") public long getAppBytesByDataType(int); method public long getCacheBytes(); method public long getDataBytes(); method public long getExternalCacheBytes(); method public void writeToParcel(android.os.Parcel, int); field @FlaggedApi("android.app.usage.get_app_bytes_by_data_type_api") public static final int APP_DATA_TYPE_FILE_TYPE_APK = 0; // 0x0 field @FlaggedApi("android.app.usage.get_app_bytes_by_data_type_api") public static final int APP_DATA_TYPE_FILE_TYPE_DM = 1; // 0x1 field @FlaggedApi("android.app.usage.get_app_bytes_by_data_type_api") public static final int APP_DATA_TYPE_LIB = 2; // 0x2 field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR; }
core/java/android/app/usage/StorageStats.java +73 −4 Original line number Diff line number Diff line Loading @@ -17,11 +17,16 @@ package android.app.usage; import android.annotation.BytesLong; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Storage statistics for a UID, package, or {@link UserHandle} on a single * storage volume. Loading @@ -29,10 +34,47 @@ import android.os.UserHandle; * @see StorageStatsManager */ public final class StorageStats implements Parcelable { /** {@hide} */ public long codeBytes; /** {@hide} */ public long dataBytes; /** {@hide} */ public long cacheBytes; /** {@hide} */ public long externalCacheBytes; /** @hide */ public long codeBytes; /** @hide */ public long dataBytes; /** @hide */ public long cacheBytes; /** @hide */ public long apkBytes; /** @hide */ public long libBytes; /** @hide */ public long dmBytes; /** @hide */ public long externalCacheBytes; /** Represents all .apk files in application code path. * Can be used as an input to {@link #getAppBytesByDataType(int)} * to get the sum of sizes for files of this type. */ @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API) public static final int APP_DATA_TYPE_FILE_TYPE_APK = 0; /** Represents all .dm files in application code path. * Can be used as an input to {@link #getAppBytesByDataType(int)} * to get the sum of sizes for files of this type. */ @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API) public static final int APP_DATA_TYPE_FILE_TYPE_DM = 1; /** Represents lib/ in application code path. * Can be used as an input to {@link #getAppBytesByDataType(int)} * to get the size of lib/ directory. */ @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API) public static final int APP_DATA_TYPE_LIB = 2; /** * Keep in sync with the file types defined above. * @hide */ @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API) @IntDef(flag = false, value = { APP_DATA_TYPE_FILE_TYPE_APK, APP_DATA_TYPE_FILE_TYPE_DM, APP_DATA_TYPE_LIB, }) @Retention(RetentionPolicy.SOURCE) public @interface AppDataType {} /** * Return the size of app. This includes {@code APK} files, optimized Loading @@ -47,6 +89,27 @@ public final class StorageStats implements Parcelable { return codeBytes; } /** * Return the size of the specified data type. This includes files stored under * application code path. * <p> * If there is more than one package inside a uid, the return represents the aggregated * stats when query StorageStat for package or uid. * The data is not collected and the return defaults to 0 when query StorageStats for user. * * <p> * Data is isolated for each user on a multiuser device. */ @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API) public long getAppBytesByDataType(@AppDataType int dataType) { switch (dataType) { case APP_DATA_TYPE_FILE_TYPE_APK: return apkBytes; case APP_DATA_TYPE_LIB: return libBytes; case APP_DATA_TYPE_FILE_TYPE_DM: return dmBytes; default: return 0; } } /** * Return the size of all data. This includes files stored under * {@link Context#getDataDir()}, {@link Context#getCacheDir()}, Loading Loading @@ -98,6 +161,9 @@ public final class StorageStats implements Parcelable { this.codeBytes = in.readLong(); this.dataBytes = in.readLong(); this.cacheBytes = in.readLong(); this.apkBytes = in.readLong(); this.libBytes = in.readLong(); this.dmBytes = in.readLong(); this.externalCacheBytes = in.readLong(); } Loading @@ -111,6 +177,9 @@ public final class StorageStats implements Parcelable { dest.writeLong(codeBytes); dest.writeLong(dataBytes); dest.writeLong(cacheBytes); dest.writeLong(apkBytes); dest.writeLong(libBytes); dest.writeLong(dmBytes); dest.writeLong(externalCacheBytes); } Loading
core/java/android/app/usage/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -35,3 +35,10 @@ flag { description: " Feature flag to support filter based event query API" bug: "194321117" } flag { name: "get_app_bytes_by_data_type_api" namespace: "system_performance" description: "Feature flag for collecting app data size by file type API" bug: "294088945" }
core/java/android/content/pm/PackageStats.java +38 −1 Original line number Diff line number Diff line Loading @@ -55,6 +55,18 @@ public class PackageStats implements Parcelable { /** Size of cache used by the application. (e.g., /data/data/<app>/cache) */ public long cacheSize; /** Size of .apk files of the application. */ /** @hide */ public long apkSize; /** Size of the libraries of the application. */ /** @hide */ public long libSize; /** Size of the .dm files of the application. */ /** @hide */ public long dmSize; /** * Size of the secure container on external storage holding the * application's code. Loading Loading @@ -108,6 +120,18 @@ public class PackageStats implements Parcelable { sb.append(" cache="); sb.append(cacheSize); } if (apkSize != 0) { sb.append(" apk="); sb.append(apkSize); } if (libSize != 0) { sb.append(" lib="); sb.append(libSize); } if (dmSize != 0) { sb.append(" dm="); sb.append(dmSize); } if (externalCodeSize != 0) { sb.append(" extCode="); sb.append(externalCodeSize); Loading Loading @@ -149,6 +173,9 @@ public class PackageStats implements Parcelable { codeSize = source.readLong(); dataSize = source.readLong(); cacheSize = source.readLong(); apkSize = source.readLong(); libSize = source.readLong(); dmSize = source.readLong(); externalCodeSize = source.readLong(); externalDataSize = source.readLong(); externalCacheSize = source.readLong(); Loading @@ -162,6 +189,9 @@ public class PackageStats implements Parcelable { codeSize = pStats.codeSize; dataSize = pStats.dataSize; cacheSize = pStats.cacheSize; apkSize = pStats.apkSize; libSize = pStats.libSize; dmSize = pStats.dmSize; externalCodeSize = pStats.externalCodeSize; externalDataSize = pStats.externalDataSize; externalCacheSize = pStats.externalCacheSize; Loading @@ -179,6 +209,9 @@ public class PackageStats implements Parcelable { dest.writeLong(codeSize); dest.writeLong(dataSize); dest.writeLong(cacheSize); dest.writeLong(apkSize); dest.writeLong(libSize); dest.writeLong(dmSize); dest.writeLong(externalCodeSize); dest.writeLong(externalDataSize); dest.writeLong(externalCacheSize); Loading @@ -198,6 +231,9 @@ public class PackageStats implements Parcelable { && codeSize == otherStats.codeSize && dataSize == otherStats.dataSize && cacheSize == otherStats.cacheSize && apkSize == otherStats.apkSize && libSize == otherStats.libSize && dmSize == otherStats.dmSize && externalCodeSize == otherStats.externalCodeSize && externalDataSize == otherStats.externalDataSize && externalCacheSize == otherStats.externalCacheSize Loading @@ -208,7 +244,8 @@ public class PackageStats implements Parcelable { @Override public int hashCode() { return Objects.hash(packageName, userHandle, codeSize, dataSize, cacheSize, externalCodeSize, externalDataSize, externalCacheSize, externalMediaSize, apkSize, libSize, dmSize, cacheSize, externalCodeSize, externalDataSize, externalCacheSize, externalMediaSize, externalObbSize); } Loading
services/usage/java/com/android/server/usage/StorageStatsService.java +67 −2 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.app.usage.ExternalStorageStats; import android.app.usage.Flags; import android.app.usage.IStorageStatsManager; import android.app.usage.StorageStats; import android.app.usage.UsageStatsManagerInternal; Loading Loading @@ -434,6 +435,7 @@ public class StorageStatsService extends IStorageStatsManager.Stub { final long[] ceDataInodes = new long[packageNames.length]; String[] codePaths = new String[0]; final PackageStats stats = new PackageStats(TAG); for (int i = 0; i < packageNames.length; i++) { try { final ApplicationInfo appInfo = mPackage.getApplicationInfoAsUser(packageNames[i], Loading @@ -445,13 +447,16 @@ public class StorageStatsService extends IStorageStatsManager.Stub { codePaths = ArrayUtils.appendElement(String.class, codePaths, appInfo.getCodePath()); } if (Flags.getAppBytesByDataTypeApi()) { computeAppStatsByDataTypes( stats, appInfo.sourceDir); } } } catch (NameNotFoundException e) { throw new ParcelableException(e); } } final PackageStats stats = new PackageStats(TAG); try { mInstaller.getAppSize(volumeUuid, packageNames, userId, getDefaultFlags(), appId, ceDataInodes, codePaths, stats); Loading Loading @@ -587,6 +592,9 @@ public class StorageStatsService extends IStorageStatsManager.Stub { res.codeBytes = stats.codeSize + stats.externalCodeSize; res.dataBytes = stats.dataSize + stats.externalDataSize; res.cacheBytes = stats.cacheSize + stats.externalCacheSize; res.apkBytes = stats.apkSize; res.libBytes = stats.libSize; res.dmBytes = stats.dmSize; res.externalCacheBytes = stats.externalCacheSize; return res; } Loading Loading @@ -894,4 +902,61 @@ public class StorageStatsService extends IStorageStatsManager.Stub { mStorageStatsAugmenters.add(Pair.create(tag, storageStatsAugmenter)); } } private long getDirBytes(File dir) { if (!dir.isDirectory()) { return 0; } long size = 0; try { for (File file : dir.listFiles()) { if (file.isFile()) { size += file.length(); continue; } if (file.isDirectory()) { size += getDirBytes(file); } } } catch (NullPointerException e) { Slog.w(TAG, "Failed to list directory " + dir.getName()); } return size; } private long getFileBytesInDir(File dir, String suffix) { if (!dir.isDirectory()) { return 0; } long size = 0; try { for (File file : dir.listFiles()) { if (file.isFile() && file.getName().endsWith(suffix)) { size += file.length(); } } } catch (NullPointerException e) { Slog.w(TAG, "Failed to list directory " + dir.getName()); } return size; } private void computeAppStatsByDataTypes( PackageStats stats, String sourceDirName) { // Get apk, lib, dm file sizes. File srcDir = new File(sourceDirName); if (srcDir.isFile()) { sourceDirName = srcDir.getParent(); srcDir = new File(sourceDirName); } stats.apkSize += getFileBytesInDir(srcDir, ".apk"); stats.dmSize += getFileBytesInDir(srcDir, ".dm"); stats.libSize += getDirBytes(new File(sourceDirName + "/lib/")); } }