Loading core/api/module-lib-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -349,6 +349,7 @@ package android.os { package android.os.storage { public class StorageManager { method public long computeStorageCacheBytes(@NonNull java.io.File); method public void notifyAppIoBlocked(@NonNull java.util.UUID, int, int, int); method public void notifyAppIoResumed(@NonNull java.util.UUID, int, int, int); field public static final int APP_IO_BLOCKED_REASON_TRANSCODING = 1; // 0x1 Loading core/api/test-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -1976,6 +1976,7 @@ package android.os.storage { } public class StorageManager { method public long computeStorageCacheBytes(@NonNull java.io.File); method @NonNull public static java.util.UUID convert(@NonNull String); method @NonNull public static String convert(@NonNull java.util.UUID); method public boolean isAppIoBlocked(@NonNull java.util.UUID, int, int, int); Loading core/java/android/os/storage/StorageManager.java +67 −16 Original line number Diff line number Diff line Loading @@ -1437,11 +1437,36 @@ public class StorageManager { throw new IllegalStateException("Missing primary storage"); } private static final int DEFAULT_THRESHOLD_PERCENTAGE = 5; private static final long DEFAULT_THRESHOLD_MAX_BYTES = DataUnit.MEBIBYTES.toBytes(500); /** * Devices having above STORAGE_THRESHOLD_PERCENT_HIGH of total space free are considered to be * in high free space category. * * @hide */ public static final int STORAGE_THRESHOLD_PERCENT_HIGH = 20; /** * Devices having below STORAGE_THRESHOLD_PERCENT_LOW of total space free are considered to be * in low free space category. * * @hide */ public static final int STORAGE_THRESHOLD_PERCENT_LOW = 5; /** * For devices in high free space category, CACHE_RESERVE_PERCENT_HIGH percent of total space is * allocated for cache. * * @hide */ public static final int CACHE_RESERVE_PERCENT_HIGH = 10; /** * For devices in low free space category, CACHE_RESERVE_PERCENT_LOW percent of total space is * allocated for cache. * * @hide */ public static final int CACHE_RESERVE_PERCENT_LOW = 2; private static final int DEFAULT_CACHE_PERCENTAGE = 10; private static final long DEFAULT_CACHE_MAX_BYTES = DataUnit.GIBIBYTES.toBytes(5); private static final long DEFAULT_THRESHOLD_MAX_BYTES = DataUnit.MEBIBYTES.toBytes(500); private static final long DEFAULT_FULL_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(1); Loading @@ -1465,7 +1490,7 @@ public class StorageManager { @UnsupportedAppUsage public long getStorageLowBytes(File path) { final long lowPercent = Settings.Global.getInt(mResolver, Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE, DEFAULT_THRESHOLD_PERCENTAGE); Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE, STORAGE_THRESHOLD_PERCENT_LOW); final long lowBytes = (path.getTotalSpace() * lowPercent) / 100; final long maxLowBytes = Settings.Global.getLong(mResolver, Loading @@ -1474,29 +1499,55 @@ public class StorageManager { return Math.min(lowBytes, maxLowBytes); } /** * Compute the minimum number of bytes of storage on the device that could * be reserved for cached data depending on the device state which is then passed on * to getStorageCacheBytes. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @TestApi @SuppressLint("StreamFiles") public long computeStorageCacheBytes(@NonNull File path) { final long totalBytes = path.getTotalSpace(); final long usableBytes = path.getUsableSpace(); final long storageThresholdHighBytes = totalBytes * STORAGE_THRESHOLD_PERCENT_HIGH / 100; final long storageThresholdLowBytes = getStorageLowBytes(path); long result; if (usableBytes > storageThresholdHighBytes) { // If free space is >STORAGE_THRESHOLD_PERCENT_HIGH of total space, // reserve CACHE_RESERVE_PERCENT_HIGH of total space result = totalBytes * CACHE_RESERVE_PERCENT_HIGH / 100; } else if (usableBytes < storageThresholdLowBytes) { // If free space is <min(STORAGE_THRESHOLD_PERCENT_LOW of total space, 500MB), // reserve CACHE_RESERVE_PERCENT_LOW of total space result = totalBytes * CACHE_RESERVE_PERCENT_LOW / 100; } else { // Else, linearly interpolate the amount of space to reserve result = ((CACHE_RESERVE_PERCENT_HIGH - CACHE_RESERVE_PERCENT_LOW) * (usableBytes - storageThresholdHighBytes) + CACHE_RESERVE_PERCENT_HIGH * (storageThresholdHighBytes - storageThresholdLowBytes)) * totalBytes / (100 * (storageThresholdHighBytes - storageThresholdLowBytes)); } return result; } /** * Return the minimum number of bytes of storage on the device that should * be reserved for cached data. * * @hide */ public long getStorageCacheBytes(File path, @AllocateFlags int flags) { final long cachePercent = Settings.Global.getInt(mResolver, Settings.Global.SYS_STORAGE_CACHE_PERCENTAGE, DEFAULT_CACHE_PERCENTAGE); final long cacheBytes = (path.getTotalSpace() * cachePercent) / 100; final long maxCacheBytes = Settings.Global.getLong(mResolver, Settings.Global.SYS_STORAGE_CACHE_MAX_BYTES, DEFAULT_CACHE_MAX_BYTES); final long result = Math.min(cacheBytes, maxCacheBytes); public long getStorageCacheBytes(@NonNull File path, @AllocateFlags int flags) { if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { return 0; } else if ((flags & StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED) != 0) { return 0; } else if ((flags & StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED) != 0) { return result / 2; return computeStorageCacheBytes(path) / 2; } else { return result; return computeStorageCacheBytes(path); } } Loading core/tests/coretests/src/android/os/storage/StorageManagerBaseTest.java +48 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package android.os.storage; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; import android.test.InstrumentationTestCase; Loading @@ -23,6 +27,10 @@ import android.util.Log; import libcore.io.Streams; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.File; Loading @@ -39,6 +47,7 @@ public class StorageManagerBaseTest extends InstrumentationTestCase { protected Context mContext = null; protected StorageManager mSm = null; @Mock private File mFile; private static String LOG_TAG = "StorageManagerBaseTest"; protected static final long MAX_WAIT_TIME = 120*1000; protected static final long WAIT_TIME_INCR = 5*1000; Loading Loading @@ -121,11 +130,49 @@ public class StorageManagerBaseTest extends InstrumentationTestCase { */ @Override public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContext = getInstrumentation().getContext(); mSm = (StorageManager)mContext.getSystemService(android.content.Context.STORAGE_SERVICE); } /** * Tests the space reserved for cache when system has high free space i.e. more than * StorageManager.STORAGE_THRESHOLD_PERCENT_HIGH of total space. */ @Test public void testGetStorageCacheBytesUnderHighStorage() throws Exception { when(mFile.getUsableSpace()).thenReturn(10000L); when(mFile.getTotalSpace()).thenReturn(15000L); long result = mSm.getStorageCacheBytes(mFile, 0); assertThat(result).isEqualTo(1500L); } /** * Tests the space reserved for cache when system has low free space i.e. less than * StorageManager.STORAGE_THRESHOLD_PERCENT_LOW of total space. */ @Test public void testGetStorageCacheBytesUnderLowStorage() throws Exception { when(mFile.getUsableSpace()).thenReturn(10000L); when(mFile.getTotalSpace()).thenReturn(250000L); long result = mSm.getStorageCacheBytes(mFile, 0); assertThat(result).isEqualTo(5000L); } /** * Tests the space reserved for cache when system has moderate free space i.e.more than * StorageManager.STORAGE_THRESHOLD_PERCENT_LOW of total space but less than * StorageManager.STORAGE_THRESHOLD_PERCENT_HIGH of total space. */ @Test public void testGetStorageCacheBytesUnderModerateStorage() throws Exception { when(mFile.getUsableSpace()).thenReturn(10000L); when(mFile.getTotalSpace()).thenReturn(100000L); long result = mSm.getStorageCacheBytes(mFile, 0); assertThat(result).isEqualTo(4666L); } /** * Creates an OBB file (with the given name), into the app's standard files directory * Loading Loading
core/api/module-lib-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -349,6 +349,7 @@ package android.os { package android.os.storage { public class StorageManager { method public long computeStorageCacheBytes(@NonNull java.io.File); method public void notifyAppIoBlocked(@NonNull java.util.UUID, int, int, int); method public void notifyAppIoResumed(@NonNull java.util.UUID, int, int, int); field public static final int APP_IO_BLOCKED_REASON_TRANSCODING = 1; // 0x1 Loading
core/api/test-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -1976,6 +1976,7 @@ package android.os.storage { } public class StorageManager { method public long computeStorageCacheBytes(@NonNull java.io.File); method @NonNull public static java.util.UUID convert(@NonNull String); method @NonNull public static String convert(@NonNull java.util.UUID); method public boolean isAppIoBlocked(@NonNull java.util.UUID, int, int, int); Loading
core/java/android/os/storage/StorageManager.java +67 −16 Original line number Diff line number Diff line Loading @@ -1437,11 +1437,36 @@ public class StorageManager { throw new IllegalStateException("Missing primary storage"); } private static final int DEFAULT_THRESHOLD_PERCENTAGE = 5; private static final long DEFAULT_THRESHOLD_MAX_BYTES = DataUnit.MEBIBYTES.toBytes(500); /** * Devices having above STORAGE_THRESHOLD_PERCENT_HIGH of total space free are considered to be * in high free space category. * * @hide */ public static final int STORAGE_THRESHOLD_PERCENT_HIGH = 20; /** * Devices having below STORAGE_THRESHOLD_PERCENT_LOW of total space free are considered to be * in low free space category. * * @hide */ public static final int STORAGE_THRESHOLD_PERCENT_LOW = 5; /** * For devices in high free space category, CACHE_RESERVE_PERCENT_HIGH percent of total space is * allocated for cache. * * @hide */ public static final int CACHE_RESERVE_PERCENT_HIGH = 10; /** * For devices in low free space category, CACHE_RESERVE_PERCENT_LOW percent of total space is * allocated for cache. * * @hide */ public static final int CACHE_RESERVE_PERCENT_LOW = 2; private static final int DEFAULT_CACHE_PERCENTAGE = 10; private static final long DEFAULT_CACHE_MAX_BYTES = DataUnit.GIBIBYTES.toBytes(5); private static final long DEFAULT_THRESHOLD_MAX_BYTES = DataUnit.MEBIBYTES.toBytes(500); private static final long DEFAULT_FULL_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(1); Loading @@ -1465,7 +1490,7 @@ public class StorageManager { @UnsupportedAppUsage public long getStorageLowBytes(File path) { final long lowPercent = Settings.Global.getInt(mResolver, Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE, DEFAULT_THRESHOLD_PERCENTAGE); Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE, STORAGE_THRESHOLD_PERCENT_LOW); final long lowBytes = (path.getTotalSpace() * lowPercent) / 100; final long maxLowBytes = Settings.Global.getLong(mResolver, Loading @@ -1474,29 +1499,55 @@ public class StorageManager { return Math.min(lowBytes, maxLowBytes); } /** * Compute the minimum number of bytes of storage on the device that could * be reserved for cached data depending on the device state which is then passed on * to getStorageCacheBytes. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @TestApi @SuppressLint("StreamFiles") public long computeStorageCacheBytes(@NonNull File path) { final long totalBytes = path.getTotalSpace(); final long usableBytes = path.getUsableSpace(); final long storageThresholdHighBytes = totalBytes * STORAGE_THRESHOLD_PERCENT_HIGH / 100; final long storageThresholdLowBytes = getStorageLowBytes(path); long result; if (usableBytes > storageThresholdHighBytes) { // If free space is >STORAGE_THRESHOLD_PERCENT_HIGH of total space, // reserve CACHE_RESERVE_PERCENT_HIGH of total space result = totalBytes * CACHE_RESERVE_PERCENT_HIGH / 100; } else if (usableBytes < storageThresholdLowBytes) { // If free space is <min(STORAGE_THRESHOLD_PERCENT_LOW of total space, 500MB), // reserve CACHE_RESERVE_PERCENT_LOW of total space result = totalBytes * CACHE_RESERVE_PERCENT_LOW / 100; } else { // Else, linearly interpolate the amount of space to reserve result = ((CACHE_RESERVE_PERCENT_HIGH - CACHE_RESERVE_PERCENT_LOW) * (usableBytes - storageThresholdHighBytes) + CACHE_RESERVE_PERCENT_HIGH * (storageThresholdHighBytes - storageThresholdLowBytes)) * totalBytes / (100 * (storageThresholdHighBytes - storageThresholdLowBytes)); } return result; } /** * Return the minimum number of bytes of storage on the device that should * be reserved for cached data. * * @hide */ public long getStorageCacheBytes(File path, @AllocateFlags int flags) { final long cachePercent = Settings.Global.getInt(mResolver, Settings.Global.SYS_STORAGE_CACHE_PERCENTAGE, DEFAULT_CACHE_PERCENTAGE); final long cacheBytes = (path.getTotalSpace() * cachePercent) / 100; final long maxCacheBytes = Settings.Global.getLong(mResolver, Settings.Global.SYS_STORAGE_CACHE_MAX_BYTES, DEFAULT_CACHE_MAX_BYTES); final long result = Math.min(cacheBytes, maxCacheBytes); public long getStorageCacheBytes(@NonNull File path, @AllocateFlags int flags) { if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) { return 0; } else if ((flags & StorageManager.FLAG_ALLOCATE_DEFY_ALL_RESERVED) != 0) { return 0; } else if ((flags & StorageManager.FLAG_ALLOCATE_DEFY_HALF_RESERVED) != 0) { return result / 2; return computeStorageCacheBytes(path) / 2; } else { return result; return computeStorageCacheBytes(path); } } Loading
core/tests/coretests/src/android/os/storage/StorageManagerBaseTest.java +48 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package android.os.storage; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; import android.test.InstrumentationTestCase; Loading @@ -23,6 +27,10 @@ import android.util.Log; import libcore.io.Streams; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.File; Loading @@ -39,6 +47,7 @@ public class StorageManagerBaseTest extends InstrumentationTestCase { protected Context mContext = null; protected StorageManager mSm = null; @Mock private File mFile; private static String LOG_TAG = "StorageManagerBaseTest"; protected static final long MAX_WAIT_TIME = 120*1000; protected static final long WAIT_TIME_INCR = 5*1000; Loading Loading @@ -121,11 +130,49 @@ public class StorageManagerBaseTest extends InstrumentationTestCase { */ @Override public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mContext = getInstrumentation().getContext(); mSm = (StorageManager)mContext.getSystemService(android.content.Context.STORAGE_SERVICE); } /** * Tests the space reserved for cache when system has high free space i.e. more than * StorageManager.STORAGE_THRESHOLD_PERCENT_HIGH of total space. */ @Test public void testGetStorageCacheBytesUnderHighStorage() throws Exception { when(mFile.getUsableSpace()).thenReturn(10000L); when(mFile.getTotalSpace()).thenReturn(15000L); long result = mSm.getStorageCacheBytes(mFile, 0); assertThat(result).isEqualTo(1500L); } /** * Tests the space reserved for cache when system has low free space i.e. less than * StorageManager.STORAGE_THRESHOLD_PERCENT_LOW of total space. */ @Test public void testGetStorageCacheBytesUnderLowStorage() throws Exception { when(mFile.getUsableSpace()).thenReturn(10000L); when(mFile.getTotalSpace()).thenReturn(250000L); long result = mSm.getStorageCacheBytes(mFile, 0); assertThat(result).isEqualTo(5000L); } /** * Tests the space reserved for cache when system has moderate free space i.e.more than * StorageManager.STORAGE_THRESHOLD_PERCENT_LOW of total space but less than * StorageManager.STORAGE_THRESHOLD_PERCENT_HIGH of total space. */ @Test public void testGetStorageCacheBytesUnderModerateStorage() throws Exception { when(mFile.getUsableSpace()).thenReturn(10000L); when(mFile.getTotalSpace()).thenReturn(100000L); long result = mSm.getStorageCacheBytes(mFile, 0); assertThat(result).isEqualTo(4666L); } /** * Creates an OBB file (with the given name), into the app's standard files directory * Loading