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

Commit 4b175024 authored by Mike Schneider's avatar Mike Schneider Committed by Android (Google) Code Review
Browse files

Merge "Add jank CUJ instrumentation to DialogLaunchAnimator" into tm-qpr-dev

parents 4c1edb45 9ae58159
Loading
Loading
Loading
Loading
+46 −16
Original line number Diff line number Diff line
@@ -34,6 +34,9 @@ import android.view.WindowInsets
import android.view.WindowManager
import android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
import android.widget.FrameLayout
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.jank.InteractionJankMonitor.Configuration
import com.android.internal.jank.InteractionJankMonitor.CujType
import kotlin.math.roundToInt

private const val TAG = "DialogLaunchAnimator"
@@ -50,6 +53,7 @@ private const val TAG = "DialogLaunchAnimator"
 */
class DialogLaunchAnimator @JvmOverloads constructor(
    private val dreamManager: IDreamManager,
    private val interactionJankMonitor: InteractionJankMonitor,
    private val launchAnimator: LaunchAnimator = LaunchAnimator(TIMINGS, INTERPOLATORS),
    private val isForTesting: Boolean = false
) {
@@ -89,12 +93,14 @@ class DialogLaunchAnimator @JvmOverloads constructor(
    fun showFromView(
        dialog: Dialog,
        view: View,
        animateBackgroundBoundsChange: Boolean = false
        cuj: DialogCuj? = null,
        animateBackgroundBoundsChange: Boolean = false,
    ) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            throw IllegalStateException(
                "showFromView must be called from the main thread and dialog must be created in " +
                    "the main thread")
                    "the main thread"
            )
        }

        // If the view we are launching from belongs to another dialog, then this means the caller
@@ -115,12 +121,14 @@ class DialogLaunchAnimator @JvmOverloads constructor(
        val animatedDialog = AnimatedDialog(
            launchAnimator,
            dreamManager,
            interactionJankMonitor,
            animateFrom,
            onDialogDismissed = { openedDialogs.remove(it) },
            dialog = dialog,
            animateBackgroundBoundsChange,
            animatedParent,
                isForTesting
            isForTesting,
            cuj
        )

        openedDialogs.add(animatedDialog)
@@ -143,8 +151,9 @@ class DialogLaunchAnimator @JvmOverloads constructor(
            ?.dialogContentWithBackground
            ?: throw IllegalStateException(
                "The animateFrom dialog was not animated using " +
                    "DialogLaunchAnimator.showFrom(View|Dialog)")
        showFromView(dialog, view, animateBackgroundBoundsChange)
                    "DialogLaunchAnimator.showFrom(View|Dialog)"
            )
        showFromView(dialog, view, animateBackgroundBoundsChange = animateBackgroundBoundsChange)
    }

    /**
@@ -270,9 +279,17 @@ class DialogLaunchAnimator @JvmOverloads constructor(
    }
}

/**
 * The CUJ interaction associated with opening the dialog.
 *
 * The optional tag indicates the specific dialog being opened.
 */
data class DialogCuj(@CujType val cujType: Int, val tag: String? = null)

private class AnimatedDialog(
    private val launchAnimator: LaunchAnimator,
    private val dreamManager: IDreamManager,
    private val interactionJankMonitor: InteractionJankMonitor,

    /** The view that triggered the dialog after being tapped. */
    var touchSurface: View,
@@ -295,7 +312,10 @@ private class AnimatedDialog(
    /**
     * Whether synchronization should be disabled, which can be useful if we are running in a test.
     */
    private val forceDisableSynchronization: Boolean
    private val forceDisableSynchronization: Boolean,

    /** Interaction to which the dialog animation is associated. */
    private val cuj: DialogCuj? = null
) {
    /**
     * The DecorView of this dialog window.
@@ -346,6 +366,14 @@ private class AnimatedDialog(
    private var decorViewLayoutListener: View.OnLayoutChangeListener? = null

    fun start() {
        if (cuj != null) {
            val config = Configuration.Builder.withView(cuj.cujType, touchSurface)
            if (cuj.tag != null) {
                config.setTag(cuj.tag)
            }
            interactionJankMonitor.begin(config)
        }

        // Create the dialog so that its onCreate() method is called, which usually sets the dialog
        // content.
        dialog.create()
@@ -432,7 +460,8 @@ private class AnimatedDialog(
            decorViewLayoutListener = View.OnLayoutChangeListener {
                    v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
                if (window.attributes.width != MATCH_PARENT ||
                    window.attributes.height != MATCH_PARENT) {
                    window.attributes.height != MATCH_PARENT
                ) {
                    // The dialog size changed, copy its size to dialogContentWithBackground and
                    // make the dialog window full screen again.
                    val layoutParams = dialogContentWithBackground.layoutParams
@@ -606,6 +635,7 @@ private class AnimatedDialog(
                    dialogContentWithBackground!!
                        .addOnLayoutChangeListener(backgroundLayoutListener)
                }
                cuj?.run { interactionJankMonitor.end(cujType) }
            }
        )
    }
+3 −1
Original line number Diff line number Diff line
@@ -175,7 +175,9 @@ public class DndTile extends QSTileImpl<BooleanState> {
                    mUiHandler.post(() -> {
                        Dialog dialog = makeZenModeDialog();
                        if (view != null) {
                            mDialogLaunchAnimator.showFromView(dialog, view, false);
                            mDialogLaunchAnimator.showFromView(dialog, view,
                                    /* cuj= */ null,
                                    /* animateBackgroundBoundsChange= */ false);
                        } else {
                            dialog.show();
                        }
