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

Commit 3ba68005 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Using StrictMode to detect activity leaks" into ub-launcher3-master

parents 9f62bc10 1779a382
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
@@ -64,6 +64,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.