• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.ApplicationInfo;
34 import android.content.pm.PackageManagerInternal;
35 
36 import com.android.server.LocalServices;
37 import com.android.server.wm.ActivityTaskManagerService;
38 
39 import org.junit.AfterClass;
40 import org.junit.Before;
41 import org.junit.BeforeClass;
42 import org.junit.Test;
43 
44 import java.lang.reflect.Field;
45 import java.lang.reflect.Modifier;
46 
47 /**
48  * Test class for {@link OomAdjuster}.
49  *
50  * Build/Install/Run:
51  *  atest FrameworksServicesTests:OomAdjusterTests
52  */
53 public class OomAdjusterTests {
54     private static Context sContext;
55     private static ActivityManagerService sService;
56     private static PackageManagerInternal sPackageManagerInternal;
57 
58     private ProcessRecord mProcessRecord;
59 
60     private static final long ZERO = 0L;
61     private static final long USAGE_STATS_INTERACTION = 10 * 60 * 1000L;
62     private static final long SERVICE_USAGE_INTERACTION = 60 * 1000;
63 
64     @SuppressWarnings("GuardedBy")
65     @BeforeClass
setUpOnce()66     public static void setUpOnce() {
67         sContext = getInstrumentation().getTargetContext();
68 
69         sPackageManagerInternal = mock(PackageManagerInternal.class);
70         doReturn(new ComponentName("", "")).when(sPackageManagerInternal)
71                 .getSystemUiServiceComponent();
72         LocalServices.addService(PackageManagerInternal.class, sPackageManagerInternal);
73 
74         // We need to run with dexmaker share class loader to make use of
75         // ActivityTaskManagerService from wm package.
76         runWithDexmakerShareClassLoader(() -> {
77             sService = mock(ActivityManagerService.class);
78             sService.mActivityTaskManager = new ActivityTaskManagerService(sContext);
79             sService.mActivityTaskManager.initialize(null, null, sContext.getMainLooper());
80             sService.mAtmInternal = sService.mActivityTaskManager.getAtmInternal();
81 
82             setFieldValue(ActivityManagerService.class, sService, "mProcLock",
83                     new ActivityManagerProcLock());
84             sService.mConstants = new ActivityManagerConstants(sContext, sService,
85                     sContext.getMainThreadHandler());
86             final AppProfiler profiler = mock(AppProfiler.class);
87             setFieldValue(AppProfiler.class, profiler, "mProfilerLock", new Object());
88             setFieldValue(ActivityManagerService.class, sService, "mAppProfiler", profiler);
89             final OomAdjuster.Injector injector = new OomAdjuster.Injector(){
90                 @Override
91                 boolean isChangeEnabled(int changeId, ApplicationInfo app,
92                         boolean defaultValue) {
93                     return true;
94                 }
95             };
96             sService.mProcessStateController = new ProcessStateController.Builder(sService,
97                     sService.mProcessList, null)
98                     .setOomAdjusterInjector(injector)
99                     .build();
100             sService.mOomAdjuster = sService.mProcessStateController.getOomAdjuster();
101             LocalServices.addService(UsageStatsManagerInternal.class,
102                     mock(UsageStatsManagerInternal.class));
103             sService.mUsageStatsService = LocalServices.getService(UsageStatsManagerInternal.class);
104         });
105     }
106 
setFieldValue(Class clazz, Object obj, String fieldName, T val)107     private static <T> void setFieldValue(Class clazz, Object obj, String fieldName, T val) {
108         try {
109             Field field = clazz.getDeclaredField(fieldName);
110             field.setAccessible(true);
111             Field mfield = Field.class.getDeclaredField("accessFlags");
112             mfield.setAccessible(true);
113             mfield.setInt(field, mfield.getInt(field) & ~(Modifier.FINAL | Modifier.PRIVATE));
114             field.set(obj, val);
115         } catch (NoSuchFieldException | IllegalAccessException e) {
116         }
117     }
118 
119     @AfterClass
tearDownOnce()120     public static void tearDownOnce() {
121         LocalServices.removeServiceForTest(PackageManagerInternal.class);
122         LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
123     }
124 
125     @Before
setUpProcess()126     public void setUpProcess() {
127         // Need to run with dexmaker share class loader to mock package private class.
128         runWithDexmakerShareClassLoader(() -> {
129             mProcessRecord = spy(new ProcessRecord(sService, sContext.getApplicationInfo(),
130                     "name", 12345));
131         });
132 
133         // Ensure certain services and constants are defined properly
134         assertNotNull(sService.mUsageStatsService);
135         assertEquals(USAGE_STATS_INTERACTION,
136                 sService.mConstants.USAGE_STATS_INTERACTION_INTERVAL_POST_S);
137         assertEquals(SERVICE_USAGE_INTERACTION,
138                 sService.mConstants.SERVICE_USAGE_INTERACTION_TIME_POST_S);
139     }
140 
141     @Test
testMaybeUpdateUsageStats_ProcStatePersistentUI()142     public void testMaybeUpdateUsageStats_ProcStatePersistentUI() {
143         final long elapsedTime = ZERO;
144         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
145         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
146 
147         assertProcessRecordState(ZERO, true, elapsedTime);
148     }
149 
150     @Test
testMaybeUpdateUsageStats_ProcStateTop()151     public void testMaybeUpdateUsageStats_ProcStateTop() {
152         final long elapsedTime = ZERO;
153         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_TOP);
154         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
155 
156         assertProcessRecordState(ZERO, true, elapsedTime);
157     }
158 
159     @Test
testMaybeUpdateUsageStats_ProcStateTop_PreviousInteraction()160     public void testMaybeUpdateUsageStats_ProcStateTop_PreviousInteraction() {
161         final long elapsedTime = ZERO;
162         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_TOP);
163         mProcessRecord.mState.setReportedInteraction(true);
164         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
165 
166         assertProcessRecordState(ZERO, true, ZERO);
167     }
168 
169     @Test
testMaybeUpdateUsageStats_ProcStateTop_PastUsageInterval()170     public void testMaybeUpdateUsageStats_ProcStateTop_PastUsageInterval() {
171         final long elapsedTime = 3 * USAGE_STATS_INTERACTION;
172         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_TOP);
173         mProcessRecord.mState.setReportedInteraction(true);
174         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
175 
176         assertProcessRecordState(ZERO, true, elapsedTime);
177     }
178 
179     @Test
testMaybeUpdateUsageStats_ProcStateBoundTop()180     public void testMaybeUpdateUsageStats_ProcStateBoundTop() {
181         final long elapsedTime = ZERO;
182         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_BOUND_TOP);
183         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
184 
185         assertProcessRecordState(ZERO, true, elapsedTime);
186     }
187 
188     @Test
testMaybeUpdateUsageStats_ProcStateFGS()189     public void testMaybeUpdateUsageStats_ProcStateFGS() {
190         final long elapsedTime = ZERO;
191         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
192         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
193 
194         assertProcessRecordState(elapsedTime, false, ZERO);
195     }
196 
197     @Test
testMaybeUpdateUsageStats_ProcStateFGS_ShortInteraction()198     public void testMaybeUpdateUsageStats_ProcStateFGS_ShortInteraction() {
199         final long elapsedTime = ZERO;
200         final long fgInteractionTime = 1000L;
201         mProcessRecord.mState.setFgInteractionTime(fgInteractionTime);
202         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
203         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
204 
205         assertProcessRecordState(fgInteractionTime, false, ZERO);
206     }
207 
208     @Test
testMaybeUpdateUsageStats_ProcStateFGS_LongInteraction()209     public void testMaybeUpdateUsageStats_ProcStateFGS_LongInteraction() {
210         final long elapsedTime = 2 * SERVICE_USAGE_INTERACTION;
211         final long fgInteractionTime = 1000L;
212         mProcessRecord.mState.setFgInteractionTime(fgInteractionTime);
213         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
214         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
215 
216         assertProcessRecordState(fgInteractionTime, true, elapsedTime);
217     }
218 
219     @Test
testMaybeUpdateUsageStats_ProcStateFGS_PreviousLongInteraction()220     public void testMaybeUpdateUsageStats_ProcStateFGS_PreviousLongInteraction() {
221         final long elapsedTime = 2 * SERVICE_USAGE_INTERACTION;
222         final long fgInteractionTime = 1000L;
223         mProcessRecord.mState.setFgInteractionTime(fgInteractionTime);
224         mProcessRecord.mState.setReportedInteraction(true);
225         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
226         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
227 
228         assertProcessRecordState(fgInteractionTime, true, ZERO);
229     }
230 
231     @Test
testMaybeUpdateUsageStats_ProcStateFGSLocation()232     public void testMaybeUpdateUsageStats_ProcStateFGSLocation() {
233         final long elapsedTime = ZERO;
234         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
235         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
236 
237         assertProcessRecordState(elapsedTime, false, ZERO);
238     }
239 
240     @Test
testMaybeUpdateUsageStats_ProcStateBFGS()241     public void testMaybeUpdateUsageStats_ProcStateBFGS() {
242         final long elapsedTime = ZERO;
243         mProcessRecord.mState.setCurProcState(
244                 ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
245         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
246 
247         assertProcessRecordState(ZERO, true, elapsedTime);
248     }
249 
250     @Test
testMaybeUpdateUsageStats_ProcStateImportantFG()251     public void testMaybeUpdateUsageStats_ProcStateImportantFG() {
252         final long elapsedTime = ZERO;
253         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
254         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
255 
256         assertProcessRecordState(ZERO, true, elapsedTime);
257     }
258 
259     @Test
testMaybeUpdateUsageStats_ProcStateImportantFG_PreviousInteraction()260     public void testMaybeUpdateUsageStats_ProcStateImportantFG_PreviousInteraction() {
261         final long elapsedTime = ZERO;
262         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
263         mProcessRecord.mState.setReportedInteraction(true);
264         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
265 
266         assertProcessRecordState(ZERO, true, ZERO);
267     }
268 
269     @Test
testMaybeUpdateUsageStats_ProcStateImportantFG_PastUsageInterval()270     public void testMaybeUpdateUsageStats_ProcStateImportantFG_PastUsageInterval() {
271         final long elapsedTime = 3 * USAGE_STATS_INTERACTION;
272         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
273         mProcessRecord.mState.setReportedInteraction(true);
274         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
275 
276         assertProcessRecordState(ZERO, true, elapsedTime);
277     }
278 
279     @Test
testMaybeUpdateUsageStats_ProcStateImportantBG()280     public void testMaybeUpdateUsageStats_ProcStateImportantBG() {
281         final long elapsedTime = ZERO;
282         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
283         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
284 
285         assertProcessRecordState(ZERO, false, ZERO);
286     }
287 
288     @Test
testMaybeUpdateUsageStats_ProcStateService()289     public void testMaybeUpdateUsageStats_ProcStateService() {
290         final long elapsedTime = ZERO;
291         mProcessRecord.mState.setCurProcState(ActivityManager.PROCESS_STATE_SERVICE);
292         sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
293 
294         assertProcessRecordState(ZERO, false, ZERO);
295     }
296 
assertProcessRecordState(long fgInteractionTime, boolean reportedInteraction, long interactionEventTime)297     private void assertProcessRecordState(long fgInteractionTime, boolean reportedInteraction,
298             long interactionEventTime) {
299         assertEquals("Foreground interaction time was not updated correctly.",
300                 fgInteractionTime, mProcessRecord.mState.getFgInteractionTime());
301         assertEquals("Interaction was not updated correctly.",
302                 reportedInteraction, mProcessRecord.mState.hasReportedInteraction());
303         assertEquals("Interaction event time was not updated correctly.",
304                 interactionEventTime, mProcessRecord.mState.getInteractionEventTime());
305     }
306 }
307