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

Commit f6bbfe21 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add a flicker test to verify IME snapshot when dismissing dialog" into...

Merge "Add a flicker test to verify IME snapshot when dismissing dialog" into tm-dev am: cd9af561 am: dd36f7fa

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17411126



Change-Id: Id29019e936f873b4382600f9350d188c0753ebba
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents b362b650 dd36f7fa
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.server.wm.flicker.helpers

import android.app.Instrumentation
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.FlickerComponentName
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper

class ImeEditorPopupDialogAppHelper @JvmOverloads constructor(
    instr: Instrumentation,
    private val rotation: Int,
    private val imePackageName: String = IME_PACKAGE,
    launcherName: String = ActivityOptions.EDITOR_POPUP_DIALOG_ACTIVITY_LAUNCHER_NAME,
    component: FlickerComponentName =
            ActivityOptions.EDITOR_POPUP_DIALOG_ACTIVITY_COMPONENT_NAME.toFlickerComponent()
) : ImeAppHelper(instr, launcherName, component) {
    override fun openIME(
        device: UiDevice,
        wmHelper: WindowManagerStateHelper?
    ) {
        val editText = device.wait(Until.findObject(By.text("focused editText")), FIND_TIMEOUT)

        require(editText != null) {
            "Text field not found, this usually happens when the device " +
                    "was left in an unknown state (e.g. in split screen)"
        }
        editText.click()
        waitIMEShown(device, wmHelper)
    }

    fun dismissDialog(wmHelper: WindowManagerStateHelper) {
        val dismissButton = uiDevice.wait(
                Until.findObject(By.text("Dismiss")), FIND_TIMEOUT)

        // Pressing back key to dismiss the dialog
        if (dismissButton != null) {
            dismissButton.click()
            wmHelper.waitForAppTransitionIdle()
        }
    }
}
 No newline at end of file
+135 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.server.wm.flicker.ime

import android.app.Instrumentation
import android.platform.test.annotations.Postsubmit
import android.view.Surface
import android.view.WindowManagerPolicyConstants
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.FlickerBuilderProvider
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.ImeEditorPopupDialogAppHelper
import com.android.server.wm.flicker.navBarWindowIsVisible
import com.android.server.wm.flicker.statusBarWindowIsVisible
import com.android.server.wm.flicker.traces.region.RegionSubject
import com.android.server.wm.traces.common.FlickerComponentName
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized

@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group4
class CloseImeEditorPopupDialogTest(private val testSpec: FlickerTestParameter) {
    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
    private val imeTestApp = ImeEditorPopupDialogAppHelper(instrumentation, testSpec.startRotation)

    @FlickerBuilderProvider
    fun buildFlicker(): FlickerBuilder {
        return FlickerBuilder(instrumentation).apply {
            setup {
                eachRun {
                    imeTestApp.launchViaIntent(wmHelper)
                    imeTestApp.openIME(device, wmHelper)
                }
            }
            transitions {
                imeTestApp.dismissDialog(wmHelper)
                instrumentation.uiAutomation.syncInputTransactions()
            }
            teardown {
                eachRun {
                    device.pressHome()
                    wmHelper.waitForHomeActivityVisible()
                    imeTestApp.exit()
                }
            }
        }
    }

    @Postsubmit
    @Test
    fun navBarWindowIsVisible() = testSpec.navBarWindowIsVisible()

    @Postsubmit
    @Test
    fun statusBarWindowIsVisible() = testSpec.statusBarWindowIsVisible()

    @Postsubmit
    @Test
    fun imeWindowBecameInvisible() = testSpec.imeWindowBecomesInvisible()

    @Postsubmit
    @Test
    fun imeLayerAndImeSnapshotVisibleOnScreen() {
        testSpec.assertLayers {
            this.isVisible(FlickerComponentName.IME)
                    .then()
                    .isVisible(FlickerComponentName.IME_SNAPSHOT)
                    .then()
                    .isInvisible(FlickerComponentName.IME)
        }
    }

