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

Commit 3dfd9e6c authored by An An Yu's avatar An An Yu Committed by Android (Google) Code Review
Browse files

Merge "Remove clip adjustment to fix bottom screen flicker issue. Add a...

Merge "Remove clip adjustment to fix bottom screen flicker issue. Add a flicker test to verify animation background is no longer visible through the transition after the fix." into udc-qpr-dev
parents 6168c6ee b540a9af
Loading
Loading
Loading
Loading
+2 −15
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ class ActivityEmbeddingAnimationAdapter {
    final SurfaceControl mLeash;
    /** Area in absolute coordinate that the animation surface shouldn't go beyond. */
    @NonNull
    private final Rect mWholeAnimationBounds = new Rect();
    final Rect mWholeAnimationBounds = new Rect();
    /**
     * Area in absolute coordinate that should represent all the content to show for this window.
     * This should be the end bounds for opening window, and start bounds for closing window in case
@@ -229,20 +229,7 @@ class ActivityEmbeddingAnimationAdapter {
            mTransformation.getMatrix().postTranslate(mContentRelOffset.x, mContentRelOffset.y);
            t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix);
            t.setAlpha(mLeash, mTransformation.getAlpha());

            // The following applies an inverse scale to the clip-rect so that it crops "after" the
            // scale instead of before.
            mVecs[1] = mVecs[2] = 0;
            mVecs[0] = mVecs[3] = 1;
            mTransformation.getMatrix().mapVectors(mVecs);
            mVecs[0] = 1.f / mVecs[0];
            mVecs[3] = 1.f / mVecs[3];
            final Rect clipRect = mTransformation.getClipRect();
            mRect.left = (int) (clipRect.left * mVecs[0] + 0.5f);
            mRect.right = (int) (clipRect.right * mVecs[0] + 0.5f);
            mRect.top = (int) (clipRect.top * mVecs[3] + 0.5f);
            mRect.bottom = (int) (clipRect.bottom * mVecs[3] + 0.5f);
            t.setCrop(mLeash, mRect);
            t.setWindowCrop(mLeash, mWholeAnimationBounds.width(), mWholeAnimationBounds.height());
        }
    }
}
+0 −9
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.ClipRectAnimation;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.ScaleAnimation;
@@ -189,14 +188,6 @@ class ActivityEmbeddingAnimationSpec {
                startBounds.top - endBounds.top, 0);
        endTranslate.setDuration(CHANGE_ANIMATION_DURATION);
        endSet.addAnimation(endTranslate);
        // The end leash is resizing, we should update the window crop based on the clip rect.
        final Rect startClip = new Rect(startBounds);
        final Rect endClip = new Rect(endBounds);
        startClip.offsetTo(0, 0);
        endClip.offsetTo(0, 0);
        final Animation clipAnim = new ClipRectAnimation(startClip, endClip);
        clipAnim.setDuration(CHANGE_ANIMATION_DURATION);
        endSet.addAnimation(clipAnim);
        endSet.initialize(startBounds.width(), startBounds.height(), parentBounds.width(),
                parentBounds.height());
        endSet.scaleCurrentDuration(mTransitionAnimationScaleSetting);
+13 −0
Original line number Diff line number Diff line
@@ -17,9 +17,12 @@
package com.android.server.wm.flicker.activityembedding

import android.tools.device.flicker.legacy.LegacyFlickerTest
import android.platform.test.annotations.Presubmit
import android.tools.common.traces.component.ComponentNameMatcher
import com.android.server.wm.flicker.BaseTest
import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
import org.junit.Before
import org.junit.Test

abstract class ActivityEmbeddingTestBase(flicker: LegacyFlickerTest) : BaseTest(flicker) {
    val testApp = ActivityEmbeddingAppHelper(instrumentation)
@@ -29,4 +32,14 @@ abstract class ActivityEmbeddingTestBase(flicker: LegacyFlickerTest) : BaseTest(
        // The test should only be run on devices that support ActivityEmbedding.
        ActivityEmbeddingAppHelper.assumeActivityEmbeddingSupportedDevice()
    }

    /** Asserts the background animation layer is never visible during bounds change transition. */
    @Presubmit
    @Test
    fun backgroundLayerNeverVisible() {
        val backgroundColorLayer = ComponentNameMatcher("", "Animation Background")
        flicker.assertLayers {
            isInvisible(backgroundColorLayer)
        }
    }
}
+152 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.activityembedding

import android.platform.test.annotations.Presubmit
import android.tools.common.datatypes.Rect
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.LegacyFlickerTest
import android.tools.device.flicker.legacy.LegacyFlickerTestFactory
import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
import androidx.test.filters.RequiresDevice
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized

