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

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

Merge "Make @QuickstepOnOff and @PortraitLandscape available to all UI tests."...

Merge "Make @QuickstepOnOff and @PortraitLandscape available to all UI tests." into ub-launcher3-master
parents 69c9e433 6ffb2c8f
Loading
Loading
Loading
Loading
+31 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.android.quickstep;

import com.android.launcher3.ui.AbstractLauncherUiTest;

import org.junit.Rule;
import org.junit.rules.TestRule;

/**
 * Base class for all instrumentation tests that deal with Quickstep.
 */
public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest {
    @Rule
    public TestRule mQuickstepOnOffExecutor =
            new QuickStepOnOffRule(mMainThreadExecutor, mLauncher);
}
+89 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.android.quickstep;

import androidx.test.InstrumentationRegistry;

import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.ui.TestHelpers;

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.Executor;

/**
 * Test rule that allows executing a test with Quickstep on and then Quickstep off.
 * The test should be annotated with @QuickstepOnOff.
 */
public class QuickStepOnOffRule implements TestRule {
    // Annotation for tests that need to be run with quickstep enabled and disabled.
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface QuickstepOnOff {
    }

    private final Executor mMainThreadExecutor;
    private final LauncherInstrumentation mLauncher;

    public QuickStepOnOffRule(Executor mainThreadExecutor, LauncherInstrumentation launcher) {
        mLauncher = launcher;
        this.mMainThreadExecutor = mainThreadExecutor;
    }

    @Override
    public Statement apply(Statement base, Description description) {
        if (TestHelpers.isInLauncherProcess() &&
                description.getAnnotation(QuickstepOnOff.class) != null) {
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    try {
                        evaluateWithQuickstepOn();
                        evaluateWithQuickstepOff();
                    } finally {
                        overrideSwipeUpEnabled(null);
                    }
                }

                private void evaluateWithQuickstepOff() throws Throwable {
                    overrideSwipeUpEnabled(false);
                    base.evaluate();
                }

                private void evaluateWithQuickstepOn() throws Throwable {
                    overrideSwipeUpEnabled(true);
                    base.evaluate();
                }

                private void overrideSwipeUpEnabled(Boolean swipeUpEnabledOverride) {
                    mLauncher.overrideSwipeUpEnabled(swipeUpEnabledOverride);
                    mMainThreadExecutor.execute(() -> OverviewInteractionState.INSTANCE.get(
                            InstrumentationRegistry.getInstrumentation().getTargetContext()).
                            notifySwipeUpSettingChanged(mLauncher.isSwipeUpEnabled()));
                }
            };
        } else {
            return base;
        }
    }
}
+60 −13
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemClock;
import android.util.Log;
import android.util.Log;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.Surface;


import androidx.test.InstrumentationRegistry;
import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.By;
@@ -59,7 +60,13 @@ import com.android.launcher3.util.rule.LauncherActivityRule;
import org.junit.After;
import org.junit.After;
import org.junit.Before;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.runners.model.Statement;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.Callable;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit;
@@ -83,22 +90,66 @@ public abstract class AbstractLauncherUiTest {
    protected final LauncherInstrumentation mLauncher;
    protected final LauncherInstrumentation mLauncher;
    protected Context mTargetContext;
    protected Context mTargetContext;
    protected String mTargetPackage;
    protected String mTargetPackage;
    protected final boolean mIsInLauncherProcess;


    private static final String TAG = "AbstractLauncherUiTest";
    private static final String TAG = "AbstractLauncherUiTest";


    protected AbstractLauncherUiTest() {
    protected AbstractLauncherUiTest() {
        final Instrumentation instrumentation = getInstrumentation();
        final Instrumentation instrumentation =TestHelpers.getInstrumentation();
        mDevice = UiDevice.getInstance(instrumentation);
        mDevice = UiDevice.getInstance(instrumentation);
        try {
            mDevice.setOrientationNatural();
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
        mLauncher = new LauncherInstrumentation(instrumentation);
        mLauncher = new LauncherInstrumentation(instrumentation);

        mIsInLauncherProcess = instrumentation.getTargetContext().getPackageName().equals(
                mDevice.getLauncherPackageName());
    }
    }


    @Rule
    @Rule
    public LauncherActivityRule mActivityMonitor = new LauncherActivityRule();
    public LauncherActivityRule mActivityMonitor = new LauncherActivityRule();


    // Annotation for tests that need to be run in portrait and landscape modes.
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    protected @interface PortraitLandscape {
    }

    @Rule
    public TestRule mPortraitLandscapeExecutor =
            (base, description) -> false && description.getAnnotation(PortraitLandscape.class)
                    != null ? new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    try {
                        // Create launcher activity if necessary and bring it to the front.
                        mDevice.pressHome();
                        waitForLauncherCondition(launcher -> launcher != null);

                        executeOnLauncher(launcher ->
                                launcher.getRotationHelper().forceAllowRotationForTesting(true));

                        evaluateInPortrait();
                        evaluateInLandscape();
                    } finally {
                        mDevice.setOrientationNatural();
                        executeOnLauncher(launcher ->
                                launcher.getRotationHelper().forceAllowRotationForTesting(false));
                        mLauncher.setExpectedRotation(Surface.ROTATION_0);
                    }
                }

                private void evaluateInPortrait() throws Throwable {
                    mDevice.setOrientationNatural();
                    mLauncher.setExpectedRotation(Surface.ROTATION_0);
                    base.evaluate();
                }

                private void evaluateInLandscape() throws Throwable {
                    mDevice.setOrientationLeft();
                    mLauncher.setExpectedRotation(Surface.ROTATION_90);
                    base.evaluate();
                }
            } : base;

    @Before
    @Before
    public void setUp() throws Exception {
    public void setUp() throws Exception {
        mTargetContext = InstrumentationRegistry.getTargetContext();
        mTargetContext = InstrumentationRegistry.getTargetContext();
@@ -119,10 +170,6 @@ public abstract class AbstractLauncherUiTest {
        }
        }
    }
    }


    protected Instrumentation getInstrumentation() {
        return InstrumentationRegistry.getInstrumentation();
    }

    /**
    /**
     * Opens all apps and returns the recycler view
     * Opens all apps and returns the recycler view
     */
     */
