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