Home | History | Annotate | Download | only in storage
      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.settings.deviceinfo.storage;
     18 
     19 import static com.google.common.truth.Truth.assertThat;
     20 
     21 import static org.mockito.Matchers.any;
     22 import static org.mockito.Matchers.anyInt;
     23 import static org.mockito.Matchers.anyString;
     24 import static org.mockito.Matchers.eq;
     25 import static org.mockito.Mockito.mock;
     26 import static org.mockito.Mockito.when;
     27 
     28 import android.content.Context;
     29 import android.content.pm.ApplicationInfo;
     30 import android.content.pm.PackageManager.NameNotFoundException;
     31 import android.content.pm.UserInfo;
     32 import android.net.TrafficStats;
     33 import android.os.UserHandle;
     34 import android.support.test.filters.SmallTest;
     35 import android.support.test.runner.AndroidJUnit4;
     36 import android.util.SparseArray;
     37 
     38 import com.android.settings.applications.PackageManagerWrapper;
     39 import com.android.settings.applications.UserManagerWrapper;
     40 import com.android.settingslib.applications.StorageStatsSource;
     41 
     42 import org.junit.Before;
     43 import org.junit.Test;
     44 import org.junit.runner.RunWith;
     45 import org.mockito.Answers;
     46 import org.mockito.Mock;
     47 import org.mockito.MockitoAnnotations;
     48 
     49 import java.util.ArrayList;
     50 import java.util.List;
     51 
     52 @RunWith(AndroidJUnit4.class)
     53 @SmallTest
     54 public class StorageAsyncLoaderTest {
     55     private static final int PRIMARY_USER_ID = 0;
     56     private static final int SECONDARY_USER_ID = 10;
     57     private static final String PACKAGE_NAME_1 = "com.blah.test";
     58     private static final String PACKAGE_NAME_2 = "com.blah.test2";
     59     private static final long DEFAULT_QUOTA = 64 * TrafficStats.MB_IN_BYTES;
     60 
     61     @Mock
     62     private StorageStatsSource mSource;
     63     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     64     private Context mContext;
     65     @Mock
     66     private PackageManagerWrapper mPackageManager;
     67     @Mock
     68     private UserManagerWrapper mUserManager;
     69     private List<ApplicationInfo> mInfo = new ArrayList<>();
     70     private List<UserInfo> mUsers;
     71 
     72     private StorageAsyncLoader mLoader;
     73 
     74 
     75     @Before
     76     public void setUp() throws Exception {
     77         MockitoAnnotations.initMocks(this);
     78         mInfo = new ArrayList<>();
     79         mLoader = new StorageAsyncLoader(mContext, mUserManager, "id", mSource, mPackageManager);
     80         when(mPackageManager.getInstalledApplicationsAsUser(eq(PRIMARY_USER_ID), anyInt()))
     81                 .thenReturn(mInfo);
     82         UserInfo info = new UserInfo();
     83         mUsers = new ArrayList<>();
     84         mUsers.add(info);
     85         when(mUserManager.getUsers()).thenReturn(mUsers);
     86         when(mSource.getCacheQuotaBytes(anyString(), anyInt())).thenReturn(DEFAULT_QUOTA);
     87     }
     88 
     89     @Test
     90     public void testLoadingApps() throws Exception {
     91         addPackage(PACKAGE_NAME_1, 0, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED);
     92         addPackage(PACKAGE_NAME_2, 0, 100, 1000, ApplicationInfo.CATEGORY_UNDEFINED);
     93 
     94         SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
     95 
     96         assertThat(result.size()).isEqualTo(1);
     97         assertThat(result.get(PRIMARY_USER_ID).gamesSize).isEqualTo(0L);
     98         assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(1111L);
     99     }
    100 
    101     @Test
    102     public void testGamesAreFiltered() throws Exception {
    103         addPackage(PACKAGE_NAME_1, 0, 1, 10, ApplicationInfo.CATEGORY_GAME);
    104 
    105         SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
    106 
    107         assertThat(result.size()).isEqualTo(1);
    108         assertThat(result.get(PRIMARY_USER_ID).gamesSize).isEqualTo(11L);
    109         assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(0);
    110     }
    111 
    112     @Test
    113     public void testLegacyGamesAreFiltered() throws Exception {
    114         ApplicationInfo info =
    115                 addPackage(PACKAGE_NAME_1, 0, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED);
    116         info.flags = ApplicationInfo.FLAG_IS_GAME;
    117 
    118         SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
    119 
    120         assertThat(result.size()).isEqualTo(1);
    121         assertThat(result.get(PRIMARY_USER_ID).gamesSize).isEqualTo(11L);
    122         assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(0);
    123     }
    124 
    125     @Test
    126     public void testCacheIsNotIgnored() throws Exception {
    127         addPackage(PACKAGE_NAME_1, 100, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED);
    128 
    129         SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
    130 
    131         assertThat(result.size()).isEqualTo(1);
    132         assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(111L);
    133     }
    134 
    135     @Test
    136     public void testMultipleUsers() throws Exception {
    137         UserInfo info = new UserInfo();
    138         info.id = SECONDARY_USER_ID;
    139         mUsers.add(info);
    140         when(mSource.getExternalStorageStats(anyString(), eq(UserHandle.SYSTEM)))
    141                 .thenReturn(new StorageStatsSource.ExternalStorageStats(9, 2, 3, 4, 0));
    142         when(mSource.getExternalStorageStats(anyString(), eq(new UserHandle(SECONDARY_USER_ID))))
    143                 .thenReturn(new StorageStatsSource.ExternalStorageStats(10, 3, 3, 4, 0));
    144 
    145         SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
    146 
    147         assertThat(result.size()).isEqualTo(2);
    148         assertThat(result.get(PRIMARY_USER_ID).externalStats.totalBytes).isEqualTo(9L);
    149         assertThat(result.get(SECONDARY_USER_ID).externalStats.totalBytes).isEqualTo(10L);
    150     }
    151 
    152     @Test
    153     public void testUpdatedSystemAppCodeSizeIsCounted() throws Exception {
    154         ApplicationInfo systemApp =
    155                 addPackage(PACKAGE_NAME_1, 100, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED);
    156         systemApp.flags = ApplicationInfo.FLAG_SYSTEM & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
    157 
    158         SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
    159 
    160         assertThat(result.size()).isEqualTo(1);
    161         assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(111L);
    162     }
    163 
    164     @Test
    165     public void testVideoAppsAreFiltered() throws Exception {
    166         addPackage(PACKAGE_NAME_1, 0, 1, 10, ApplicationInfo.CATEGORY_VIDEO);
    167 
    168         SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
    169 
    170         assertThat(result.size()).isEqualTo(1);
    171         assertThat(result.get(PRIMARY_USER_ID).videoAppsSize).isEqualTo(11L);
    172         assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(0);
    173     }
    174 
    175     @Test
    176     public void testRemovedPackageDoesNotCrash() throws Exception {
    177         ApplicationInfo info = new ApplicationInfo();
    178         info.packageName = PACKAGE_NAME_1;
    179         info.category = ApplicationInfo.CATEGORY_UNDEFINED;
    180         mInfo.add(info);
    181         when(mSource.getStatsForPackage(anyString(), anyString(), any(UserHandle.class)))
    182                 .thenThrow(new NameNotFoundException());
    183 
    184         SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
    185 
    186         // Should not crash.
    187     }
    188 
    189     @Test
    190     public void testPackageIsNotDoubleCounted() throws Exception {
    191         UserInfo info = new UserInfo();
    192         info.id = SECONDARY_USER_ID;
    193         mUsers.add(info);
    194         when(mSource.getExternalStorageStats(anyString(), eq(UserHandle.SYSTEM)))
    195                 .thenReturn(new StorageStatsSource.ExternalStorageStats(9, 2, 3, 4, 0));
    196         when(mSource.getExternalStorageStats(anyString(), eq(new UserHandle(SECONDARY_USER_ID))))
    197                 .thenReturn(new StorageStatsSource.ExternalStorageStats(10, 3, 3, 4, 0));
    198         addPackage(PACKAGE_NAME_1, 0, 1, 10, ApplicationInfo.CATEGORY_VIDEO);
    199         ArrayList<ApplicationInfo> secondaryUserApps = new ArrayList<>();
    200         ApplicationInfo appInfo = new ApplicationInfo();
    201         appInfo.packageName = PACKAGE_NAME_1;
    202         appInfo.category = ApplicationInfo.CATEGORY_VIDEO;
    203         secondaryUserApps.add(appInfo);
    204 
    205         SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
    206 
    207         assertThat(result.size()).isEqualTo(2);
    208         assertThat(result.get(PRIMARY_USER_ID).videoAppsSize).isEqualTo(11L);
    209         // No code size for the second user.
    210         assertThat(result.get(SECONDARY_USER_ID).videoAppsSize).isEqualTo(10L);
    211     }
    212 
    213     @Test
    214     public void testCacheOveragesAreCountedAsFree() throws Exception {
    215         addPackage(PACKAGE_NAME_1, DEFAULT_QUOTA + 100, 1, 10, ApplicationInfo.CATEGORY_UNDEFINED);
    216 
    217         SparseArray<StorageAsyncLoader.AppsStorageResult> result = mLoader.loadInBackground();
    218 
    219         assertThat(result.size()).isEqualTo(1);
    220         assertThat(result.get(PRIMARY_USER_ID).otherAppsSize).isEqualTo(DEFAULT_QUOTA + 11);
    221     }
    222 
    223     private ApplicationInfo addPackage(String packageName, long cacheSize, long codeSize,
    224             long dataSize, int category) throws Exception {
    225         StorageStatsSource.AppStorageStats storageStats =
    226                 mock(StorageStatsSource.AppStorageStats.class);
    227         when(storageStats.getCodeBytes()).thenReturn(codeSize);
    228         when(storageStats.getDataBytes()).thenReturn(dataSize + cacheSize);
    229         when(storageStats.getCacheBytes()).thenReturn(cacheSize);
    230         when(mSource.getStatsForPackage(anyString(), eq(packageName), any(UserHandle.class)))
    231                 .thenReturn(storageStats);
    232 
    233         ApplicationInfo info = new ApplicationInfo();
    234         info.packageName = packageName;
    235         info.category = category;
    236         mInfo.add(info);
    237         return info;
    238     }
    239 
    240 }
    241