+16 −5
Original line number Diff line number Diff line
@@ -19,7 +19,9 @@ import android.content.Context
import android.os.Handler
import android.util.Log
import android.view.View
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.logging.UiEventLogger
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
@@ -45,6 +47,7 @@ class InternetDialogFactory @Inject constructor(
    private val keyguardStateController: KeyguardStateController
) {
    companion object {
        private const val INTERACTION_JANK_TAG = "internet"
        var internetDialog: InternetDialog? = null
    }

@@ -61,12 +64,20 @@ class InternetDialogFactory @Inject constructor(
            }
            return
        } else {
            internetDialog = InternetDialog(context, this, internetDialogController,
            internetDialog = InternetDialog(
                context, this, internetDialogController,
                canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, handler,
                    executor, keyguardStateController)
                executor, keyguardStateController
            )
            if (view != null) {
                dialogLaunchAnimator.showFromView(internetDialog!!, view,
                    animateBackgroundBoundsChange = true)
                dialogLaunchAnimator.showFromView(
                    internetDialog!!, view,
                    animateBackgroundBoundsChange = true,
                    cuj = DialogCuj(
                        InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
                        INTERACTION_JANK_TAG
                    )
                )
            } else {
                internetDialog?.show()
            }
+4 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.content.Context;
import android.os.Handler;
import android.service.dreams.IDreamManager;

import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.statusbar.IStatusBarService;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.animation.ActivityLaunchAnimator;
@@ -317,7 +318,8 @@ public interface CentralSurfacesDependenciesModule {
     */
    @Provides
    @SysUISingleton
    static DialogLaunchAnimator provideDialogLaunchAnimator(IDreamManager dreamManager) {
        return new DialogLaunchAnimator(dreamManager);
    static DialogLaunchAnimator provideDialogLaunchAnimator(IDreamManager dreamManager,
            InteractionJankMonitor interactionJankMonitor) {
        return new DialogLaunchAnimator(dreamManager, interactionJankMonitor);
    }
}
+27 −3
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.WindowManager
import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.policy.DecorView
import com.android.systemui.SysuiTestCase
import junit.framework.Assert.assertEquals
@@ -29,6 +30,8 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.any
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit

@SmallTest
@@ -40,12 +43,14 @@ class DialogLaunchAnimatorTest : SysuiTestCase() {
    private val attachedViews = mutableSetOf<View>()

    @Mock lateinit var dreamManager: IDreamManager
    @Mock lateinit var interactionJankMonitor: InteractionJankMonitor
    @get:Rule val rule = MockitoJUnit.rule()

    @Before
    fun setUp() {
        dialogLaunchAnimator = DialogLaunchAnimator(
            dreamManager, launchAnimator, isForTesting = true)
            dreamManager, interactionJankMonitor, launchAnimator, isForTesting = true
        )
    }

    @After
@@ -90,7 +95,8 @@ class DialogLaunchAnimatorTest : SysuiTestCase() {

        // The dialog content is inside this fake window view.
        assertNotNull(
            dialogContentWithBackground.findViewByPredicate { it === dialog.contentView })
            dialogContentWithBackground.findViewByPredicate { it === dialog.contentView }
        )

        // Clicking the transparent background should dismiss the dialog.
        runOnMainThreadAndWaitForIdleSync {
@@ -161,6 +167,24 @@ class DialogLaunchAnimatorTest : SysuiTestCase() {
        assertNotEquals(0, dialog.window.attributes.windowAnimations)
    }

    @Test
    fun testCujSpecificationLogsInteraction() {
        val touchSurface = createTouchSurface()
        return runOnMainThreadAndWaitForIdleSync {
            val dialog = TestDialog(context)
            dialogLaunchAnimator.showFromView(
                dialog, touchSurface,
                cuj = DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN)
            )
        }

        verify(interactionJankMonitor).begin(
            any()
        )
        verify(interactionJankMonitor)
            .end(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN)
    }

    private fun createAndShowDialog(): TestDialog {
        val touchSurface = createTouchSurface()
        return runOnMainThreadAndWaitForIdleSync {
Loading