diff options
author | Hung-ying Tyan <tyanh@google.com> | 2024-01-12 09:30:11 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-01-12 09:30:11 +0000 |
commit | c9363add3d2ea5eb049bd75b7bc9daa6ba5d6fee (patch) | |
tree | f648e17608fb2a5802d966509aecc83dce0d3660 | |
parent | 2c8bbf1e23f4b531335a4dedca2d8973e3046644 (diff) | |
parent | f5dd1ea3e2d84fff14087f1d46b3656cdf2307fa (diff) | |
download | base-c9363add3d2ea5eb049bd75b7bc9daa6ba5d6fee.tar.gz |
Merge "Fix StorageStatsService#getTotalBytes" into android14-gsi
6 files changed, 83 insertions, 56 deletions
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index af09a0662795..5b24dcacbf53 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -1294,32 +1294,30 @@ public final class FileUtils { * Round the given size of a storage device to a nice round power-of-two * value, such as 256MB or 32GB. This avoids showing weird values like * "29.5GB" in UI. - * - * Some storage devices are still using GiB (powers of 1024) over - * GB (powers of 1000) measurements and this method takes it into account. - * * Round ranges: * ... - * [256 GiB + 1; 512 GiB] -> 512 GB - * [512 GiB + 1; 1 TiB] -> 1 TB - * [1 TiB + 1; 2 TiB] -> 2 TB + * (128 GB; 256 GB] -> 256 GB + * (256 GB; 512 GB] -> 512 GB + * (512 GB; 1000 GB] -> 1000 GB + * (1000 GB; 2000 GB] -> 2000 GB + * ... * etc * * @hide */ public static long roundStorageSize(long size) { long val = 1; - long kiloPow = 1; - long kibiPow = 1; - while ((val * kibiPow) < size) { + long pow = 1; + while ((val * pow) < size) { val <<= 1; if (val > 512) { val = 1; - kibiPow *= 1024; - kiloPow *= 1000; + pow *= 1000; } } - return val * kiloPow; + + Log.d(TAG, String.format("Rounded bytes from %d to %d", size, val * pow)); + return val * pow; } private static long toBytes(long value, String unit) { diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl index bc52744078ea..369a1932e437 100644 --- a/core/java/android/os/storage/IStorageManager.aidl +++ b/core/java/android/os/storage/IStorageManager.aidl @@ -174,4 +174,5 @@ interface IStorageManager { boolean isAppIoBlocked(in String volumeUuid, int uid, int tid, int reason) = 95; void setCloudMediaProvider(in String authority) = 96; String getCloudMediaProvider() = 97; + long getInternalStorageBlockDeviceSize() = 98; }
\ No newline at end of file diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 80dd48825ba7..ee387e7c284f 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1359,6 +1359,15 @@ public class StorageManager { } /** {@hide} */ + public long getInternalStorageBlockDeviceSize() { + try { + return mStorageManager.getInternalStorageBlockDeviceSize(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** {@hide} */ public void mkdirs(File file) { BlockGuard.getVmPolicy().onPathAccess(file.getAbsolutePath()); try { diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java index 394ff0ae9a2e..a0d8183b8da7 100644 --- a/core/tests/coretests/src/android/os/FileUtilsTest.java +++ b/core/tests/coretests/src/android/os/FileUtilsTest.java @@ -505,45 +505,32 @@ public class FileUtilsTest { @Test public void testRoundStorageSize() throws Exception { - final long GB1 = DataUnit.GIGABYTES.toBytes(1); - final long GiB1 = DataUnit.GIBIBYTES.toBytes(1); - final long GB2 = DataUnit.GIGABYTES.toBytes(2); - final long GiB2 = DataUnit.GIBIBYTES.toBytes(2); - final long GiB128 = DataUnit.GIBIBYTES.toBytes(128); - final long GB256 = DataUnit.GIGABYTES.toBytes(256); - final long GiB256 = DataUnit.GIBIBYTES.toBytes(256); - final long GB512 = DataUnit.GIGABYTES.toBytes(512); - final long GiB512 = DataUnit.GIBIBYTES.toBytes(512); - final long TB1 = DataUnit.TERABYTES.toBytes(1); - final long TiB1 = DataUnit.TEBIBYTES.toBytes(1); - final long TB2 = DataUnit.TERABYTES.toBytes(2); - final long TiB2 = DataUnit.TEBIBYTES.toBytes(2); - final long TB4 = DataUnit.TERABYTES.toBytes(4); - final long TiB4 = DataUnit.TEBIBYTES.toBytes(4); - final long TB8 = DataUnit.TERABYTES.toBytes(8); - final long TiB8 = DataUnit.TEBIBYTES.toBytes(8); - - assertEquals(GB1, roundStorageSize(GB1 - 1)); - assertEquals(GB1, roundStorageSize(GB1)); - assertEquals(GB1, roundStorageSize(GB1 + 1)); - assertEquals(GB1, roundStorageSize(GiB1 - 1)); - assertEquals(GB1, roundStorageSize(GiB1)); - assertEquals(GB2, roundStorageSize(GiB1 + 1)); - assertEquals(GB2, roundStorageSize(GiB2)); - - assertEquals(GB256, roundStorageSize(GiB128 + 1)); - assertEquals(GB256, roundStorageSize(GiB256)); - assertEquals(GB512, roundStorageSize(GiB256 + 1)); - assertEquals(GB512, roundStorageSize(GiB512)); - assertEquals(TB1, roundStorageSize(GiB512 + 1)); - assertEquals(TB1, roundStorageSize(TiB1)); - assertEquals(TB2, roundStorageSize(TiB1 + 1)); - assertEquals(TB2, roundStorageSize(TiB2)); - assertEquals(TB4, roundStorageSize(TiB2 + 1)); - assertEquals(TB4, roundStorageSize(TiB4)); - assertEquals(TB8, roundStorageSize(TiB4 + 1)); - assertEquals(TB8, roundStorageSize(TiB8)); - assertEquals(TB1, roundStorageSize(1013077688320L)); // b/268571529 + final long M256 = DataUnit.MEGABYTES.toBytes(256); + final long M512 = DataUnit.MEGABYTES.toBytes(512); + final long G1 = DataUnit.GIGABYTES.toBytes(1); + final long G2 = DataUnit.GIGABYTES.toBytes(2); + final long G32 = DataUnit.GIGABYTES.toBytes(32); + final long G64 = DataUnit.GIGABYTES.toBytes(64); + final long G512 = DataUnit.GIGABYTES.toBytes(512); + final long G1000 = DataUnit.TERABYTES.toBytes(1); + final long G2000 = DataUnit.TERABYTES.toBytes(2); + + assertEquals(M256, roundStorageSize(M256 - 1)); + assertEquals(M256, roundStorageSize(M256)); + assertEquals(M512, roundStorageSize(M256 + 1)); + assertEquals(M512, roundStorageSize(M512 - 1)); + assertEquals(M512, roundStorageSize(M512)); + assertEquals(G1, roundStorageSize(M512 + 1)); + assertEquals(G1, roundStorageSize(G1)); + assertEquals(G2, roundStorageSize(G1 + 1)); + + assertEquals(G32, roundStorageSize(G32 - 1)); + assertEquals(G32, roundStorageSize(G32)); + assertEquals(G64, roundStorageSize(G32 + 1)); + + assertEquals(G512, roundStorageSize(G512 - 1)); + assertEquals(G1000, roundStorageSize(G512 + 1)); + assertEquals(G2000, roundStorageSize(G1000 + 1)); } @Test diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 73dbb86ae7cc..d47573d52767 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -73,8 +73,8 @@ import android.content.pm.ProviderInfo; import android.content.pm.UserInfo; import android.content.res.ObbInfo; import android.database.ContentObserver; -import android.media.MediaCodecList; import android.media.MediaCodecInfo; +import android.media.MediaCodecList; import android.media.MediaFormat; import android.net.Uri; import android.os.BatteryManager; @@ -219,6 +219,8 @@ class StorageManagerService extends IStorageManager.Stub @GuardedBy("mLock") private final Set<Integer> mCeStoragePreparedUsers = new ArraySet<>(); + private volatile long mInternalStorageSize = 0; + public static class Lifecycle extends SystemService { private StorageManagerService mStorageManagerService; @@ -3479,6 +3481,15 @@ class StorageManagerService extends IStorageManager.Stub return authority; } + @Override + public long getInternalStorageBlockDeviceSize() throws RemoteException { + if (mInternalStorageSize == 0) { + mInternalStorageSize = mVold.getStorageSize(); + } + + return mInternalStorageSize; + } + /** * Enforces that the caller is the {@link ExternalStorageService} * diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java index 0d88a0d485ff..030615fd7527 100644 --- a/services/usage/java/com/android/server/usage/StorageStatsService.java +++ b/services/usage/java/com/android/server/usage/StorageStatsService.java @@ -259,7 +259,24 @@ public class StorageStatsService extends IStorageStatsManager.Stub { // NOTE: No permissions required if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) { - return FileUtils.roundStorageSize(mStorage.getPrimaryStorageSize()); + // As a safety measure, use the original implementation for the devices + // with storage size <= 512GB to prevent any potential regressions + final long roundedUserspaceBytes = mStorage.getPrimaryStorageSize(); + if (roundedUserspaceBytes <= DataUnit.GIGABYTES.toBytes(512)) { + return roundedUserspaceBytes; + } + + // Since 1TB devices can actually have either 1000GB or 1024GB, + // get the block device size and do just a small rounding if any at all + final long totalBytes = mStorage.getInternalStorageBlockDeviceSize(); + final long totalBytesRounded = FileUtils.roundStorageSize(totalBytes); + // If the storage size is 997GB-999GB, round it to a 1000GB to show + // 1TB in UI instead of 0.99TB. Same for 2TB, 4TB, 8TB etc. + if (totalBytesRounded - totalBytes <= DataUnit.GIGABYTES.toBytes(3)) { + return totalBytesRounded; + } else { + return totalBytes; + } } else { final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid); if (vol == null) { @@ -286,15 +303,19 @@ public class StorageStatsService extends IStorageStatsManager.Stub { // Free space is usable bytes plus any cached data that we're // willing to automatically clear. To avoid user confusion, this // logic should be kept in sync with getAllocatableBytes(). + long freeBytes; if (isQuotaSupported(volumeUuid, PLATFORM_PACKAGE_NAME)) { final long cacheTotal = getCacheBytes(volumeUuid, PLATFORM_PACKAGE_NAME); final long cacheReserved = mStorage.getStorageCacheBytes(path, 0); final long cacheClearable = Math.max(0, cacheTotal - cacheReserved); - return path.getUsableSpace() + cacheClearable; + freeBytes = path.getUsableSpace() + cacheClearable; } else { - return path.getUsableSpace(); + freeBytes = path.getUsableSpace(); } + + Slog.d(TAG, "getFreeBytes: " + freeBytes); + return freeBytes; } finally { Binder.restoreCallingIdentity(token); } |