/**
 * Test changing split ratio at runtime on a horizona split.
 *
 * Setup: Launch A|B in horizontal split with B being the secondary activity, by default A and B
 * windows are equal in size. B is on the top and A is on the bottom.
 * Transitions:
 * Change the split ratio to A:B=0.7:0.3, expect bounds change for both A and B.
 *
 * To run this test: `atest FlickerTests:HorizontalSplitChangeRatioTest`
 */
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class HorizontalSplitChangeRatioTest(flicker: LegacyFlickerTest) :
        ActivityEmbeddingTestBase(flicker) {
    /** {@inheritDoc} */
    override val transition: FlickerBuilder.() -> Unit = {
        setup {
            tapl.setExpectedRotationCheckEnabled(false)
            testApp.launchViaIntent(wmHelper)
            testApp.launchSecondaryActivityHorizontally(wmHelper)
            startDisplayBounds =
                    wmHelper.currentState.layerState.physicalDisplayBounds
                            ?: error("Display not found")
        }
        transitions {
            testApp.changeSecondaryActivityRatio(wmHelper)
        }
        teardown {
            tapl.goHome()
            testApp.exit(wmHelper)
        }
    }

    /** Assert the Main activity window is always visible. */
    @Presubmit
    @Test
    fun mainActivityWindowIsAlwaysVisible() {
        flicker.assertWm { isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) }
    }

    /** Assert the Main activity window is always visible. */
    @Presubmit
    @Test
    fun mainActivityLayerIsAlwaysVisible() {
        flicker.assertLayers { isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) }
    }

    /** Assert the Secondary activity window is always visible. */
    @Presubmit
    @Test
    fun secondaryActivityWindowIsAlwaysVisible() {
        flicker.assertWm {
            isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) }
    }

    /** Assert the Secondary activity window is always visible. */
    @Presubmit
    @Test
    fun secondaryActivityLayerIsAlwaysVisible() {
        flicker.assertLayers { isVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) }
    }

    /** Assert the Main and Secondary activity change height during the transition. */
    @Presubmit
    @Test
    fun secondaryActivityAdjustsHeightRuntime() {
        flicker.assertLayersStart {
            val topLayerRegion =
                    this.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
            val bottomLayerRegion =
                    this.visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
            // Compare dimensions of two splits, given we're using default split attributes,
            // both activities take up the same visible size on the display.
            check { "height" }
                    .that(topLayerRegion.region.height).isEqual(bottomLayerRegion.region.height)
            check { "width" }
                    .that(topLayerRegion.region.width).isEqual(bottomLayerRegion.region.width)
            topLayerRegion.notOverlaps(bottomLayerRegion.region)
            // Layers of two activities sum to be fullscreen size on display.
            topLayerRegion.plus(bottomLayerRegion.region).coversExactly(startDisplayBounds)
        }

        flicker.assertLayersEnd {
            val topLayerRegion =
                    this.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
            val bottomLayerRegion =
                    this.visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
            // Compare dimensions of two splits, given we're using default split attributes,
            // both activities take up the same visible size on the display.
            check { "height" }
                    .that(topLayerRegion.region.height).isLower(bottomLayerRegion.region.height)
            check { "height" }
                    .that(
                            topLayerRegion.region.height / 0.3f -
                                    bottomLayerRegion.region.height / 0.7f)
                    .isLower(0.1f)
            check { "width" }
                    .that(topLayerRegion.region.width).isEqual(bottomLayerRegion.region.width)
            topLayerRegion.notOverlaps(bottomLayerRegion.region)
            // Layers of two activities sum to be fullscreen size on display.
            topLayerRegion.plus(bottomLayerRegion.region).coversExactly(startDisplayBounds)
        }
    }

    companion object {
        /** {@inheritDoc} */
        private var startDisplayBounds = Rect.EMPTY
        /**
         * Creates the test configurations.
         *
         * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and
         * navigation modes.
         */
        @Parameterized.Parameters(name = "{0}")
        @JvmStatic
        fun getParams() = LegacyFlickerTestFactory.nonRotationTests()
    }
}
 No newline at end of file
+0 −8
Original line number Diff line number Diff line
@@ -142,14 +142,6 @@ class OpenThirdActivityOverSplitTest(flicker: LegacyFlickerTest) :
        }
    }

    /** Assert the background animation layer is never visible during transition. */
    @Presubmit
    @Test
    fun backgroundLayerNeverVisible() {
        val backgroundColorLayer = ComponentNameMatcher("", "Animation Background")
        flicker.assertLayers { isInvisible(backgroundColorLayer) }
    }

    companion object {
        /** {@inheritDoc} */
        private var startDisplayBounds = Rect.EMPTY
Loading