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

Commit 29c3345f authored by Charles Chen's avatar Charles Chen Committed by Android (Google) Code Review
Browse files

Merge "Introduce RecordTraceWithTransitionRule" into main

parents 6a92a9f9 403424b5
Loading
Loading
Loading
Loading
+51 −46
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ import com.android.server.wm.flicker.assertNavBarPosition
import com.android.server.wm.flicker.assertStatusBarLayerPosition
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.wm.shell.Flags
import org.junit.BeforeClass
import org.junit.ClassRule
import org.junit.FixMethodOrder
import org.junit.Rule
import org.junit.Test
@@ -101,29 +101,28 @@ class EnterBubbleViaBubbleMenuTest {
         */
        private lateinit var traceDataReader: Reader

        @BeforeClass
        @JvmStatic
        fun recordTraceWithTransition() {
            setUpBeforeTransition(instrumentation, wmHelper)

            // Run transition while recording trace.
            traceDataReader = runTransitionWithTrace {
                launchBubbleViaBubbleMenu(testApp, tapl, wmHelper)
            }

            // Finish the test app.
            testApp.exit(wmHelper)
        }
        @ClassRule
        @JvmField
        val recordTraceWithTransitionRule = RecordTraceWithTransitionRule(
            setUpBeforeTransition = { setUpBeforeTransition(instrumentation, wmHelper) },
            transition = { launchBubbleViaBubbleMenu(testApp, tapl, wmHelper) },
            tearDownAfterTransition = { testApp.exit(wmHelper) }
        )
    }

    @get:Rule
    val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()

    /**
     * The reader to read trace from.
     */
    private val traceDataReader = recordTraceWithTransitionRule.reader

    /**
     * The WindowManager trace subject, which is equivalent to the data shown in
     * `Window Manager` tab in go/winscope.
     */
    private val wmTraceSubject: WindowManagerTraceSubject = WindowManagerTraceSubject(
    private val wmTraceSubject = WindowManagerTraceSubject(
        traceDataReader.readWmTrace() ?: error("Failed to read WM trace")
    )

@@ -131,7 +130,7 @@ class EnterBubbleViaBubbleMenuTest {
     * The Layer trace subject, which is equivalent to the data shown in
     * `Surface Flinger` tab in go/winscope.
     */
    private val layersTraceSubject: LayersTraceSubject = LayersTraceSubject(
    private val layersTraceSubject = LayersTraceSubject(
        traceDataReader.readLayersTrace() ?: error("Failed to read layer trace")
    )

@@ -155,6 +154,12 @@ class EnterBubbleViaBubbleMenuTest {
     */
    private val layerTraceEntrySubjectAtEnd: LayerTraceEntrySubject

    // TODO(b/396020056): Verify bubble scenarios in 3-button mode.
    /**
     * Indicates whether the device uses gesture navigation bar or not.
     */
    private val isGesturalNavBar = tapl.navigationModel == NavigationModel.ZERO_BUTTON

    /**
     * Initialize subjects inherited from [FlickerSubject].
     */
@@ -212,36 +217,6 @@ class EnterBubbleViaBubbleMenuTest {

// endregion

// region Generic tests

    /**
     * Verifies there's no flickers among all visible windows.
     *
     * In other words, all visible windows shouldn't be visible -> invisible -> visible in
     * consecutive entries
     */
    @Test
    fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
        wmTraceSubject
            .visibleWindowsShownMoreThanOneConsecutiveEntry()
            .forAllEntries()
    }

    /**
     * Verifies there's no flickers among all visible layers.
     *
     * In other words, all visible layers shouldn't be visible -> invisible -> visible in
     * consecutive entries
     */
    @Test
    fun visibleLayersShownMoreThanOneConsecutiveEntry() {
        layersTraceSubject
            .visibleLayersShownMoreThanOneConsecutiveEntry()
            .forAllEntries()
    }

// endregion

// region App Launch related tests

    /**
@@ -348,6 +323,36 @@ class EnterBubbleViaBubbleMenuTest {

// endregion

// region Generic tests

    /**
     * Verifies there's no flickers among all visible windows.
     *
     * In other words, all visible windows shouldn't be visible -> invisible -> visible in
     * consecutive entries
     */
    @Test
    fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
        wmTraceSubject
            .visibleWindowsShownMoreThanOneConsecutiveEntry()
            .forAllEntries()
    }

    /**
     * Verifies there's no flickers among all visible layers.
     *
     * In other words, all visible layers shouldn't be visible -> invisible -> visible in
     * consecutive entries
     */
    @Test
    fun visibleLayersShownMoreThanOneConsecutiveEntry() {
        layersTraceSubject
            .visibleLayersShownMoreThanOneConsecutiveEntry()
            .forAllEntries()
    }

// endregion

// region System UI related tests

    /**
+64 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.wm.shell.flicker.bubbles

import android.tools.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
import android.tools.io.Reader
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement

/**
 * A [org.junit.ClassRule] to record trace with transition.
 *
 * @sample com.android.wm.shell.flicker.bubbles.samples.RecordTraceWithTransitionRuleSample
 *
 * @property setUpBeforeTransition the function to initialize the environment before transition
 * @property transition the transition to execute
 * @property tearDownAfterTransition the function to clean up after transition
 */
class RecordTraceWithTransitionRule(
    private val setUpBeforeTransition: () -> Unit,
    private val transition: () -> Unit,
    private val tearDownAfterTransition: () -> Unit,
) : TestRule {

    /**
     * The reader to read trace from.
     */
    lateinit var reader: Reader

    override fun apply(base: Statement, description: Description?): Statement {
        return object : Statement() {
            override fun evaluate() {
                recordTraceWithTransition()
                base.evaluate()
            }
        }
    }

    private fun recordTraceWithTransition() {
        try {
            setUpBeforeTransition()
            reader = runTransitionWithTrace { transition() }
            tearDownAfterTransition()
        } finally {
            // In case the crash during transition and test App is not removed.
            removeAllTasksButHome()
        }
    }
}
 No newline at end of file
+43 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.wm.shell.flicker.bubbles.samples
import android.tools.flicker.subject.events.EventLogSubject
import android.tools.flicker.subject.layers.LayersTraceSubject
import android.tools.flicker.subject.wm.WindowManagerTraceSubject
import com.android.wm.shell.flicker.bubbles.RecordTraceWithTransitionRule
import com.android.wm.shell.flicker.bubbles.runTransitionWithTrace

/**
@@ -48,3 +49,44 @@ fun runTransitionWithTraceSample() {
    // Read CUJ Trace
    val cujTrace = reader.readCujTrace()
}

/**
 * Sample to illustrate how to use [RecordTraceWithTransitionRule].
 */
fun RecordTraceWithTransitionRuleSample() {

    // Set as @ClassRule and make it public static
    val rule = RecordTraceWithTransitionRule(
        setUpBeforeTransition = { clearAllTasksAndGoToHomeScreen() },
        transition = { launchActivityViaClickIcon() },
        tearDownAfterTransition = { finishActivity() },
    )

    // In test constructor ...
    val reader = rule.reader

    // Extract [WindowManagerTraceSubject]
    val wmTraceSubject = WindowManagerTraceSubject(
        reader.readWmTrace() ?: error("Failed to read WM trace")
    )

    // Extract [LayerTraceSubject]
    val layersTraceSubject = LayersTraceSubject(
        reader.readLayersTrace() ?: error("Failed to read Layers trace")
    )

    // Extract [EventLogSubject]
    val eventLogSubject = EventLogSubject(
        reader.readEventLogTrace() ?: error("Failed to read event log trace"),
        reader,
    )

    // Read CUJ Trace
    val cujTrace = reader.readCujTrace()
}

private fun clearAllTasksAndGoToHomeScreen() {}

private fun launchActivityViaClickIcon() {}

private fun finishActivity() {}
 No newline at end of file