Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f0bb51b1 authored by Neharika Jali's avatar Neharika Jali
Browse files

Change reserved cache space as sum of cache quotas of all uids

Bug: 203650406
Test: atest
frameworks/base/core/tests/coretests/src/android/os/storage/StorageManagerBaseTest
atest
cts/tests/tests/os/src/android/os/storage/cts/StorageManagerTest#testComputeStorageCacheBytes
Change-Id: I72710c89961ecc16b27ebb0647798f28e2e810ca
parent 97c0d421
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -341,6 +341,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
+1 −0
Original line number Diff line number Diff line
@@ -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);
+67 −16
Original line number Diff line number Diff line
@@ -1434,11 +1434,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);

@@ -1462,7 +1487,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,
@@ -1471,29 +1496,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);
        }
    }

+48 −1
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
@@ -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
     *