summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHung-ying Tyan <tyanh@google.com>2024-01-12 09:30:11 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-01-12 09:30:11 +0000
commitc9363add3d2ea5eb049bd75b7bc9daa6ba5d6fee (patch)
treef648e17608fb2a5802d966509aecc83dce0d3660
parent2c8bbf1e23f4b531335a4dedca2d8973e3046644 (diff)
parentf5dd1ea3e2d84fff14087f1d46b3656cdf2307fa (diff)
downloadbase-c9363add3d2ea5eb049bd75b7bc9daa6ba5d6fee.tar.gz
Merge "Fix StorageStatsService#getTotalBytes" into android14-gsi
-rw-r--r--core/java/android/os/FileUtils.java24
-rw-r--r--core/java/android/os/storage/IStorageManager.aidl1
-rw-r--r--core/java/android/os/storage/StorageManager.java9
-rw-r--r--core/tests/coretests/src/android/os/FileUtilsTest.java65
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java13
-rw-r--r--services/usage/java/com/android/server/usage/StorageStatsService.java27
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);
}