Merge "Using StrictMode to detect activity leaks" into ub-launcher3-master
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index 1229a63..cd94704 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -35,6 +35,7 @@
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.TestHelpers;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.FailureWatcher;
import com.android.systemui.shared.system.QuickStepContract;
@@ -199,7 +200,7 @@
+ launcher.getNavigationModeMismatchError(),
() -> launcher.getNavigationModeMismatchError() == null,
60000 /* b/148422894 */, launcher);
-
+ AbstractLauncherUiTest.checkDetectedLeaks();
return true;
}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 5e98184..afdf378 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -37,6 +37,7 @@
import android.content.pm.PackageManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.StrictMode;
import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.By;
@@ -95,6 +96,9 @@
public static final long DEFAULT_UI_TIMEOUT = 10000;
private static final String TAG = "AbstractLauncherUiTest";
+ private static String sDetectedActivityLeak;
+ private static boolean sActivityLeakReported;
+
protected LooperExecutor mMainThreadExecutor = MAIN_EXECUTOR;
protected final UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
protected final LauncherInstrumentation mLauncher = new LauncherInstrumentation();
@@ -102,6 +106,41 @@
protected String mTargetPackage;
private int mLauncherPid;
+ static {
+ if (TestHelpers.isInLauncherProcess()) {
+ StrictMode.VmPolicy.Builder builder =
+ new StrictMode.VmPolicy.Builder()
+ .detectActivityLeaks()
+ .penaltyLog()
+ .penaltyListener(Runnable::run, violation -> {
+ // Runs in the main thread. We can't dumpheap in the main thread,
+ // so let's just mark the fact that the leak has happened.
+ if (sDetectedActivityLeak == null) {
+ sDetectedActivityLeak = violation.toString();
+ }
+ });
+ StrictMode.setVmPolicy(builder.build());
+ }
+ }
+
+ public static void checkDetectedLeaks() {
+ if (sDetectedActivityLeak != null && !sActivityLeakReported) {
+ sActivityLeakReported = true;
+
+ final UiDevice device = UiDevice.getInstance(getInstrumentation());
+ try {
+ device.executeShellCommand(
+ "am dumpheap "
+ + device.getLauncherPackageName()
+ + " "
+ + getInstrumentation().getTargetContext().getFilesDir().getPath()
+ + "/ActivityLeakHeapDump.hprof");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
protected AbstractLauncherUiTest() {
mLauncher.enableCheckEventsForSuccessfulGestures();
try {
@@ -190,6 +229,7 @@
if (mLauncherPid != 0) {
assertEquals("Launcher crashed, pid mismatch:", mLauncherPid, mLauncher.getPid());
}
+ checkDetectedLeaks();
}
protected void clearLauncherData() throws IOException, InterruptedException {
diff --git a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
index 1a68122..38f50c1 100644
--- a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
+++ b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
@@ -56,6 +56,7 @@
private void evaluateInPortrait() throws Throwable {
mTest.mDevice.setOrientationNatural();
mTest.mLauncher.setExpectedRotation(Surface.ROTATION_0);
+ AbstractLauncherUiTest.checkDetectedLeaks();
base.evaluate();
mTest.getDevice().pressHome();
}
@@ -63,6 +64,7 @@
private void evaluateInLandscape() throws Throwable {
mTest.mDevice.setOrientationLeft();
mTest.mLauncher.setExpectedRotation(Surface.ROTATION_90);
+ AbstractLauncherUiTest.checkDetectedLeaks();
base.evaluate();
mTest.getDevice().pressHome();
}
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 2ecac75..f8bbf21 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -64,6 +64,7 @@
test.waitForResumed("Launcher internal state is still Background");
// Check that we switched to home.
test.mLauncher.getWorkspace();
+ AbstractLauncherUiTest.checkDetectedLeaks();
}
// Please don't add negative test cases for methods that fail only after a long wait.