Home | History | Annotate | Download | only in storageapp
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.cts.storageapp;
     18 
     19 import static com.android.cts.storageapp.Utils.CACHE_ALL;
     20 import static com.android.cts.storageapp.Utils.CACHE_EXT;
     21 import static com.android.cts.storageapp.Utils.CACHE_INT;
     22 import static com.android.cts.storageapp.Utils.DATA_EXT;
     23 import static com.android.cts.storageapp.Utils.DATA_INT;
     24 import static com.android.cts.storageapp.Utils.MB_IN_BYTES;
     25 import static com.android.cts.storageapp.Utils.PKG_B;
     26 import static com.android.cts.storageapp.Utils.assertMostlyEquals;
     27 import static com.android.cts.storageapp.Utils.getSizeManual;
     28 import static com.android.cts.storageapp.Utils.makeUniqueFile;
     29 import static com.android.cts.storageapp.Utils.shouldHaveQuota;
     30 import static com.android.cts.storageapp.Utils.useSpace;
     31 
     32 import android.app.usage.StorageStats;
     33 import android.app.usage.StorageStatsManager;
     34 import android.content.ComponentName;
     35 import android.content.Context;
     36 import android.content.pm.ApplicationInfo;
     37 import android.content.pm.PackageManager;
     38 import android.os.Environment;
     39 import android.os.ParcelFileDescriptor;
     40 import android.os.UserHandle;
     41 import android.os.storage.StorageManager;
     42 import android.system.Os;
     43 import android.test.InstrumentationTestCase;
     44 
     45 import java.io.File;
     46 import java.io.IOException;
     47 import java.util.UUID;
     48 
     49 /**
     50  * Client app for verifying storage behaviors.
     51  */
     52 public class StorageTest extends InstrumentationTestCase {
     53     private Context getContext() {
     54         return getInstrumentation().getContext();
     55     }
     56 
     57     public void testAllocate() throws Exception {
     58         useSpace(getContext());
     59     }
     60 
     61     public void testFullDisk() throws Exception {
     62         if (shouldHaveQuota(Os.uname())) {
     63             final File dataDir = getContext().getDataDir();
     64 
     65             // Pre-flight to see if we have enough disk space to test with
     66             final long total = dataDir.getTotalSpace();
     67             final long free = dataDir.getFreeSpace();
     68             final long required = ((total * 9) / 10) + MB_IN_BYTES;
     69             if (free < required) {
     70                 fail("Skipping full disk test; only found " + free + " free out of " + total);
     71             }
     72 
     73             Hoarder.doBlocks(dataDir, true);
     74         } else {
     75             fail("Skipping full disk test due to missing quota support");
     76         }
     77     }
     78 
     79     public void testTweakComponent() throws Exception {
     80         getContext().getPackageManager().setComponentEnabledSetting(
     81                 new ComponentName(getContext().getPackageName(), UtilsReceiver.class.getName()),
     82                 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
     83     }
     84 
     85     /**
     86      * Measure ourselves manually.
     87      */
     88     public void testVerifySpaceManual() throws Exception {
     89         assertMostlyEquals(DATA_INT,
     90                 getSizeManual(getContext().getDataDir()));
     91         assertMostlyEquals(DATA_EXT,
     92                 getSizeManual(getContext().getExternalCacheDir().getParentFile()));
     93     }
     94 
     95     /**
     96      * Measure ourselves using platform APIs.
     97      */
     98     public void testVerifySpaceApi() throws Exception {
     99         final StorageManager sm = getContext().getSystemService(StorageManager.class);
    100         final StorageStatsManager stats = getContext().getSystemService(StorageStatsManager.class);
    101 
    102         final long cacheSize = sm.getCacheSizeBytes(
    103                 sm.getUuidForPath(getContext().getCacheDir()));
    104         final long extCacheSize = sm.getCacheSizeBytes(
    105                 sm.getUuidForPath(getContext().getExternalCacheDir()));
    106         if (cacheSize == extCacheSize) {
    107             assertMostlyEquals(CACHE_ALL, cacheSize);
    108         } else {
    109             assertMostlyEquals(CACHE_INT, cacheSize);
    110             assertMostlyEquals(CACHE_EXT, extCacheSize);
    111         }
    112 
    113         // Verify APIs that don't require any special permissions
    114         assertTrue(stats.getTotalBytes(StorageManager.UUID_DEFAULT) >= Environment
    115                 .getDataDirectory().getTotalSpace());
    116         assertTrue(stats.getFreeBytes(StorageManager.UUID_DEFAULT) >= Environment
    117                 .getDataDirectory().getUsableSpace());
    118 
    119         // Verify that we can see our own stats, and that they look sane
    120         ApplicationInfo ai = getContext().getApplicationInfo();
    121         final StorageStats pstats = stats.queryStatsForPackage(ai.storageUuid, ai.packageName,
    122                 UserHandle.getUserHandleForUid(ai.uid));
    123         final StorageStats ustats = stats.queryStatsForUid(ai.storageUuid, ai.uid);
    124         assertEquals(cacheSize, pstats.getCacheBytes());
    125         assertEquals(cacheSize, ustats.getCacheBytes());
    126 
    127         // Verify that other packages are off-limits
    128         ai = getContext().getPackageManager().getApplicationInfo(PKG_B, 0);
    129         try {
    130             stats.queryStatsForPackage(ai.storageUuid, ai.packageName,
    131                     UserHandle.getUserHandleForUid(ai.uid));
    132             fail("Unexpected access");
    133         } catch (SecurityException expected) {
    134         }
    135         try {
    136             stats.queryStatsForUid(ai.storageUuid, ai.uid);
    137             fail("Unexpected access");
    138         } catch (SecurityException expected) {
    139         }
    140         try {
    141             stats.queryExternalStatsForUser(StorageManager.UUID_DEFAULT,
    142                     android.os.Process.myUserHandle());
    143             fail("Unexpected access");
    144         } catch (SecurityException expected) {
    145         }
    146     }
    147 
    148     public void testVerifyQuotaApi() throws Exception {
    149         final StorageManager sm = getContext().getSystemService(StorageManager.class);
    150 
    151         final long cacheSize = sm.getCacheQuotaBytes(
    152                 sm.getUuidForPath(getContext().getCacheDir()));
    153         assertTrue("Apps must have at least 10MB quota", cacheSize > 10 * MB_IN_BYTES);
    154     }
    155 
    156     public void testVerifyAllocateApi() throws Exception {
    157         final StorageManager sm = getContext().getSystemService(StorageManager.class);
    158 
    159         final File filesDir = getContext().getFilesDir();
    160         final File extDir = Environment.getExternalStorageDirectory();
    161 
    162         final UUID filesUuid = sm.getUuidForPath(filesDir);
    163         final UUID extUuid = sm.getUuidForPath(extDir);
    164 
    165         assertTrue("Apps must be able to allocate internal space",
    166                 sm.getAllocatableBytes(filesUuid) > 10 * MB_IN_BYTES);
    167         assertTrue("Apps must be able to allocate external space",
    168                 sm.getAllocatableBytes(extUuid) > 10 * MB_IN_BYTES);
    169 
    170         // Should always be able to allocate 1MB indirectly
    171         sm.allocateBytes(filesUuid, 1 * MB_IN_BYTES);
    172 
    173         // Should always be able to allocate 1MB directly
    174         final File filesFile = makeUniqueFile(filesDir);
    175         assertEquals(0L, filesFile.length());
    176         try (ParcelFileDescriptor pfd = ParcelFileDescriptor.open(filesFile,
    177                 ParcelFileDescriptor.parseMode("rwt"))) {
    178             sm.allocateBytes(pfd.getFileDescriptor(), 1 * MB_IN_BYTES);
    179         }
    180         assertEquals(1 * MB_IN_BYTES, filesFile.length());
    181     }
    182 
    183     public void testBehaviorNormal() throws Exception {
    184         final StorageManager sm = getContext().getSystemService(StorageManager.class);
    185 
    186         final File dir = makeUniqueFile(getContext().getCacheDir());
    187         dir.mkdir();
    188         assertFalse(sm.isCacheBehaviorGroup(dir));
    189         assertFalse(sm.isCacheBehaviorTombstone(dir));
    190 
    191         final File ext = makeUniqueFile(getContext().getExternalCacheDir());
    192         ext.mkdir();
    193         try { sm.isCacheBehaviorGroup(ext); fail(); } catch (IOException expected) { }
    194         try { sm.isCacheBehaviorTombstone(ext); fail(); } catch (IOException expected) { }
    195     }
    196 
    197     public void testBehaviorGroup() throws Exception {
    198         final StorageManager sm = getContext().getSystemService(StorageManager.class);
    199 
    200         final File dir = makeUniqueFile(getContext().getCacheDir());
    201         dir.mkdir();
    202         sm.setCacheBehaviorGroup(dir, true);
    203         assertTrue(sm.isCacheBehaviorGroup(dir));
    204 
    205         final File ext = makeUniqueFile(getContext().getExternalCacheDir());
    206         ext.mkdir();
    207         try { sm.setCacheBehaviorGroup(ext, true); fail(); } catch (IOException expected) { }
    208         try { sm.setCacheBehaviorGroup(ext, false); fail(); } catch (IOException expected) { }
    209     }
    210 
    211     public void testBehaviorTombstone() throws Exception {
    212         final StorageManager sm = getContext().getSystemService(StorageManager.class);
    213 
    214         final File dir = makeUniqueFile(getContext().getCacheDir());
    215         dir.mkdir();
    216         sm.setCacheBehaviorTombstone(dir, true);
    217         assertTrue(sm.isCacheBehaviorTombstone(dir));
    218 
    219         final File ext = makeUniqueFile(getContext().getExternalCacheDir());
    220         ext.mkdir();
    221         try { sm.setCacheBehaviorTombstone(ext, true); fail(); } catch (IOException expected) { }
    222         try { sm.setCacheBehaviorTombstone(ext, false); fail(); } catch (IOException expected) { }
    223     }
    224 }
    225