Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit daa553c7 authored by Vadim Tryshev's avatar Vadim Tryshev Committed by Android (Google) Code Review
Browse files

Merge "Starting to tighten leak detector checks" into main

parents 62656d06 d8c049f2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -144,7 +144,7 @@ public class FallbackRecentsTest {
                .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(
+18 −8
Original line number Diff line number Diff line
@@ -111,15 +111,22 @@ public abstract class AbstractLauncherUiTest {
    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 @@ public abstract class AbstractLauncherUiTest {
        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 @@ public abstract class AbstractLauncherUiTest {
                            "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 @@ public abstract class AbstractLauncherUiTest {
                .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)
+1 −1
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest {
        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
+5 −3
Original line number Diff line number Diff line
@@ -30,10 +30,12 @@ import org.junit.runners.model.Statement;
 * 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 @@ public class TestIsolationRule implements TestRule {
                // Make sure that Launcher workspace looks correct.

                UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).pressHome();
                AbstractLauncherUiTest.checkDetectedLeaks(mLauncher);
                AbstractLauncherUiTest.checkDetectedLeaks(mLauncher, mRequireOneActiveActivity);
            }
        };
    }
+7 −4
Original line number Diff line number Diff line
@@ -704,6 +704,7 @@ public final class LauncherInstrumentation {

    /**
     * Set the trackpad gesture type of the interaction.
     *
     * @param trackpadGestureType whether it's not from trackpad, two-finger, three-finger, or
     *                            four-finger gesture.
     */
@@ -2072,14 +2073,16 @@ public final class LauncherInstrumentation {
        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() {