@@ -231,7 +278,7 @@ public abstract class AbstractLauncherUiTest {
    protected void sendPointer(int action, Point point) {
    protected void sendPointer(int action, Point point) {
        MotionEvent event = MotionEvent.obtain(SystemClock.uptimeMillis(),
        MotionEvent event = MotionEvent.obtain(SystemClock.uptimeMillis(),
                SystemClock.uptimeMillis(), action, point.x, point.y, 0);
                SystemClock.uptimeMillis(), action, point.x, point.y, 0);
        getInstrumentation().sendPointerSync(event);
        TestHelpers.getInstrumentation().sendPointerSync(event);
        event.recycle();
        event.recycle();
    }
    }


@@ -271,7 +318,7 @@ public abstract class AbstractLauncherUiTest {
    }
    }


    protected <T> T getFromLauncher(Function<Launcher, T> f) {
    protected <T> T getFromLauncher(Function<Launcher, T> f) {
        if (!mIsInLauncherProcess) return null;
        if (!TestHelpers.isInLauncherProcess()) return null;
        return getOnUiThread(() -> f.apply(mActivityMonitor.getActivity()));
        return getOnUiThread(() -> f.apply(mActivityMonitor.getActivity()));
    }
    }


@@ -298,7 +345,7 @@ public abstract class AbstractLauncherUiTest {
    // flakiness.
    // flakiness.
    protected boolean waitForLauncherCondition(
    protected boolean waitForLauncherCondition(
            Function<Launcher, Boolean> condition, long timeout) {
            Function<Launcher, Boolean> condition, long timeout) {
        if (!mIsInLauncherProcess) return true;
        if (!TestHelpers.isInLauncherProcess()) return true;
        return Wait.atMost(() -> getFromLauncher(condition), timeout);
        return Wait.atMost(() -> getFromLauncher(condition), timeout);
    }
    }


@@ -311,7 +358,7 @@ public abstract class AbstractLauncherUiTest {
                getOnUiThread(new Callable<LauncherAppWidgetProviderInfo>() {
                getOnUiThread(new Callable<LauncherAppWidgetProviderInfo>() {
            @Override
            @Override
            public LauncherAppWidgetProviderInfo call() throws Exception {
            public LauncherAppWidgetProviderInfo call() throws Exception {
                ComponentName cn = new ComponentName(getInstrumentation().getContext(),
                ComponentName cn = new ComponentName(TestHelpers.getInstrumentation().getContext(),
                        hasConfigureScreen ? AppWidgetWithConfig.class : AppWidgetNoConfig.class);
                        hasConfigureScreen ? AppWidgetWithConfig.class : AppWidgetNoConfig.class);
                Log.d(TAG, "findWidgetProvider componentName=" + cn.flattenToString());
                Log.d(TAG, "findWidgetProvider componentName=" + cn.flattenToString());
                return AppWidgetManagerCompat.getInstance(mTargetContext)
                return AppWidgetManagerCompat.getInstance(mTargetContext)
+36 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.android.launcher3.ui;

import android.app.Instrumentation;

import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;

public class TestHelpers {
    private static final boolean IS_IN_LAUNCHER_PROCESS =
            getInstrumentation().getTargetContext().getPackageName().equals(
                    UiDevice.getInstance(getInstrumentation()).getLauncherPackageName());

    public static Instrumentation getInstrumentation() {
        return InstrumentationRegistry.getInstrumentation();
    }

    public static boolean isInLauncherProcess() {
        return IS_IN_LAUNCHER_PROCESS;
    }
}
+2 −1
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.Workspace;
import com.android.launcher3.Workspace;
import com.android.launcher3.testcomponent.WidgetConfigActivity;
import com.android.launcher3.testcomponent.WidgetConfigActivity;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TestHelpers;
import com.android.launcher3.util.Condition;
import com.android.launcher3.util.Condition;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.util.rule.ShellCommandRule;
@@ -131,7 +132,7 @@ public class AddConfigWidgetTest extends AbstractLauncherUiTest {


    private void setResult(boolean success) {
    private void setResult(boolean success) {


        getInstrumentation().getTargetContext().sendBroadcast(
        TestHelpers.getInstrumentation().getTargetContext().sendBroadcast(
                WidgetConfigActivity.getCommandIntent(WidgetConfigActivity.class,
                WidgetConfigActivity.getCommandIntent(WidgetConfigActivity.class,
                        success ? "clickOK" : "clickCancel"));
                        success ? "clickOK" : "clickCancel"));
    }
    }