Starting to tighten leak detector checks
This will help to detect leaks earlier, not when we have 3 activities in some cases, but when we have 2.
Adding a parameter that enables more strict detection, and using it in some places.
I'll try to convert as many places as possible to the more strict check after landing this CL.
Bug: 187761685
Test: presubmit
Flag: N/A
Change-Id: Idd5a0386005e46dad8aab222bd77c0240f23f43a
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index 57d20f8..99c79b3 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -144,7 +144,7 @@
.around(new NavigationModeSwitchRule(mLauncher))
.around(new FailureWatcher(mLauncher, viewCaptureRule::getViewCaptureData))
.around(viewCaptureRule)
- .around(new TestIsolationRule(mLauncher))
+ .around(new TestIsolationRule(mLauncher, false))
.around(setLauncherCommand);
mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 3f763c3..e837b8b 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -111,15 +111,22 @@
protected String mTargetPackage;
private int mLauncherPid;
+ /** Detects activity leaks and throws an exception if a leak is found. */
public static void checkDetectedLeaks(LauncherInstrumentation launcher) {
+ checkDetectedLeaks(launcher, false);
+ }
+
+ /** Detects activity leaks and throws an exception if a leak is found. */
+ public static void checkDetectedLeaks(LauncherInstrumentation launcher,
+ boolean requireOneActiveActivity) {
if (sActivityLeakReported) return;
// Check whether activity leak detector has found leaked activities.
- Wait.atMost(() -> getActivityLeakErrorMessage(launcher),
+ Wait.atMost(() -> getActivityLeakErrorMessage(launcher, requireOneActiveActivity),
() -> {
launcher.forceGc();
return MAIN_EXECUTOR.submit(
- () -> launcher.noLeakedActivities()).get();
+ () -> launcher.noLeakedActivities(requireOneActiveActivity)).get();
}, DEFAULT_UI_TIMEOUT, launcher);
}
@@ -127,13 +134,16 @@
return getInstrumentation().getContext().getPackageName();
}
- private static String getActivityLeakErrorMessage(LauncherInstrumentation launcher) {
+ private static String getActivityLeakErrorMessage(LauncherInstrumentation launcher,
+ boolean requireOneActiveActivity) {
sActivityLeakReported = true;
- return "Activity leak detector has found leaked activities, "
- + dumpHprofData(launcher, false) + ".";
+ return "Activity leak detector has found leaked activities, requirining 1 activity: "
+ + requireOneActiveActivity + "; "
+ + dumpHprofData(launcher, false, requireOneActiveActivity) + ".";
}
- public static String dumpHprofData(LauncherInstrumentation launcher, boolean intentionalLeak) {
+ private static String dumpHprofData(LauncherInstrumentation launcher, boolean intentionalLeak,
+ boolean requireOneActiveActivity) {
if (intentionalLeak) return "intentional leak; not generating dump";
String result;
@@ -152,7 +162,7 @@
"am dumpheap " + device.getLauncherPackageName() + " " + fileName);
}
Log.d(TAG, "Saved leak dump, the leak is still present: "
- + !launcher.noLeakedActivities());
+ + !launcher.noLeakedActivities(requireOneActiveActivity));
sDumpWasGenerated = true;
result = "saved memory dump as an artifact";
} catch (Throwable e) {
@@ -211,7 +221,7 @@
.outerRule(new PortraitLandscapeRunner(this))
.around(new FailureWatcher(mLauncher, viewCaptureRule::getViewCaptureData))
.around(viewCaptureRule)
- .around(new TestIsolationRule(mLauncher));
+ .around(new TestIsolationRule(mLauncher, true));
return TestHelpers.isInLauncherProcess()
? RuleChain.outerRule(ShellCommandRule.setDefaultLauncher()).around(inner)
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index bc53d6d..8fc7933 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -93,7 +93,7 @@
test.waitForResumed("Launcher internal state is still Background");
// Check that we switched to home.
test.mLauncher.getWorkspace();
- AbstractLauncherUiTest.checkDetectedLeaks(test.mLauncher);
+ AbstractLauncherUiTest.checkDetectedLeaks(test.mLauncher, true);
}
@After
diff --git a/tests/src/com/android/launcher3/util/rule/TestIsolationRule.java b/tests/src/com/android/launcher3/util/rule/TestIsolationRule.java
index c1f9d40..2b45902 100644
--- a/tests/src/com/android/launcher3/util/rule/TestIsolationRule.java
+++ b/tests/src/com/android/launcher3/util/rule/TestIsolationRule.java
@@ -30,10 +30,12 @@
* Isolates tests from some of the state created by the previous test.
*/
public class TestIsolationRule implements TestRule {
- final LauncherInstrumentation mLauncher;
+ private final LauncherInstrumentation mLauncher;
+ private final boolean mRequireOneActiveActivity;
- public TestIsolationRule(LauncherInstrumentation launcher) {
+ public TestIsolationRule(LauncherInstrumentation launcher, boolean requireOneActiveActivity) {
mLauncher = launcher;
+ mRequireOneActiveActivity = requireOneActiveActivity;
}
@NonNull
@@ -46,7 +48,7 @@
// Make sure that Launcher workspace looks correct.
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).pressHome();
- AbstractLauncherUiTest.checkDetectedLeaks(mLauncher);
+ AbstractLauncherUiTest.checkDetectedLeaks(mLauncher, mRequireOneActiveActivity);
}
};
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 2dec880..d7f9c78 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -704,6 +704,7 @@
/**
* Set the trackpad gesture type of the interaction.
+ *
* @param trackpadGestureType whether it's not from trackpad, two-finger, three-finger, or
* four-finger gesture.
*/
@@ -1821,8 +1822,8 @@
final MotionEvent event = isTrackpadGesture
? getTrackpadMotionEvent(
- downTime, currentTime, action, point.x, point.y, pointerCount,
- mTrackpadGestureType)
+ downTime, currentTime, action, point.x, point.y, pointerCount,
+ mTrackpadGestureType)
: getMotionEvent(downTime, currentTime, action, point.x, point.y, source);
if (action == MotionEvent.ACTION_BUTTON_PRESS
|| action == MotionEvent.ACTION_BUTTON_RELEASE) {
@@ -2072,14 +2073,16 @@
return String.join(", ", getActivities());
}
- public boolean noLeakedActivities() {
+ /** Returns whether no leaked activities are detected. */
+ public boolean noLeakedActivities(boolean requireOneActiveActivity) {
final String[] activities = getActivities();
+
for (String activity : activities) {
if (activity.contains("(destroyed)")) {
return false;
}
}
- return activities.length <= 2;
+ return activities.length <= (requireOneActiveActivity ? 1 : 2);
}
public int getActivitiesCreated() {