    @Postsubmit
    @Test
    fun imeSnapshotAssociatedOnAppVisibleRegion() {
        testSpec.assertLayers {
            this.invoke("imeSnapshotAssociatedOnAppVisibleRegion") {
                val imeSnapshotLayers = it.subjects.filter {
                    subject -> subject.name.contains(
                        FlickerComponentName.IME_SNAPSHOT.toLayerName()) && subject.isVisible
                }
                if (imeSnapshotLayers.isNotEmpty()) {
                    val visibleAreas = imeSnapshotLayers.mapNotNull { imeSnapshotLayer ->
                        imeSnapshotLayer.layer?.visibleRegion }.toTypedArray()
                    val imeVisibleRegion = RegionSubject.assertThat(visibleAreas, this, timestamp)
                    val appVisibleRegion = it.visibleRegion(imeTestApp.component)
                    if (imeVisibleRegion.region.isNotEmpty) {
                        imeVisibleRegion.coversAtMost(appVisibleRegion.region)
                    }
                }
            }
        }
    }

    companion object {
        @Parameterized.Parameters(name = "{0}")
        @JvmStatic
        fun getParams(): Collection<FlickerTestParameter> {
            return FlickerTestParameterFactory.getInstance()
                    .getConfigNonRotationTests(
                            repetitions = 2,
                            supportedNavigationModes = listOf(
                                    WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
                                    WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
                            ),
                            supportedRotations = listOf(Surface.ROTATION_0)
                    )
        }
    }
}
 No newline at end of file
+11 −0
Original line number Diff line number Diff line
@@ -119,5 +119,16 @@
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity android:name=".ImeEditorPopupDialogActivity"
            android:taskAffinity="com.android.server.wm.flicker.testapp.ImeEditorPopupDialogActivity"
            android:configChanges="orientation|screenSize"
            android:theme="@style/CutoutShortEdges"
            android:label="ImeEditorPopupDialogActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>
+7 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ public class ActivityOptions {
    public static final ComponentName LAUNCH_NEW_TASK_ACTIVITY_COMPONENT_NAME =
            new ComponentName(FLICKER_APP_PACKAGE,
                    FLICKER_APP_PACKAGE + ".LaunchNewTaskActivity");

    public static final String DIALOG_THEMED_ACTIVITY = "DialogThemedActivity";
    public static final ComponentName DIALOG_THEMED_ACTIVITY_COMPONENT_NAME =
            new ComponentName(FLICKER_APP_PACKAGE,
@@ -65,4 +66,10 @@ public class ActivityOptions {
    public static final ComponentName PORTRAIT_ONLY_ACTIVITY_COMPONENT_NAME =
            new ComponentName(FLICKER_APP_PACKAGE,
                    FLICKER_APP_PACKAGE + ".PortraitOnlyActivity");

    public static final String EDITOR_POPUP_DIALOG_ACTIVITY_LAUNCHER_NAME =
            "ImeEditorPopupDialogActivity";
    public static final ComponentName EDITOR_POPUP_DIALOG_ACTIVITY_COMPONENT_NAME =
            new ComponentName(FLICKER_APP_PACKAGE,
                    FLICKER_APP_PACKAGE + ".ImeEditorPopupDialogActivity");
}
+46 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.server.wm.flicker.testapp;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.LinearLayout;

public class ImeEditorPopupDialogActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WindowManager.LayoutParams p = getWindow().getAttributes();
        p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
                .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
        getWindow().setAttributes(p);
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        setContentView(R.layout.activity_simple);

        final EditText editText = new EditText(this);
        editText.setHint("focused editText");
        final AlertDialog dialog = new AlertDialog.Builder(this)
                .setView(editText)
                .setPositiveButton("Dismiss", (d, which) -> d.dismiss())
                .create();
        dialog.show();
    }
}