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

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

Merge "Adding tests for fallback recents when a 3rd party launcher is...

Merge "Adding tests for fallback recents when a 3rd party launcher is installed" into ub-launcher3-master
parents 2d571363 4ed58d6c
Loading
Loading
Loading
Loading
+126 −0
Original line number 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 static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;

import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
import static com.android.launcher3.tapl.TestHelpers.getHomeIntentInPackage;
import static com.android.launcher3.tapl.TestHelpers.getLauncherInMyProcess;
import static com.android.launcher3.util.rule.ShellCommandRule.disableHeadsUpNotification;
import static com.android.launcher3.util.rule.ShellCommandRule.getLauncherCommand;
import static com.android.quickstep.QuickStepOnOffRule.Mode.OFF;

import static org.junit.Assert.assertTrue;

import static androidx.test.InstrumentationRegistry.getInstrumentation;

import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;

import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.testcomponent.TestCommandReceiver;
import com.android.quickstep.QuickStepOnOffRule.QuickstepOnOff;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.junit.runners.model.Statement;

import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;

@LargeTest
@RunWith(AndroidJUnit4.class)
/**
 * TODO: Fix fallback when quickstep is enabled
 */
public class FallbackRecentsTest {

    private final UiDevice mDevice;
    private final LauncherInstrumentation mLauncher;
    private final ActivityInfo mOtherLauncherActivity;

    @Rule public final TestRule mDisableHeadsUpNotification = disableHeadsUpNotification();
    @Rule public final TestRule mQuickstepOnOffExecutor;

    @Rule public final TestRule mSetLauncherCommand;

    public FallbackRecentsTest() {
        Instrumentation instrumentation = getInstrumentation();
        Context context = instrumentation.getContext();
        mDevice = UiDevice.getInstance(instrumentation);
        mLauncher = new LauncherInstrumentation(instrumentation);

        mQuickstepOnOffExecutor = new QuickStepOnOffRule(new MainThreadExecutor(), mLauncher);
        mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
                getHomeIntentInPackage(context),
                MATCH_DISABLED_COMPONENTS).get(0).activityInfo;

        mSetLauncherCommand = (base, desc) -> new Statement() {
            @Override
            public void evaluate() throws Throwable {
                TestCommandReceiver.callCommand(TestCommandReceiver.ENABLE_TEST_LAUNCHER);
                UiDevice.getInstance(getInstrumentation()).executeShellCommand(
                        getLauncherCommand(mOtherLauncherActivity));
                try {
                    base.evaluate();
                } finally {
                    TestCommandReceiver.callCommand(TestCommandReceiver.DISABLE_TEST_LAUNCHER);
                    UiDevice.getInstance(getInstrumentation()).executeShellCommand(
                            getLauncherCommand(getLauncherInMyProcess()));
                }
            }
        };
    }

    @QuickstepOnOff(mode = OFF)
    @Test
    public void goToOverviewFromHome() {
        mDevice.pressHome();
        assertTrue("Fallback Launcher not visible", mDevice.wait(Until.hasObject(By.pkg(
                mOtherLauncherActivity.packageName)), WAIT_TIME_MS));

        mLauncher.getBackground().switchToOverview();
    }

    @QuickstepOnOff(mode = OFF)
    @Test
    public void goToOverviewFromApp() {
        startAppFast("com.android.settings");

        mLauncher.getBackground().switchToOverview();
    }

    private void startAppFast(String packageName) {
        final Instrumentation instrumentation = getInstrumentation();
        final Intent intent = instrumentation.getContext().getPackageManager().
                getLaunchIntentForPackage(packageName);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        instrumentation.getTargetContext().startActivity(intent);
        assertTrue(packageName + " didn't start",
                mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), WAIT_TIME_MS));
    }

}
+18 −3
Original line number Diff line number Diff line
@@ -16,10 +16,14 @@

package com.android.quickstep;

import static com.android.quickstep.QuickStepOnOffRule.Mode.BOTH;
import static com.android.quickstep.QuickStepOnOffRule.Mode.OFF;
import static com.android.quickstep.QuickStepOnOffRule.Mode.ON;

import androidx.test.InstrumentationRegistry;

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

