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