diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index b478a37984e03..af09a06627955 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -1295,19 +1295,31 @@ public final class FileUtils { * 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 + * etc + * * @hide */ public static long roundStorageSize(long size) { long val = 1; - long pow = 1; - while ((val * pow) < size) { + long kiloPow = 1; + long kibiPow = 1; + while ((val * kibiPow) < size) { val <<= 1; if (val > 512) { val = 1; - pow *= 1000; + kibiPow *= 1024; + kiloPow *= 1000; } } - return val * pow; + return val * kiloPow; } private static long toBytes(long value, String unit) { diff --git a/core/java/android/util/DataUnit.java b/core/java/android/util/DataUnit.java index cf045b8aec065..cc33af32ba934 100644 --- a/core/java/android/util/DataUnit.java +++ b/core/java/android/util/DataUnit.java @@ -36,9 +36,11 @@ public enum DataUnit { KILOBYTES { @Override public long toBytes(long v) { return v * 1_000; } }, MEGABYTES { @Override public long toBytes(long v) { return v * 1_000_000; } }, GIGABYTES { @Override public long toBytes(long v) { return v * 1_000_000_000; } }, + TERABYTES { @Override public long toBytes(long v) { return v * 1_000_000_000_000L; } }, KIBIBYTES { @Override public long toBytes(long v) { return v * 1_024; } }, MEBIBYTES { @Override public long toBytes(long v) { return v * 1_048_576; } }, - GIBIBYTES { @Override public long toBytes(long v) { return v * 1_073_741_824; } }; + GIBIBYTES { @Override public long toBytes(long v) { return v * 1_073_741_824; } }, + TEBIBYTES { @Override public long toBytes(long v) { return v * 1_099_511_627_776L; } }; public long toBytes(long v) { throw new AbstractMethodError(); diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java index 91fbe00341337..394ff0ae9a2e4 100644 --- a/core/tests/coretests/src/android/os/FileUtilsTest.java +++ b/core/tests/coretests/src/android/os/FileUtilsTest.java @@ -54,6 +54,7 @@ import static org.junit.Assert.fail; import android.content.Context; import android.os.FileUtils.MemoryPipe; import android.provider.DocumentsContract.Document; +import android.util.DataUnit; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; @@ -504,31 +505,45 @@ public class FileUtilsTest { @Test public void testRoundStorageSize() throws Exception { - final long M128 = 128000000L; - final long M256 = 256000000L; - final long M512 = 512000000L; - final long G1 = 1000000000L; - final long G2 = 2000000000L; - final long G16 = 16000000000L; - final long G32 = 32000000000L; - final long G64 = 64000000000L; + 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(M128, roundStorageSize(M128)); - assertEquals(M256, roundStorageSize(M128 + 1)); - 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(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(G16, roundStorageSize(G16)); - assertEquals(G32, roundStorageSize(G16 + 1)); - assertEquals(G32, roundStorageSize(G32 - 1)); - assertEquals(G32, roundStorageSize(G32)); - assertEquals(G64, roundStorageSize(G32 + 1)); + 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 } @Test diff --git a/core/tests/coretests/src/android/util/DataUnitTest.java b/core/tests/coretests/src/android/util/DataUnitTest.java index ec296b76c3740..034cbddc0144b 100644 --- a/core/tests/coretests/src/android/util/DataUnitTest.java +++ b/core/tests/coretests/src/android/util/DataUnitTest.java @@ -26,11 +26,13 @@ public class DataUnitTest extends TestCase { assertEquals(12_000L, DataUnit.KILOBYTES.toBytes(12)); assertEquals(12_000_000L, DataUnit.MEGABYTES.toBytes(12)); assertEquals(12_000_000_000L, DataUnit.GIGABYTES.toBytes(12)); + assertEquals(12_000_000_000_000L, DataUnit.TERABYTES.toBytes(12)); } public void testIec() throws Exception { assertEquals(12_288L, DataUnit.KIBIBYTES.toBytes(12)); assertEquals(12_582_912L, DataUnit.MEBIBYTES.toBytes(12)); assertEquals(12_884_901_888L, DataUnit.GIBIBYTES.toBytes(12)); + assertEquals(13_194_139_533_312L, DataUnit.TEBIBYTES.toBytes(12)); } }