blob: d12d8040183a70abb36948fc2517d0204e6f8170 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.am;
import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import android.app.ActivityManager;
import android.app.usage.UsageStatsManagerInternal;
import android.content.Context;
import com.android.server.LocalServices;
import com.android.server.wm.ActivityTaskManagerService;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Test class for {@link OomAdjuster}.
*
* Build/Install/Run:
* atest FrameworksServicesTests:OomAdjusterTests
*/
public class OomAdjusterTests {
private static Context sContext;
private static ActivityManagerService sService;
private ProcessRecord mProcessRecord;
private static final long ZERO = 0L;
private static final long USAGE_STATS_INTERACTION = 2 * 60 * 60 * 1000L;
private static final long SERVICE_USAGE_INTERACTION = 30 * 60 * 1000;
@BeforeClass
public static void setUpOnce() {
sContext = getInstrumentation().getTargetContext();
// We need to run with dexmaker share class loader to make use of
// ActivityTaskManagerService from wm package.
runWithDexmakerShareClassLoader(() -> {
sService = mock(ActivityManagerService.class);
sService.mActivityTaskManager = new ActivityTaskManagerService(sContext);
sService.mActivityTaskManager.initialize(null, null, sContext.getMainLooper());
sService.mAtmInternal = sService.mActivityTaskManager.getAtmInternal();
sService.mConstants = new ActivityManagerConstants(sContext, sService,
sContext.getMainThreadHandler());
sService.mOomAdjuster = new OomAdjuster(sService, sService.mProcessList, null);
LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
LocalServices.addService(UsageStatsManagerInternal.class,
mock(UsageStatsManagerInternal.class));
sService.mUsageStatsService = LocalServices.getService(UsageStatsManagerInternal.class);
});
}
@Before
public void setUpProcess() {
// Need to run with dexmaker share class loader to mock package private class.
runWithDexmakerShareClassLoader(() -> {
mProcessRecord = spy(new ProcessRecord(sService, sContext.getApplicationInfo(),
"name", 12345));
});
// Ensure certain services and constants are defined properly
assertNotNull(sService.mUsageStatsService);
assertEquals(USAGE_STATS_INTERACTION, sService.mConstants.USAGE_STATS_INTERACTION_INTERVAL);
assertEquals(SERVICE_USAGE_INTERACTION, sService.mConstants.SERVICE_USAGE_INTERACTION_TIME);
}
@Test
public void testMaybeUpdateUsageStats_ProcStatePersistentUI() {
final long elapsedTime = ZERO;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT_UI);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(ZERO, true, elapsedTime);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateTop() {
final long elapsedTime = ZERO;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_TOP);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(ZERO, true, elapsedTime);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateTop_PreviousInteraction() {
final long elapsedTime = ZERO;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_TOP);
mProcessRecord.reportedInteraction = true;
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(ZERO, true, ZERO);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateTop_PastUsageInterval() {
final long elapsedTime = 3 * USAGE_STATS_INTERACTION;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_TOP);
mProcessRecord.reportedInteraction = true;
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(ZERO, true, elapsedTime);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateBoundTop() {
final long elapsedTime = ZERO;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_BOUND_TOP);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(ZERO, true, elapsedTime);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateFGS() {
final long elapsedTime = ZERO;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(elapsedTime, false, ZERO);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateFGS_ShortInteraction() {
final long elapsedTime = ZERO;
final long fgInteractionTime = 1000L;
mProcessRecord.setFgInteractionTime(fgInteractionTime);
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(fgInteractionTime, false, ZERO);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateFGS_LongInteraction() {
final long elapsedTime = 2 * SERVICE_USAGE_INTERACTION;
final long fgInteractionTime = 1000L;
mProcessRecord.setFgInteractionTime(fgInteractionTime);
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(fgInteractionTime, true, elapsedTime);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateFGS_PreviousLongInteraction() {
final long elapsedTime = 2 * SERVICE_USAGE_INTERACTION;
final long fgInteractionTime = 1000L;
mProcessRecord.setFgInteractionTime(fgInteractionTime);
mProcessRecord.reportedInteraction = true;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(fgInteractionTime, true, ZERO);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateFGSLocation() {
final long elapsedTime = ZERO;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(elapsedTime, false, ZERO);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateBFGS() {
final long elapsedTime = ZERO;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(ZERO, true, elapsedTime);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateImportantFG() {
final long elapsedTime = ZERO;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(ZERO, true, elapsedTime);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateImportantFG_PreviousInteraction() {
final long elapsedTime = ZERO;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
mProcessRecord.reportedInteraction = true;
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(ZERO, true, ZERO);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateImportantFG_PastUsageInterval() {
final long elapsedTime = 3 * USAGE_STATS_INTERACTION;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
mProcessRecord.reportedInteraction = true;
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(ZERO, true, elapsedTime);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateImportantBG() {
final long elapsedTime = ZERO;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(ZERO, false, ZERO);
}
@Test
public void testMaybeUpdateUsageStats_ProcStateService() {
final long elapsedTime = ZERO;
mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_SERVICE);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(ZERO, false, ZERO);
}
private void assertProcessRecordState(long fgInteractionTime, boolean reportedInteraction,
long interactionEventTime) {
assertEquals("Foreground interaction time was not updated correctly.",
fgInteractionTime, mProcessRecord.getFgInteractionTime());
assertEquals("Interaction was not updated correctly.",
reportedInteraction, mProcessRecord.reportedInteraction);
assertEquals("Interaction event time was not updated correctly.",
interactionEventTime, mProcessRecord.getInteractionEventTime());
}
}