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

Commit 1779a382 authored by vadimt's avatar vadimt
Browse files

Using StrictMode to detect activity leaks

Change-Id: I615f641897d57be0cd31be944796c6931ef9ab00
parent d71c3b18
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import androidx.test.uiautomator.UiDevice;

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 @@ public class NavigationModeSwitchRule implements TestRule {
                        + launcher.getNavigationModeMismatchError(),
                () -> launcher.getNavigationModeMismatchError() == null,
                60000 /* b/148422894 */, launcher);

        AbstractLauncherUiTest.checkDetectedLeaks();
        return true;
    }

+40 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.content.pm.LauncherApps;
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 abstract class AbstractLauncherUiTest {
    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 @@ public abstract class AbstractLauncherUiTest {
    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 @@ public abstract class AbstractLauncherUiTest {
        if (mLauncherPid != 0) {
            assertEquals("Launcher crashed, pid mismatch:", mLauncherPid, mLauncher.getPid());
        }
        checkDetectedLeaks();
    }

    protected void clearLauncherData() throws IOException, InterruptedException {
+2 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ class PortraitLandscapeRunner implements TestRule {
            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 @@ class PortraitLandscapeRunner implements TestRule {
            private void evaluateInLandscape() throws Throwable {
                mTest.mDevice.setOrientationLeft();
                mTest.mLauncher.setExpectedRotation(Surface.ROTATION_90);
                AbstractLauncherUiTest.checkDetectedLeaks();
                base.evaluate();
                mTest.getDevice().pressHome();
            }
+1 −0
Original line number Diff line number Diff line
@@ -65,6 +65,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();
    }

    // Please don't add negative test cases for methods that fail only after a long wait.