import org.junit.rules.TestRule;
import org.junit.runner.Description;
@@ -36,10 +40,16 @@ import java.util.concurrent.Executor;
 * The test should be annotated with @QuickstepOnOff.
 */
public class QuickStepOnOffRule implements TestRule {

    public enum Mode {
        ON, OFF, BOTH
    }

    // Annotation for tests that need to be run with quickstep enabled and disabled.
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface QuickstepOnOff {
        Mode mode() default BOTH;
    }

    private final Executor mMainThreadExecutor;
@@ -54,12 +64,17 @@ public class QuickStepOnOffRule implements TestRule {
    public Statement apply(Statement base, Description description) {
        if (TestHelpers.isInLauncherProcess() &&
                description.getAnnotation(QuickstepOnOff.class) != null) {
            Mode mode = description.getAnnotation(QuickstepOnOff.class).mode();
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    try {
                        if (mode == ON || mode == BOTH) {
                            evaluateWithQuickstepOn();
                        }
                        if (mode == OFF || mode == BOTH) {
                            evaluateWithQuickstepOff();
                        }
                    } finally {
                        overrideSwipeUpEnabled(null);
                    }
+28 −0
Original line number Diff line number Diff line
@@ -67,5 +67,33 @@
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

        <provider
            android:name="com.android.launcher3.testcomponent.TestCommandReceiver"
            android:authorities="${packageName}.commands"
            android:exported="true" />

        <activity
            android:name="com.android.launcher3.testcomponent.TestLauncherActivity"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:label="Test launcher"
            android:stateNotNeeded="true"
            android:theme="@android:style/Theme.DeviceDefault.Light"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="unspecified"
            android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
            android:resizeableActivity="true"
            android:taskAffinity=""
            android:process=":testLauncherProcess"
            android:enabled="false">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
                <category android:name="android.intent.category.LAUNCHER_APP" />
            </intent-filter>
        </activity>
    </application>
</manifest>
+96 −0
Original line number 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.testcomponent;

import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.content.pm.PackageManager.DONT_KILL_APP;

import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;

import androidx.test.InstrumentationRegistry;

/**
 * Content provider to receive commands from tests
 */
public class TestCommandReceiver extends ContentProvider {

    public static final String ENABLE_TEST_LAUNCHER = "enable-test-launcher";
    public static final String DISABLE_TEST_LAUNCHER = "disable-test-launcher";

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException("unimplemented mock method");
    }

    @Override
    public String getType(Uri uri) {
        throw new UnsupportedOperationException("unimplemented mock method");
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        throw new UnsupportedOperationException("unimplemented mock method");
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
            String sortOrder) {
        throw new UnsupportedOperationException("unimplemented mock method");
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException("unimplemented mock method");
    }

    @Override
    public Bundle call(String method, String arg, Bundle extras) {
        switch (method) {
            case ENABLE_TEST_LAUNCHER: {
                getContext().getPackageManager().setComponentEnabledSetting(
                        new ComponentName(getContext(), TestLauncherActivity.class),
                        COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP);
                return null;
            }
            case DISABLE_TEST_LAUNCHER: {
                getContext().getPackageManager().setComponentEnabledSetting(
                        new ComponentName(getContext(), TestLauncherActivity.class),
                        COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP);
                return null;
            }

        }
        return super.call(method, arg, extras);
    }

    public static Bundle callCommand(String command) {
        Instrumentation inst = InstrumentationRegistry.getInstrumentation();
        Uri uri = Uri.parse("content://" + inst.getContext().getPackageName() + ".commands");
        return inst.getTargetContext().getContentResolver().call(uri, command, null, null);
    }
}
+34 −0
Original line number Diff line number Diff line
@@ -13,24 +13,22 @@
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.android.launcher3.testcomponent;

package com.android.launcher3.ui;
import static android.content.Intent.ACTION_MAIN;
import static android.content.Intent.CATEGORY_LAUNCHER;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;

import android.app.Instrumentation;
import android.app.LauncherActivity;
import android.content.Intent;

import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
public class TestLauncherActivity extends LauncherActivity {

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;
    @Override
    protected Intent getTargetIntent() {
        return new Intent(ACTION_MAIN, null)
                .addCategory(CATEGORY_LAUNCHER)
                .addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
    }
}
Loading