1 /* 2 * Copyright (C) 2019 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.server.am; 18 19 import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader; 20 21 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 22 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertNotNull; 25 import static org.mockito.Mockito.doReturn; 26 import static org.mockito.Mockito.mock; 27 import static org.mockito.Mockito.spy; 28 29 import android.app.ActivityManager; 30 import android.app.usage.UsageStatsManagerInternal; 31 import android.content.ComponentName; 32 import android.content.Context; 33 import android.content.pm.PackageManagerInternal; 34 35 import com.android.server.LocalServices; 36 import com.android.server.wm.ActivityTaskManagerService; 37 38 import org.junit.Before; 39 import org.junit.BeforeClass; 40 import org.junit.Test; 41 42 /** 43 * Test class for {@link OomAdjuster}. 44 * 45 * Build/Install/Run: 46 * atest FrameworksServicesTests:OomAdjusterTests 47 */ 48 public class OomAdjusterTests { 49 private static Context sContext; 50 private static ActivityManagerService sService; 51 private static PackageManagerInternal sPackageManagerInternal; 52 53 private ProcessRecord mProcessRecord; 54 55 private static final long ZERO = 0L; 56 private static final long USAGE_STATS_INTERACTION = 2 * 60 * 60 * 1000L; 57 private static final long SERVICE_USAGE_INTERACTION = 30 * 60 * 1000; 58 59 @BeforeClass setUpOnce()60 public static void setUpOnce() { 61 sContext = getInstrumentation().getTargetContext(); 62 63 sPackageManagerInternal = mock(PackageManagerInternal.class); 64 doReturn(new ComponentName("", "")).when(sPackageManagerInternal) 65 .getSystemUiServiceComponent(); 66 // Remove stale instance of PackageManagerInternal if there is any 67 LocalServices.removeServiceForTest(PackageManagerInternal.class); 68 LocalServices.addService(PackageManagerInternal.class, sPackageManagerInternal); 69 70 // We need to run with dexmaker share class loader to make use of 71 // ActivityTaskManagerService from wm package. 72 runWithDexmakerShareClassLoader(() -> { 73 sService = mock(ActivityManagerService.class); 74 sService.mActivityTaskManager = new ActivityTaskManagerService(sContext); 75 sService.mActivityTaskManager.initialize(null, null, sContext.getMainLooper()); 76 sService.mAtmInternal = sService.mActivityTaskManager.getAtmInternal(); 77 78 sService.mConstants = new ActivityManagerConstants(sContext, sService, 79 sContext.getMainThreadHandler()); 80 sService.mOomAdjuster = new OomAdjuster(sService, sService.mProcessList, null); 81 LocalServices.removeServiceForTest(UsageStatsManagerInternal.class); 82 LocalServices.addService(UsageStatsManagerInternal.class, 83 mock(UsageStatsManagerInternal.class)); 84 sService.mUsageStatsService = LocalServices.getService(UsageStatsManagerInternal.class); 85 }); 86 } 87 88 @Before setUpProcess()89 public void setUpProcess() { 90 // Need to run with dexmaker share class loader to mock package private class. 91 runWithDexmakerShareClassLoader(() -> { 92 mProcessRecord = spy(new ProcessRecord(sService, sContext.getApplicationInfo(), 93 "name", 12345)); 94 }); 95 96 // Ensure certain services and constants are defined properly 97 assertNotNull(sService.mUsageStatsService); 98 assertEquals(USAGE_STATS_INTERACTION, sService.mConstants.USAGE_STATS_INTERACTION_INTERVAL); 99 assertEquals(SERVICE_USAGE_INTERACTION, sService.mConstants.SERVICE_USAGE_INTERACTION_TIME); 100 } 101 102 @Test testMaybeUpdateUsageStats_ProcStatePersistentUI()103 public void testMaybeUpdateUsageStats_ProcStatePersistentUI() { 104 final long elapsedTime = ZERO; 105 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI); 106 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 107 108 assertProcessRecordState(ZERO, true, elapsedTime); 109 } 110 111 @Test testMaybeUpdateUsageStats_ProcStateTop()112 public void testMaybeUpdateUsageStats_ProcStateTop() { 113 final long elapsedTime = ZERO; 114 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_TOP); 115 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 116 117 assertProcessRecordState(ZERO, true, elapsedTime); 118 } 119 120 @Test testMaybeUpdateUsageStats_ProcStateTop_PreviousInteraction()121 public void testMaybeUpdateUsageStats_ProcStateTop_PreviousInteraction() { 122 final long elapsedTime = ZERO; 123 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_TOP); 124 mProcessRecord.reportedInteraction = true; 125 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 126 127 assertProcessRecordState(ZERO, true, ZERO); 128 } 129 130 @Test testMaybeUpdateUsageStats_ProcStateTop_PastUsageInterval()131 public void testMaybeUpdateUsageStats_ProcStateTop_PastUsageInterval() { 132 final long elapsedTime = 3 * USAGE_STATS_INTERACTION; 133 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_TOP); 134 mProcessRecord.reportedInteraction = true; 135 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 136 137 assertProcessRecordState(ZERO, true, elapsedTime); 138 } 139 140 @Test testMaybeUpdateUsageStats_ProcStateBoundTop()141 public void testMaybeUpdateUsageStats_ProcStateBoundTop() { 142 final long elapsedTime = ZERO; 143 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_BOUND_TOP); 144 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 145 146 assertProcessRecordState(ZERO, true, elapsedTime); 147 } 148 149 @Test testMaybeUpdateUsageStats_ProcStateFGS()150 public void testMaybeUpdateUsageStats_ProcStateFGS() { 151 final long elapsedTime = ZERO; 152 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); 153 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 154 155 assertProcessRecordState(elapsedTime, false, ZERO); 156 } 157 158 @Test testMaybeUpdateUsageStats_ProcStateFGS_ShortInteraction()159 public void testMaybeUpdateUsageStats_ProcStateFGS_ShortInteraction() { 160 final long elapsedTime = ZERO; 161 final long fgInteractionTime = 1000L; 162 mProcessRecord.setFgInteractionTime(fgInteractionTime); 163 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); 164 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 165 166 assertProcessRecordState(fgInteractionTime, false, ZERO); 167 } 168 169 @Test testMaybeUpdateUsageStats_ProcStateFGS_LongInteraction()170 public void testMaybeUpdateUsageStats_ProcStateFGS_LongInteraction() { 171 final long elapsedTime = 2 * SERVICE_USAGE_INTERACTION; 172 final long fgInteractionTime = 1000L; 173 mProcessRecord.setFgInteractionTime(fgInteractionTime); 174 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); 175 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 176 177 assertProcessRecordState(fgInteractionTime, true, elapsedTime); 178 } 179 180 @Test testMaybeUpdateUsageStats_ProcStateFGS_PreviousLongInteraction()181 public void testMaybeUpdateUsageStats_ProcStateFGS_PreviousLongInteraction() { 182 final long elapsedTime = 2 * SERVICE_USAGE_INTERACTION; 183 final long fgInteractionTime = 1000L; 184 mProcessRecord.setFgInteractionTime(fgInteractionTime); 185 mProcessRecord.reportedInteraction = true; 186 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); 187 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 188 189 assertProcessRecordState(fgInteractionTime, true, ZERO); 190 } 191 192 @Test testMaybeUpdateUsageStats_ProcStateFGSLocation()193 public void testMaybeUpdateUsageStats_ProcStateFGSLocation() { 194 final long elapsedTime = ZERO; 195 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); 196 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 197 198 assertProcessRecordState(elapsedTime, false, ZERO); 199 } 200 201 @Test testMaybeUpdateUsageStats_ProcStateBFGS()202 public void testMaybeUpdateUsageStats_ProcStateBFGS() { 203 final long elapsedTime = ZERO; 204 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); 205 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 206 207 assertProcessRecordState(ZERO, true, elapsedTime); 208 } 209 210 @Test testMaybeUpdateUsageStats_ProcStateImportantFG()211 public void testMaybeUpdateUsageStats_ProcStateImportantFG() { 212 final long elapsedTime = ZERO; 213 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND); 214 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 215 216 assertProcessRecordState(ZERO, true, elapsedTime); 217 } 218 219 @Test testMaybeUpdateUsageStats_ProcStateImportantFG_PreviousInteraction()220 public void testMaybeUpdateUsageStats_ProcStateImportantFG_PreviousInteraction() { 221 final long elapsedTime = ZERO; 222 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND); 223 mProcessRecord.reportedInteraction = true; 224 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 225 226 assertProcessRecordState(ZERO, true, ZERO); 227 } 228 229 @Test testMaybeUpdateUsageStats_ProcStateImportantFG_PastUsageInterval()230 public void testMaybeUpdateUsageStats_ProcStateImportantFG_PastUsageInterval() { 231 final long elapsedTime = 3 * USAGE_STATS_INTERACTION; 232 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND); 233 mProcessRecord.reportedInteraction = true; 234 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 235 236 assertProcessRecordState(ZERO, true, elapsedTime); 237 } 238 239 @Test testMaybeUpdateUsageStats_ProcStateImportantBG()240 public void testMaybeUpdateUsageStats_ProcStateImportantBG() { 241 final long elapsedTime = ZERO; 242 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND); 243 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 244 245 assertProcessRecordState(ZERO, false, ZERO); 246 } 247 248 @Test testMaybeUpdateUsageStats_ProcStateService()249 public void testMaybeUpdateUsageStats_ProcStateService() { 250 final long elapsedTime = ZERO; 251 mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_SERVICE); 252 sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime); 253 254 assertProcessRecordState(ZERO, false, ZERO); 255 } 256 assertProcessRecordState(long fgInteractionTime, boolean reportedInteraction, long interactionEventTime)257 private void assertProcessRecordState(long fgInteractionTime, boolean reportedInteraction, 258 long interactionEventTime) { 259 assertEquals("Foreground interaction time was not updated correctly.", 260 fgInteractionTime, mProcessRecord.getFgInteractionTime()); 261 assertEquals("Interaction was not updated correctly.", 262 reportedInteraction, mProcessRecord.reportedInteraction); 263 assertEquals("Interaction event time was not updated correctly.", 264 interactionEventTime, mProcessRecord.getInteractionEventTime()); 265 } 266 } 267