1ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei/* 2ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * Copyright (C) 2016 The Android Open Source Project 3ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * 4ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * use this file except in compliance with the License. You may obtain a copy of 6ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * the License at 7ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * 8ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * http://www.apache.org/licenses/LICENSE-2.0 9ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * 10ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * Unless required by applicable law or agreed to in writing, software 11ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * License for the specific language governing permissions and limitations under 14ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * the License. 15ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei */ 16ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 17ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleipackage com.android.storagemanager.deletionhelper; 18ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 19ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport android.app.usage.UsageStats; 20ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport android.app.usage.UsageStatsManager; 21ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport android.content.Context; 22ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport android.content.pm.ApplicationInfo; 23ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport android.content.pm.PackageInfo; 24ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport android.os.Looper; 25ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport com.android.settingslib.applications.ApplicationsState; 26ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport com.android.storagemanager.testing.TestingConstants; 27ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport com.android.storagemanager.deletionhelper.AppStateUsageStatsBridge.UsageStatsState; 28ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.junit.Before; 29ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.junit.Test; 30ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.junit.runner.RunWith; 31ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.mockito.ArgumentCaptor; 32ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.mockito.Mock; 33ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.mockito.MockitoAnnotations; 34ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.robolectric.RobolectricTestRunner; 35ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.robolectric.RuntimeEnvironment; 36ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.robolectric.Shadows; 37ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.robolectric.annotation.Config; 38ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.robolectric.res.builder.RobolectricPackageManager; 39bfc2b11b9357c4508756243f540760458611b3b8jackqdyuleiimport org.robolectric.shadows.ShadowApplication; 40ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 41ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport java.util.ArrayList; 42ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport java.util.HashMap; 43ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport java.util.concurrent.TimeUnit; 44ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 45ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static com.google.common.truth.Truth.assertThat; 46ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static org.mockito.Matchers.any; 47ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static org.mockito.Matchers.anyLong; 48ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static org.mockito.Mockito.atLeastOnce; 49ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static org.mockito.Mockito.mock; 50b96906a082511a5390700818257c8a215637b9e9jackqdyuleiimport static org.mockito.Mockito.verify; 51ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static org.mockito.Mockito.when; 52ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 53ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei@RunWith(RobolectricTestRunner.class) 54ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei@Config(manifest=TestingConstants.MANIFEST, sdk=23) 55ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleipublic class AppStateUsageStatsBridgeTest { 56ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 57ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei public static final String PACKAGE_SYSTEM = "package.system"; 58ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private static final long STARTING_TIME = TimeUnit.DAYS.toMillis(1000); 59ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private static final String PACKAGE_NAME = "package.mcpackageface"; 60ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei public static final String PACKAGE_CLEARABLE = "package.clearable"; 61ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei public static final String PACKAGE_TOO_NEW_TO_DELETE = "package.tooNewToDelete"; 62ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 63ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock private ApplicationsState mState; 64ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock private ApplicationsState.Session mSession; 65ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock private UsageStatsManager mUsageStatsManager; 66ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock private AppStateUsageStatsBridge.Clock mClock; 67ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private AppStateUsageStatsBridge mBridge; 68ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private ArrayList<ApplicationsState.AppEntry> mApps; 69ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private HashMap<String, UsageStats> mUsageStats; 70ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private RobolectricPackageManager mPm; 71ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 72ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Before 73ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei public void setUp() { 74ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei MockitoAnnotations.initMocks(this); 75ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 76ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei // Set up the application state. 77ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei when(mState.newSession(any(ApplicationsState.Callbacks.class))).thenReturn(mSession); 78ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei when(mState.getBackgroundLooper()).thenReturn(Looper.getMainLooper()); 79ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 80ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei // Set up the ApplicationState's session to return our fake list of apps. 81ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mApps = new ArrayList<>(); 82ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei when(mSession.getAllApps()).thenReturn(mApps); 83ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 84bfc2b11b9357c4508756243f540760458611b3b8jackqdyulei // Set up our mock usage stats service. 85bfc2b11b9357c4508756243f540760458611b3b8jackqdyulei ShadowApplication app = Shadows.shadowOf(RuntimeEnvironment.application); 86ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mPm = RuntimeEnvironment.getRobolectricPackageManager(); 87ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei app.setSystemService(Context.USAGE_STATS_SERVICE, mUsageStatsManager); 88ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 89ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei // Set up the AppStateUsageStatsBridge with a fake clock for us to manipulate the time. 90ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei when(mClock.getCurrentTime()).thenReturn(STARTING_TIME); 91ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBridge = new AppStateUsageStatsBridge(RuntimeEnvironment.application, mState, null); 92ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBridge.mClock = mClock; 93ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei AppStateUsageStatsBridge.FILTER_USAGE_STATS.init(); 94ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 95ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei // Set up our fake usage stats. 96b96906a082511a5390700818257c8a215637b9e9jackqdyulei mUsageStats = new HashMap<>(); 97b96906a082511a5390700818257c8a215637b9e9jackqdyulei when(mUsageStatsManager.queryAndAggregateUsageStats(anyLong(), 98bfc2b11b9357c4508756243f540760458611b3b8jackqdyulei anyLong())).thenReturn(mUsageStats); 99ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei } 100ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 101ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Test 102ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei public void test_appInstalledSameDayNeverUsed_isInvalid() { 103ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei ApplicationsState.AppEntry app = 104ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(1000)); 105ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 106ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 107ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei UsageStatsState stats = (UsageStatsState) app.extraInfo; 108ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 109ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(app.extraInfo).isNotNull(); 110ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(stats.daysSinceFirstInstall).isEqualTo(0); 111ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(stats.daysSinceLastUse).isEqualTo(AppStateUsageStatsBridge.NEVER_USED); 112ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(app)).isFalse(); 113bfc2b11b9357c4508756243f540760458611b3b8jackqdyulei } 114bfc2b11b9357c4508756243f540760458611b3b8jackqdyulei 115ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Test 116ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei public void test_noThresholdFilter_appInstalledSameDayNeverUsed_isValid() { 117ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei ApplicationsState.AppEntry app = 118ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(1000)); 119ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 120ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 121ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei UsageStatsState stats = (UsageStatsState) app.extraInfo; 122ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 123ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(app.extraInfo).isNotNull(); 124ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(stats.daysSinceFirstInstall).isEqualTo(0); 125ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(stats.daysSinceLastUse).isEqualTo(AppStateUsageStatsBridge.NEVER_USED); 126ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(AppStateUsageStatsBridge.FILTER_NO_THRESHOLD.filterApp(app)).isTrue(); 127ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei } 128ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 129ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Test 130ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei public void test_unusedApp_isValid() { 131ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei ApplicationsState.AppEntry app = 132ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(910)); 133ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 134ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 135ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei UsageStatsState stats = (UsageStatsState) app.extraInfo; 136ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 137ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(app.extraInfo).isNotNull(); 138ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(stats.daysSinceFirstInstall).isEqualTo(90); 139ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(stats.daysSinceLastUse).isEqualTo(AppStateUsageStatsBridge.NEVER_USED); 140ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(app)).isTrue(); 141ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei } 142ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 143ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Test 144ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei public void test_noThresholdFilter_unusedApp_isValid() { 145ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei ApplicationsState.AppEntry app = 146ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(910)); 147ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 148ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 149ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei UsageStatsState stats = (UsageStatsState) app.extraInfo; 150ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 151ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(app.extraInfo).isNotNull(); 152ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(stats.daysSinceFirstInstall).isEqualTo(90); 153ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(stats.daysSinceLastUse).isEqualTo(AppStateUsageStatsBridge.NEVER_USED); 154ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(AppStateUsageStatsBridge.FILTER_NO_THRESHOLD.filterApp(app)).isTrue(); 155ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei } 156ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 157ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Test 158edfebbaa4f3ffa98c99e1e41b054853ccbff06c7jackqdyulei public void test_unknownLastUse_isFilteredOut() { 159ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei ApplicationsState.AppEntry app = 160ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(910)); 161ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei registerLastUse(PACKAGE_NAME, -1); 162ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 163 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 164 UsageStatsState stats = (UsageStatsState) app.extraInfo; 165 166 assertThat(app.extraInfo).isNotNull(); 167 assertThat(stats.daysSinceFirstInstall).isEqualTo(90); 168 assertThat(stats.daysSinceLastUse).isEqualTo(AppStateUsageStatsBridge.UNKNOWN_LAST_USE); 169 assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(app)).isFalse(); 170 } 171 172 @Test 173 public void test_noThresholdFilter_unknownLastUse_isFilteredOut() { 174 ApplicationsState.AppEntry app = 175 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(910)); 176 registerLastUse(PACKAGE_NAME, -1); 177 178 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 179 UsageStatsState stats = (UsageStatsState) app.extraInfo; 180 181 assertThat(app.extraInfo).isNotNull(); 182 assertThat(stats.daysSinceFirstInstall).isEqualTo(90); 183 assertThat(stats.daysSinceLastUse).isEqualTo(AppStateUsageStatsBridge.UNKNOWN_LAST_USE); 184 assertThat(AppStateUsageStatsBridge.FILTER_NO_THRESHOLD.filterApp(app)).isFalse(); 185 } 186 187 @Test 188 public void test_oldAppRecentlyUsed_isNotValid() { 189 ApplicationsState.AppEntry app = 190 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 191 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(999)); 192 193 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 194 UsageStatsState stats = (UsageStatsState) app.extraInfo; 195 196 assertThat(app.extraInfo).isNotNull(); 197 assertThat(stats.daysSinceFirstInstall).isEqualTo(200); 198 assertThat(stats.daysSinceLastUse).isEqualTo(1); 199 assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(app)).isFalse(); 200 } 201 202 @Test 203 public void test_noThresholdFilter_oldAppRecentlyUsed_isValid() { 204 ApplicationsState.AppEntry app = 205 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 206 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(999)); 207 208 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 209 UsageStatsState stats = (UsageStatsState) app.extraInfo; 210 211 assertThat(app.extraInfo).isNotNull(); 212 assertThat(stats.daysSinceFirstInstall).isEqualTo(200); 213 assertThat(stats.daysSinceLastUse).isEqualTo(1); 214 assertThat(AppStateUsageStatsBridge.FILTER_NO_THRESHOLD.filterApp(app)).isTrue(); 215 } 216 217 @Test 218 public void test_oldUnusedApp_isValid() { 219 ApplicationsState.AppEntry app = 220 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 221 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(801)); 222 223 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 224 UsageStatsState stats = (UsageStatsState) app.extraInfo; 225 226 assertThat(app.extraInfo).isNotNull(); 227 assertThat(stats.daysSinceFirstInstall).isEqualTo(200); 228 assertThat(stats.daysSinceLastUse).isEqualTo(199); 229 assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(app)).isTrue(); 230 } 231 232 @Test 233 public void test_noThresholdFilter_oldUnusedApp_isValid() { 234 ApplicationsState.AppEntry app = 235 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 236 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(801)); 237 238 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 239 UsageStatsState stats = (UsageStatsState) app.extraInfo; 240 241 assertThat(app.extraInfo).isNotNull(); 242 assertThat(stats.daysSinceFirstInstall).isEqualTo(200); 243 assertThat(stats.daysSinceLastUse).isEqualTo(199); 244 assertThat(AppStateUsageStatsBridge.FILTER_NO_THRESHOLD.filterApp(app)).isTrue(); 245 } 246 247 @Test 248 public void test_systemApps_areInvalid() { 249 ApplicationsState.AppEntry app = 250 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 251 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 252 app.info.flags = ApplicationInfo.FLAG_SYSTEM; 253 254 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 255 UsageStatsState stats = (UsageStatsState) app.extraInfo; 256 257 assertThat(app.extraInfo).isNotNull(); 258 assertThat(stats.daysSinceFirstInstall).isEqualTo(200); 259 assertThat(stats.daysSinceLastUse).isEqualTo(200); 260 assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(app)).isFalse(); 261 } 262 263 @Test 264 public void test_noThresholdFilter_systemApps_areInvalid() { 265 ApplicationsState.AppEntry app = 266 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 267 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 268 app.info.flags = ApplicationInfo.FLAG_SYSTEM; 269 270 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 271 UsageStatsState stats = (UsageStatsState) app.extraInfo; 272 273 assertThat(app.extraInfo).isNotNull(); 274 assertThat(stats.daysSinceFirstInstall).isEqualTo(200); 275 assertThat(stats.daysSinceLastUse).isEqualTo(200); 276 assertThat(AppStateUsageStatsBridge.FILTER_NO_THRESHOLD.filterApp(app)).isFalse(); 277 } 278 279 @Test 280 public void test_persistentProcessApps_areInvalid() { 281 ApplicationsState.AppEntry app = 282 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 283 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 284 app.info.flags = ApplicationInfo.FLAG_PERSISTENT; 285 286 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 287 UsageStatsState stats = (UsageStatsState) app.extraInfo; 288 289 assertThat(app.extraInfo).isNotNull(); 290 assertThat(stats.daysSinceFirstInstall).isEqualTo(200); 291 assertThat(stats.daysSinceLastUse).isEqualTo(200); 292 assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(app)).isFalse(); 293 } 294 295 @Test 296 public void test_noThresholdFilter_persistentProcessApps_areInvalid() { 297 ApplicationsState.AppEntry app = 298 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 299 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 300 app.info.flags = ApplicationInfo.FLAG_PERSISTENT; 301 302 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 303 UsageStatsState stats = (UsageStatsState) app.extraInfo; 304 305 assertThat(app.extraInfo).isNotNull(); 306 assertThat(stats.daysSinceFirstInstall).isEqualTo(200); 307 assertThat(stats.daysSinceLastUse).isEqualTo(200); 308 assertThat(AppStateUsageStatsBridge.FILTER_NO_THRESHOLD.filterApp(app)).isFalse(); 309 } 310 311 @Test 312 public void test_multipleApps_processCorrectly() { 313 ApplicationsState.AppEntry clearable = 314 addPackageToPackageManager(PACKAGE_CLEARABLE, TimeUnit.DAYS.toMillis(800)); 315 registerLastUse(PACKAGE_CLEARABLE, TimeUnit.DAYS.toMillis(800)); 316 mApps.add(clearable); 317 ApplicationsState.AppEntry tooNewtoDelete = 318 addPackageToPackageManager(PACKAGE_TOO_NEW_TO_DELETE, TimeUnit.DAYS.toMillis(1000)); 319 registerLastUse(PACKAGE_TOO_NEW_TO_DELETE, TimeUnit.DAYS.toMillis(1000)); 320 mApps.add(tooNewtoDelete); 321 ApplicationsState.AppEntry systemApp = 322 addPackageToPackageManager(PACKAGE_SYSTEM, TimeUnit.DAYS.toMillis(800)); 323 registerLastUse(PACKAGE_SYSTEM, TimeUnit.DAYS.toMillis(800)); 324 systemApp.info.flags = ApplicationInfo.FLAG_SYSTEM; 325 mApps.add(systemApp); 326 ApplicationsState.AppEntry persistentApp = 327 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 328 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 329 persistentApp.info.flags = ApplicationInfo.FLAG_PERSISTENT; 330 mApps.add(persistentApp); 331 332 mBridge.loadAllExtraInfo(); 333 334 assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(clearable)).isTrue(); 335 assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(tooNewtoDelete)).isFalse(); 336 assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(systemApp)).isFalse(); 337 assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(persistentApp)).isFalse(); 338 } 339 340 @Test 341 public void test_noThresholdFilter_ignoresUsageForFiltering() { 342 ApplicationsState.AppEntry clearable = 343 addPackageToPackageManager(PACKAGE_CLEARABLE, TimeUnit.DAYS.toMillis(800)); 344 registerLastUse(PACKAGE_CLEARABLE, TimeUnit.DAYS.toMillis(800)); 345 mApps.add(clearable); 346 ApplicationsState.AppEntry tooNewtoDelete = 347 addPackageToPackageManager(PACKAGE_TOO_NEW_TO_DELETE, TimeUnit.DAYS.toMillis(1000)); 348 registerLastUse(PACKAGE_TOO_NEW_TO_DELETE, TimeUnit.DAYS.toMillis(1000)); 349 mApps.add(tooNewtoDelete); 350 ApplicationsState.AppEntry systemApp = 351 addPackageToPackageManager(PACKAGE_SYSTEM, TimeUnit.DAYS.toMillis(800)); 352 registerLastUse(PACKAGE_SYSTEM, TimeUnit.DAYS.toMillis(800)); 353 systemApp.info.flags = ApplicationInfo.FLAG_SYSTEM; 354 mApps.add(systemApp); 355 ApplicationsState.AppEntry persistentApp = 356 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 357 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(800)); 358 persistentApp.info.flags = ApplicationInfo.FLAG_PERSISTENT; 359 mApps.add(persistentApp); 360 361 mBridge.loadAllExtraInfo(); 362 363 assertThat(AppStateUsageStatsBridge.FILTER_NO_THRESHOLD.filterApp(clearable)).isTrue(); 364 assertThat(AppStateUsageStatsBridge.FILTER_NO_THRESHOLD.filterApp(tooNewtoDelete)).isTrue(); 365 assertThat(AppStateUsageStatsBridge.FILTER_NO_THRESHOLD.filterApp(systemApp)).isFalse(); 366 assertThat(AppStateUsageStatsBridge.FILTER_NO_THRESHOLD.filterApp(persistentApp)).isFalse(); 367 } 368 369 @Test 370 public void testAppUsedOverOneYearAgoIsValid() { 371 ApplicationsState.AppEntry app = 372 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(600)); 373 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(1000 - 366)); 374 375 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 376 UsageStatsState stats = (UsageStatsState) app.extraInfo; 377 378 assertThat(app.extraInfo).isNotNull(); 379 assertThat(stats.daysSinceFirstInstall).isEqualTo(400); 380 assertThat(stats.daysSinceLastUse).isEqualTo(AppStateUsageStatsBridge.NEVER_USED); 381 assertThat(AppStateUsageStatsBridge.FILTER_USAGE_STATS.filterApp(app)).isTrue(); 382 } 383 384 @Test 385 public void testStartEndIsBeforeEndTimeInQuery() { 386 ApplicationsState.AppEntry app = 387 addPackageToPackageManager(PACKAGE_NAME, TimeUnit.DAYS.toMillis(600)); 388 registerLastUse(PACKAGE_NAME, TimeUnit.DAYS.toMillis(1000 - 366)); 389 ArgumentCaptor<Long> startTimeCaptor = ArgumentCaptor.forClass(Long.class); 390 ArgumentCaptor<Long> endTimeCaptor = ArgumentCaptor.forClass(Long.class); 391 392 mBridge.updateExtraInfo(app, PACKAGE_NAME, 0); 393 394 verify(mUsageStatsManager, atLeastOnce()) 395 .queryAndAggregateUsageStats(startTimeCaptor.capture(), endTimeCaptor.capture()); 396 assertThat(startTimeCaptor.getValue()).isLessThan(endTimeCaptor.getValue()); 397 } 398 399 private ApplicationsState.AppEntry addPackageToPackageManager(String packageName, 400 long installTime) { 401 PackageInfo testPackage = new PackageInfo(); 402 testPackage.packageName = packageName; 403 testPackage.firstInstallTime = installTime; 404 mPm.addPackage(testPackage); 405 ApplicationsState.AppEntry app = mock(ApplicationsState.AppEntry.class); 406 ApplicationInfo info = mock(ApplicationInfo.class); 407 info.packageName = packageName; 408 app.info = info; 409 return app; 410 } 411 412 private void registerLastUse(String packageName, long time) { 413 UsageStats usageStats = mock(UsageStats.class); 414 when(usageStats.getPackageName()).thenReturn(packageName); 415 when(usageStats.getLastTimeUsed()).thenReturn(time); 416 mUsageStats.put(packageName, usageStats); 417 } 418 419 private class FakeClock extends AppStateUsageStatsBridge.Clock { 420 public long time; 421 422 @Override 423 public long getCurrentTime() { 424 return time; 425 } 426 } 427} 428