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

Commit fa214993 authored by Neharika Jali's avatar Neharika Jali Committed by Android (Google) Code Review
Browse files

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

parents fcf3a92a f0bb51b1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+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
@@ -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);

@@ -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,
@@ -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);
        }
    }

+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
     *