blob: 5b85980d3f1cf2330eacdb14743434f5fd67f732 [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.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.FlakyTest;
import com.android.server.wm.ActivityTaskManagerService;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.Collections;
/**
* Build/Install/Run:
* atest FrameworksServicesTests:ProcessRecordTests
*/
@Presubmit
@FlakyTest(detail = "Promote to presubmit when shown to be stable.")
public class ProcessRecordTests {
private static Context sContext;
private static ActivityManagerService sService;
private ProcessRecord mProcessRecord;
@BeforeClass
public static void setUpOnce() throws Exception {
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();
});
}
@Before
public void setUpProcess() throws Exception {
// Need to run with dexmaker share class loader to mock package private class.
runWithDexmakerShareClassLoader(() -> {
mProcessRecord = spy(new ProcessRecord(sService, sContext.getApplicationInfo(),
"name", 12345));
doNothing().when(mProcessRecord).startAppProblemLocked();
doReturn(false).when(mProcessRecord).isSilentAnr();
doReturn(false).when(mProcessRecord).isMonitorCpuUsage();
doReturn(Collections.emptyList()).when(mProcessRecord).getLruProcessList();
});
}
/**
* This test verifies the process default status. If this doesn't pass, none of the other tests
* should be able to pass.
*/
@Test
public void testProcessDefaultAnrRelatedStatus() {
assertFalse(mProcessRecord.isNotResponding());
assertFalse(mProcessRecord.isCrashing());
assertFalse(mProcessRecord.killedByAm);
assertFalse(mProcessRecord.killed);
}
/**
* This test verifies that if the process is crashing, Anr will do nothing.
*/
@Test
public void testAnrWhenCrash() {
mProcessRecord.setCrashing(true);
assertTrue(mProcessRecord.isCrashing());
mProcessRecord.appNotResponding(null, null, null, null, false, "Test ANR when crash");
assertFalse(mProcessRecord.isNotResponding());
assertFalse(mProcessRecord.killedByAm);
assertFalse(mProcessRecord.killed);
}
/**
* This test verifies that if the process is killed by AM, Anr will do nothing.
*/
@Test
public void testAnrWhenKilledByAm() {
mProcessRecord.killedByAm = true;
mProcessRecord.appNotResponding(null, null, null, null, false,
"Test ANR when killed by AM");
assertFalse(mProcessRecord.isNotResponding());
assertFalse(mProcessRecord.isCrashing());
assertFalse(mProcessRecord.killed);
}
/**
* This test verifies that if the process is killed, Anr will do nothing.
*/
@Test
public void testAnrWhenKilled() {
mProcessRecord.killed = true;
mProcessRecord.appNotResponding(null, null, null, null, false, "Test ANR when killed");
assertFalse(mProcessRecord.isNotResponding());
assertFalse(mProcessRecord.isCrashing());
assertFalse(mProcessRecord.killedByAm);
}
/**
* This test verifies that non-silent ANR can run through successfully and the corresponding
* flags can be set correctly.
*/
@Test
public void testNonSilentAnr() {
mProcessRecord.appNotResponding(null, null, null, null, false, "Test non-silent ANR");
assertTrue(mProcessRecord.isNotResponding());
assertFalse(mProcessRecord.isCrashing());
assertFalse(mProcessRecord.killedByAm);
assertFalse(mProcessRecord.killed);
}
/**
* This test verifies that silent ANR can run through successfully and the corresponding flags
* can be set correctly.
*/
@Test
public void testSilentAnr() {
// Silent Anr will run through even without a parent process, and directly killed by AM.
doReturn(true).when(mProcessRecord).isSilentAnr();
mProcessRecord.appNotResponding(null, null, null, null, false, "Test silent ANR");
assertTrue(mProcessRecord.isNotResponding());
assertFalse(mProcessRecord.isCrashing());
assertTrue(mProcessRecord.killedByAm);
assertTrue(mProcessRecord.killed);
}
}